1 | var elliptic = require('elliptic')
|
2 | var BN = require('bn.js')
|
3 |
|
4 | module.exports = function createECDH (curve) {
|
5 | return new ECDH(curve)
|
6 | }
|
7 |
|
8 | var aliases = {
|
9 | secp256k1: {
|
10 | name: 'secp256k1',
|
11 | byteLength: 32
|
12 | },
|
13 | secp224r1: {
|
14 | name: 'p224',
|
15 | byteLength: 28
|
16 | },
|
17 | prime256v1: {
|
18 | name: 'p256',
|
19 | byteLength: 32
|
20 | },
|
21 | prime192v1: {
|
22 | name: 'p192',
|
23 | byteLength: 24
|
24 | },
|
25 | ed25519: {
|
26 | name: 'ed25519',
|
27 | byteLength: 32
|
28 | },
|
29 | secp384r1: {
|
30 | name: 'p384',
|
31 | byteLength: 48
|
32 | },
|
33 | secp521r1: {
|
34 | name: 'p521',
|
35 | byteLength: 66
|
36 | }
|
37 | }
|
38 |
|
39 | aliases.p224 = aliases.secp224r1
|
40 | aliases.p256 = aliases.secp256r1 = aliases.prime256v1
|
41 | aliases.p192 = aliases.secp192r1 = aliases.prime192v1
|
42 | aliases.p384 = aliases.secp384r1
|
43 | aliases.p521 = aliases.secp521r1
|
44 |
|
45 | function ECDH (curve) {
|
46 | this.curveType = aliases[curve]
|
47 | if (!this.curveType) {
|
48 | this.curveType = {
|
49 | name: curve
|
50 | }
|
51 | }
|
52 | this.curve = new elliptic.ec(this.curveType.name)
|
53 | this.keys = void 0
|
54 | }
|
55 |
|
56 | ECDH.prototype.generateKeys = function (enc, format) {
|
57 | this.keys = this.curve.genKeyPair()
|
58 | return this.getPublicKey(enc, format)
|
59 | }
|
60 |
|
61 | ECDH.prototype.computeSecret = function (other, inenc, enc) {
|
62 | inenc = inenc || 'utf8'
|
63 | if (!Buffer.isBuffer(other)) {
|
64 | other = new Buffer(other, inenc)
|
65 | }
|
66 | var otherPub = this.curve.keyFromPublic(other).getPublic()
|
67 | var out = otherPub.mul(this.keys.getPrivate()).getX()
|
68 | return formatReturnValue(out, enc, this.curveType.byteLength)
|
69 | }
|
70 |
|
71 | ECDH.prototype.getPublicKey = function (enc, format) {
|
72 | var key = this.keys.getPublic(format === 'compressed', true)
|
73 | if (format === 'hybrid') {
|
74 | if (key[key.length - 1] % 2) {
|
75 | key[0] = 7
|
76 | } else {
|
77 | key[0] = 6
|
78 | }
|
79 | }
|
80 | return formatReturnValue(key, enc)
|
81 | }
|
82 |
|
83 | ECDH.prototype.getPrivateKey = function (enc) {
|
84 | return formatReturnValue(this.keys.getPrivate(), enc)
|
85 | }
|
86 |
|
87 | ECDH.prototype.setPublicKey = function (pub, enc) {
|
88 | enc = enc || 'utf8'
|
89 | if (!Buffer.isBuffer(pub)) {
|
90 | pub = new Buffer(pub, enc)
|
91 | }
|
92 | this.keys._importPublic(pub)
|
93 | return this
|
94 | }
|
95 |
|
96 | ECDH.prototype.setPrivateKey = function (priv, enc) {
|
97 | enc = enc || 'utf8'
|
98 | if (!Buffer.isBuffer(priv)) {
|
99 | priv = new Buffer(priv, enc)
|
100 | }
|
101 |
|
102 | var _priv = new BN(priv)
|
103 | _priv = _priv.toString(16)
|
104 | this.keys = this.curve.genKeyPair()
|
105 | this.keys._importPrivate(_priv)
|
106 | return this
|
107 | }
|
108 |
|
109 | function formatReturnValue (bn, enc, len) {
|
110 | if (!Array.isArray(bn)) {
|
111 | bn = bn.toArray()
|
112 | }
|
113 | var buf = new Buffer(bn)
|
114 | if (len && buf.length < len) {
|
115 | var zeros = new Buffer(len - buf.length)
|
116 | zeros.fill(0)
|
117 | buf = Buffer.concat([zeros, buf])
|
118 | }
|
119 | if (!enc) {
|
120 | return buf
|
121 | } else {
|
122 | return buf.toString(enc)
|
123 | }
|
124 | }
|