123 lines
2.5 KiB
JavaScript
123 lines
2.5 KiB
JavaScript
var elliptic = require('elliptic');
|
|
var BN = require('bn.js');
|
|
|
|
module.exports = function createECDH(curve) {
|
|
return new ECDH(curve);
|
|
};
|
|
|
|
var aliases = {
|
|
secp256k1: {
|
|
name: 'secp256k1',
|
|
byteLength: 32
|
|
},
|
|
secp224r1: {
|
|
name: 'p224',
|
|
byteLength: 28
|
|
},
|
|
prime256v1: {
|
|
name: 'p256',
|
|
byteLength: 32
|
|
},
|
|
prime192v1: {
|
|
name: 'p192',
|
|
byteLength: 24
|
|
},
|
|
ed25519: {
|
|
name: 'ed25519',
|
|
byteLength: 32
|
|
},
|
|
secp384r1: {
|
|
name: 'p384',
|
|
byteLength: 48
|
|
},
|
|
secp521r1: {
|
|
name: 'p521',
|
|
byteLength: 66
|
|
}
|
|
};
|
|
|
|
aliases.p224 = aliases.secp224r1;
|
|
aliases.p256 = aliases.secp256r1 = aliases.prime256v1;
|
|
aliases.p192 = aliases.secp192r1 = aliases.prime192v1;
|
|
aliases.p384 = aliases.secp384r1;
|
|
aliases.p521 = aliases.secp521r1;
|
|
|
|
function ECDH(curve) {
|
|
this.curveType = aliases[curve];
|
|
if (!this.curveType ) {
|
|
this.curveType = {
|
|
name: curve
|
|
};
|
|
}
|
|
this.curve = new elliptic.ec(this.curveType.name);
|
|
this.keys = void 0;
|
|
}
|
|
|
|
ECDH.prototype.generateKeys = function (enc, format) {
|
|
this.keys = this.curve.genKeyPair();
|
|
return this.getPublicKey(enc, format);
|
|
};
|
|
|
|
ECDH.prototype.computeSecret = function (other, inenc, enc) {
|
|
inenc = inenc || 'utf8';
|
|
if (!Buffer.isBuffer(other)) {
|
|
other = new Buffer(other, inenc);
|
|
}
|
|
var otherPub = this.curve.keyFromPublic(other).getPublic();
|
|
var out = otherPub.mul(this.keys.getPrivate()).getX();
|
|
return formatReturnValue(out, enc, this.curveType.byteLength);
|
|
};
|
|
|
|
ECDH.prototype.getPublicKey = function (enc, format) {
|
|
var key = this.keys.getPublic(format === 'compressed', true);
|
|
if (format === 'hybrid') {
|
|
if (key[key.length - 1] % 2) {
|
|
key[0] = 7;
|
|
} else {
|
|
key [0] = 6;
|
|
}
|
|
}
|
|
return formatReturnValue(key, enc);
|
|
};
|
|
|
|
ECDH.prototype.getPrivateKey = function (enc) {
|
|
return formatReturnValue(this.keys.getPrivate(), enc);
|
|
};
|
|
|
|
ECDH.prototype.setPublicKey = function (pub, enc) {
|
|
enc = enc || 'utf8';
|
|
if (!Buffer.isBuffer(pub)) {
|
|
pub = new Buffer(pub, enc);
|
|
}
|
|
this.keys._importPublic(pub);
|
|
return this;
|
|
};
|
|
|
|
ECDH.prototype.setPrivateKey = function (priv, enc) {
|
|
enc = enc || 'utf8';
|
|
if (!Buffer.isBuffer(priv)) {
|
|
priv = new Buffer(priv, enc);
|
|
}
|
|
var _priv = new BN(priv);
|
|
_priv = _priv.toString(16);
|
|
this.keys._importPrivate(_priv);
|
|
return this;
|
|
};
|
|
|
|
function formatReturnValue(bn, enc, len) {
|
|
if (!Array.isArray(bn)) {
|
|
bn = bn.toArray();
|
|
}
|
|
var buf = new Buffer(bn);
|
|
if (len && buf.length < len) {
|
|
var zeros = new Buffer(len - buf.length);
|
|
zeros.fill(0);
|
|
buf = Buffer.concat([zeros, buf]);
|
|
}
|
|
if (!enc) {
|
|
return buf;
|
|
} else {
|
|
return buf.toString(enc);
|
|
}
|
|
}
|