Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
80621 views
1
'use strict';
2
3
var bn = require('bn.js');
4
5
var elliptic = require('../../elliptic');
6
var utils = elliptic.utils;
7
8
function KeyPair(ec, options) {
9
this.ec = ec;
10
this.priv = null;
11
this.pub = null;
12
13
// KeyPair(ec, { priv: ..., pub: ... })
14
if (options.priv)
15
this._importPrivate(options.priv, options.privEnc);
16
if (options.pub)
17
this._importPublic(options.pub, options.pubEnc);
18
}
19
module.exports = KeyPair;
20
21
KeyPair.fromPublic = function fromPublic(ec, pub, enc) {
22
if (pub instanceof KeyPair)
23
return pub;
24
25
return new KeyPair(ec, {
26
pub: pub,
27
pubEnc: enc
28
});
29
};
30
31
KeyPair.fromPrivate = function fromPrivate(ec, priv, enc) {
32
if (priv instanceof KeyPair)
33
return priv;
34
35
return new KeyPair(ec, {
36
priv: priv,
37
privEnc: enc
38
});
39
};
40
41
KeyPair.prototype.validate = function validate() {
42
var pub = this.getPublic();
43
44
if (pub.isInfinity())
45
return { result: false, reason: 'Invalid public key' };
46
if (!pub.validate())
47
return { result: false, reason: 'Public key is not a point' };
48
if (!pub.mul(this.ec.curve.n).isInfinity())
49
return { result: false, reason: 'Public key * N != O' };
50
51
return { result: true, reason: null };
52
};
53
54
KeyPair.prototype.getPublic = function getPublic(compact, enc) {
55
if (!this.pub)
56
this.pub = this.ec.g.mul(this.priv);
57
58
// compact is optional argument
59
if (typeof compact === 'string') {
60
enc = compact;
61
compact = null;
62
}
63
64
if (!enc)
65
return this.pub;
66
67
var len = this.ec.curve.p.byteLength();
68
var x = this.pub.getX().toArray();
69
70
for (var i = x.length; i < len; i++)
71
x.unshift(0);
72
73
var res;
74
if (this.ec.curve.type !== 'mont') {
75
if (compact) {
76
res = [ this.pub.getY().isEven() ? 0x02 : 0x03 ].concat(x);
77
} else {
78
var y = this.pub.getY().toArray();
79
for (var i = y.length; i < len; i++)
80
y.unshift(0);
81
var res = [ 0x04 ].concat(x, y);
82
}
83
} else {
84
res = x;
85
}
86
87
return utils.encode(res, enc);
88
};
89
90
KeyPair.prototype.getPrivate = function getPrivate(enc) {
91
if (enc === 'hex')
92
return this.priv.toString(16, 2);
93
else
94
return this.priv;
95
};
96
97
KeyPair.prototype._importPrivate = function _importPrivate(key, enc) {
98
this.priv = new bn(key, enc || 16);
99
100
// Ensure that the priv won't be bigger than n, otherwise we may fail
101
// in fixed multiplication method
102
this.priv = this.priv.mod(this.ec.curve.n);
103
};
104
105
KeyPair.prototype._importPublic = function _importPublic(key, enc) {
106
if (key.x || key.y) {
107
this.pub = this.ec.curve.point(key.x, key.y);
108
return;
109
}
110
111
key = utils.toArray(key, enc);
112
if (this.ec.curve.type !== 'mont')
113
return this._importPublicShort(key);
114
else
115
return this._importPublicMont(key);
116
};
117
118
KeyPair.prototype._importPublicShort = function _importPublicShort(key) {
119
var len = this.ec.curve.p.byteLength();
120
if (key[0] === 0x04 && key.length - 1 === 2 * len) {
121
this.pub = this.ec.curve.point(
122
key.slice(1, 1 + len),
123
key.slice(1 + len, 1 + 2 * len));
124
} else if ((key[0] === 0x02 || key[0] === 0x03) && key.length - 1 === len) {
125
this.pub = this.ec.curve.pointFromX(key[0] === 0x03, key.slice(1, 1 + len));
126
}
127
};
128
129
KeyPair.prototype._importPublicMont = function _importPublicMont(key) {
130
this.pub = this.ec.curve.point(key, 1);
131
};
132
133
// ECDH
134
KeyPair.prototype.derive = function derive(pub) {
135
return pub.mul(this.priv).getX();
136
};
137
138
// ECDSA
139
KeyPair.prototype.sign = function sign(msg) {
140
return this.ec.sign(msg, this);
141
};
142
143
KeyPair.prototype.verify = function verify(msg, signature) {
144
return this.ec.verify(msg, signature, this);
145
};
146
147
KeyPair.prototype.inspect = function inspect() {
148
return '<Key priv: ' + (this.priv && this.priv.toString(16, 2)) +
149
' pub: ' + (this.pub && this.pub.inspect()) + ' >';
150
};
151
152