Projekt

Obecné

Profil

Stáhnout (3.79 KB) Statistiky
| Větev: | Revize:
1
var BN = require('bn.js');
2
var MillerRabin = require('miller-rabin');
3
var millerRabin = new MillerRabin();
4
var TWENTYFOUR = new BN(24);
5
var ELEVEN = new BN(11);
6
var TEN = new BN(10);
7
var THREE = new BN(3);
8
var SEVEN = new BN(7);
9
var primes = require('./generatePrime');
10
var randomBytes = require('randombytes');
11
module.exports = DH;
12

    
13
function setPublicKey(pub, enc) {
14
  enc = enc || 'utf8';
15
  if (!Buffer.isBuffer(pub)) {
16
    pub = new Buffer(pub, enc);
17
  }
18
  this._pub = new BN(pub);
19
  return this;
20
}
21

    
22
function setPrivateKey(priv, enc) {
23
  enc = enc || 'utf8';
24
  if (!Buffer.isBuffer(priv)) {
25
    priv = new Buffer(priv, enc);
26
  }
27
  this._priv = new BN(priv);
28
  return this;
29
}
30

    
31
var primeCache = {};
32
function checkPrime(prime, generator) {
33
  var gen = generator.toString('hex');
34
  var hex = [gen, prime.toString(16)].join('_');
35
  if (hex in primeCache) {
36
    return primeCache[hex];
37
  }
38
  var error = 0;
39

    
40
  if (prime.isEven() ||
41
    !primes.simpleSieve ||
42
    !primes.fermatTest(prime) ||
43
    !millerRabin.test(prime)) {
44
    //not a prime so +1
45
    error += 1;
46

    
47
    if (gen === '02' || gen === '05') {
48
      // we'd be able to check the generator
49
      // it would fail so +8
50
      error += 8;
51
    } else {
52
      //we wouldn't be able to test the generator
53
      // so +4
54
      error += 4;
55
    }
56
    primeCache[hex] = error;
57
    return error;
58
  }
59
  if (!millerRabin.test(prime.shrn(1))) {
60
    //not a safe prime
61
    error += 2;
62
  }
63
  var rem;
64
  switch (gen) {
65
    case '02':
66
      if (prime.mod(TWENTYFOUR).cmp(ELEVEN)) {
67
        // unsuidable generator
68
        error += 8;
69
      }
70
      break;
71
    case '05':
72
      rem = prime.mod(TEN);
73
      if (rem.cmp(THREE) && rem.cmp(SEVEN)) {
74
        // prime mod 10 needs to equal 3 or 7
75
        error += 8;
76
      }
77
      break;
78
    default:
79
      error += 4;
80
  }
81
  primeCache[hex] = error;
82
  return error;
83
}
84

    
85
function DH(prime, generator, malleable) {
86
  this.setGenerator(generator);
87
  this.__prime = new BN(prime);
88
  this._prime = BN.mont(this.__prime);
89
  this._primeLen = prime.length;
90
  this._pub = undefined;
91
  this._priv = undefined;
92
  this._primeCode = undefined;
93
  if (malleable) {
94
    this.setPublicKey = setPublicKey;
95
    this.setPrivateKey = setPrivateKey;
96
  } else {
97
    this._primeCode = 8;
98
  }
99
}
100
Object.defineProperty(DH.prototype, 'verifyError', {
101
  enumerable: true,
102
  get: function () {
103
    if (typeof this._primeCode !== 'number') {
104
      this._primeCode = checkPrime(this.__prime, this.__gen);
105
    }
106
    return this._primeCode;
107
  }
108
});
109
DH.prototype.generateKeys = function () {
110
  if (!this._priv) {
111
    this._priv = new BN(randomBytes(this._primeLen));
112
  }
113
  this._pub = this._gen.toRed(this._prime).redPow(this._priv).fromRed();
114
  return this.getPublicKey();
115
};
116

    
117
DH.prototype.computeSecret = function (other) {
118
  other = new BN(other);
119
  other = other.toRed(this._prime);
120
  var secret = other.redPow(this._priv).fromRed();
121
  var out = new Buffer(secret.toArray());
122
  var prime = this.getPrime();
123
  if (out.length < prime.length) {
124
    var front = new Buffer(prime.length - out.length);
125
    front.fill(0);
126
    out = Buffer.concat([front, out]);
127
  }
128
  return out;
129
};
130

    
131
DH.prototype.getPublicKey = function getPublicKey(enc) {
132
  return formatReturnValue(this._pub, enc);
133
};
134

    
135
DH.prototype.getPrivateKey = function getPrivateKey(enc) {
136
  return formatReturnValue(this._priv, enc);
137
};
138

    
139
DH.prototype.getPrime = function (enc) {
140
  return formatReturnValue(this.__prime, enc);
141
};
142

    
143
DH.prototype.getGenerator = function (enc) {
144
  return formatReturnValue(this._gen, enc);
145
};
146

    
147
DH.prototype.setGenerator = function (gen, enc) {
148
  enc = enc || 'utf8';
149
  if (!Buffer.isBuffer(gen)) {
150
    gen = new Buffer(gen, enc);
151
  }
152
  this.__gen = gen;
153
  this._gen = new BN(gen);
154
  return this;
155
};
156

    
157
function formatReturnValue(bn, enc) {
158
  var buf = new Buffer(bn.toArray());
159
  if (!enc) {
160
    return buf;
161
  } else {
162
    return buf.toString(enc);
163
  }
164
}
(1-1/3)