| 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) // eslint-disable-line new-cap | |
| 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 = this.curve.genKeyPair() | |
| 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) | |
| } | |
| } |