1
|
# Elliptic [![Build Status](https://secure.travis-ci.org/indutny/elliptic.png)](http://travis-ci.org/indutny/elliptic) [![Coverage Status](https://coveralls.io/repos/indutny/elliptic/badge.svg?branch=master&service=github)](https://coveralls.io/github/indutny/elliptic?branch=master) [![Code Climate](https://codeclimate.com/github/indutny/elliptic/badges/gpa.svg)](https://codeclimate.com/github/indutny/elliptic)
|
2
|
|
3
|
[![Saucelabs Test Status](https://saucelabs.com/browser-matrix/gh-indutny-elliptic.svg)](https://saucelabs.com/u/gh-indutny-elliptic)
|
4
|
|
5
|
Fast elliptic-curve cryptography in a plain javascript implementation.
|
6
|
|
7
|
NOTE: Please take a look at http://safecurves.cr.yp.to/ before choosing a curve
|
8
|
for your cryptography operations.
|
9
|
|
10
|
## Incentive
|
11
|
|
12
|
ECC is much slower than regular RSA cryptography, the JS implementations are
|
13
|
even more slower.
|
14
|
|
15
|
## Benchmarks
|
16
|
|
17
|
```bash
|
18
|
$ node benchmarks/index.js
|
19
|
Benchmarking: sign
|
20
|
elliptic#sign x 262 ops/sec ±0.51% (177 runs sampled)
|
21
|
eccjs#sign x 55.91 ops/sec ±0.90% (144 runs sampled)
|
22
|
------------------------
|
23
|
Fastest is elliptic#sign
|
24
|
========================
|
25
|
Benchmarking: verify
|
26
|
elliptic#verify x 113 ops/sec ±0.50% (166 runs sampled)
|
27
|
eccjs#verify x 48.56 ops/sec ±0.36% (125 runs sampled)
|
28
|
------------------------
|
29
|
Fastest is elliptic#verify
|
30
|
========================
|
31
|
Benchmarking: gen
|
32
|
elliptic#gen x 294 ops/sec ±0.43% (176 runs sampled)
|
33
|
eccjs#gen x 62.25 ops/sec ±0.63% (129 runs sampled)
|
34
|
------------------------
|
35
|
Fastest is elliptic#gen
|
36
|
========================
|
37
|
Benchmarking: ecdh
|
38
|
elliptic#ecdh x 136 ops/sec ±0.85% (156 runs sampled)
|
39
|
------------------------
|
40
|
Fastest is elliptic#ecdh
|
41
|
========================
|
42
|
```
|
43
|
|
44
|
## API
|
45
|
|
46
|
### ECDSA
|
47
|
|
48
|
```javascript
|
49
|
var EC = require('elliptic').ec;
|
50
|
|
51
|
// Create and initialize EC context
|
52
|
// (better do it once and reuse it)
|
53
|
var ec = new EC('secp256k1');
|
54
|
|
55
|
// Generate keys
|
56
|
var key = ec.genKeyPair();
|
57
|
|
58
|
// Sign the message's hash (input must be an array, or a hex-string)
|
59
|
var msgHash = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
|
60
|
var signature = key.sign(msgHash);
|
61
|
|
62
|
// Export DER encoded signature in Array
|
63
|
var derSign = signature.toDER();
|
64
|
|
65
|
// Verify signature
|
66
|
console.log(key.verify(msgHash, derSign));
|
67
|
|
68
|
// CHECK WITH NO PRIVATE KEY
|
69
|
|
70
|
var pubPoint = key.getPublic();
|
71
|
var x = pubPoint.getX();
|
72
|
var y = pubPoint.getY();
|
73
|
|
74
|
// Public Key MUST be either:
|
75
|
// 1) '04' + hex string of x + hex string of y; or
|
76
|
// 2) object with two hex string properties (x and y); or
|
77
|
// 3) object with two buffer properties (x and y)
|
78
|
var pub = pubPoint.encode('hex'); // case 1
|
79
|
var pub = { x: x.toString('hex'), y: y.toString('hex') }; // case 2
|
80
|
var pub = { x: x.toBuffer(), y: y.toBuffer() }; // case 3
|
81
|
var pub = { x: x.toArrayLike(Buffer), y: y.toArrayLike(Buffer) }; // case 3
|
82
|
|
83
|
// Import public key
|
84
|
var key = ec.keyFromPublic(pub, 'hex');
|
85
|
|
86
|
// Signature MUST be either:
|
87
|
// 1) DER-encoded signature as hex-string; or
|
88
|
// 2) DER-encoded signature as buffer; or
|
89
|
// 3) object with two hex-string properties (r and s); or
|
90
|
// 4) object with two buffer properties (r and s)
|
91
|
|
92
|
var signature = '3046022100...'; // case 1
|
93
|
var signature = new Buffer('...'); // case 2
|
94
|
var signature = { r: 'b1fc...', s: '9c42...' }; // case 3
|
95
|
|
96
|
// Verify signature
|
97
|
console.log(key.verify(msgHash, signature));
|
98
|
```
|
99
|
|
100
|
### EdDSA
|
101
|
|
102
|
```javascript
|
103
|
var EdDSA = require('elliptic').eddsa;
|
104
|
|
105
|
// Create and initialize EdDSA context
|
106
|
// (better do it once and reuse it)
|
107
|
var ec = new EdDSA('ed25519');
|
108
|
|
109
|
// Create key pair from secret
|
110
|
var key = ec.keyFromSecret('693e3c...'); // hex string, array or Buffer
|
111
|
|
112
|
// Sign the message's hash (input must be an array, or a hex-string)
|
113
|
var msgHash = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
|
114
|
var signature = key.sign(msgHash).toHex();
|
115
|
|
116
|
// Verify signature
|
117
|
console.log(key.verify(msgHash, signature));
|
118
|
|
119
|
// CHECK WITH NO PRIVATE KEY
|
120
|
|
121
|
// Import public key
|
122
|
var pub = '0a1af638...';
|
123
|
var key = ec.keyFromPublic(pub, 'hex');
|
124
|
|
125
|
// Verify signature
|
126
|
var signature = '70bed1...';
|
127
|
console.log(key.verify(msgHash, signature));
|
128
|
```
|
129
|
|
130
|
### ECDH
|
131
|
|
132
|
```javascript
|
133
|
var EC = require('elliptic').ec;
|
134
|
var ec = new EC('curve25519');
|
135
|
|
136
|
// Generate keys
|
137
|
var key1 = ec.genKeyPair();
|
138
|
var key2 = ec.genKeyPair();
|
139
|
|
140
|
var shared1 = key1.derive(key2.getPublic());
|
141
|
var shared2 = key2.derive(key1.getPublic());
|
142
|
|
143
|
console.log('Both shared secrets are BN instances');
|
144
|
console.log(shared1.toString(16));
|
145
|
console.log(shared2.toString(16));
|
146
|
```
|
147
|
|
148
|
three and more members:
|
149
|
```javascript
|
150
|
var EC = require('elliptic').ec;
|
151
|
var ec = new EC('curve25519');
|
152
|
|
153
|
var A = ec.genKeyPair();
|
154
|
var B = ec.genKeyPair();
|
155
|
var C = ec.genKeyPair();
|
156
|
|
157
|
var AB = A.getPublic().mul(B.getPrivate())
|
158
|
var BC = B.getPublic().mul(C.getPrivate())
|
159
|
var CA = C.getPublic().mul(A.getPrivate())
|
160
|
|
161
|
var ABC = AB.mul(C.getPrivate())
|
162
|
var BCA = BC.mul(A.getPrivate())
|
163
|
var CAB = CA.mul(B.getPrivate())
|
164
|
|
165
|
console.log(ABC.getX().toString(16))
|
166
|
console.log(BCA.getX().toString(16))
|
167
|
console.log(CAB.getX().toString(16))
|
168
|
```
|
169
|
|
170
|
NOTE: `.derive()` returns a [BN][1] instance.
|
171
|
|
172
|
## Supported curves
|
173
|
|
174
|
Elliptic.js support following curve types:
|
175
|
|
176
|
* Short Weierstrass
|
177
|
* Montgomery
|
178
|
* Edwards
|
179
|
* Twisted Edwards
|
180
|
|
181
|
Following curve 'presets' are embedded into the library:
|
182
|
|
183
|
* `secp256k1`
|
184
|
* `p192`
|
185
|
* `p224`
|
186
|
* `p256`
|
187
|
* `p384`
|
188
|
* `p521`
|
189
|
* `curve25519`
|
190
|
* `ed25519`
|
191
|
|
192
|
NOTE: That `curve25519` could not be used for ECDSA, use `ed25519` instead.
|
193
|
|
194
|
### Implementation details
|
195
|
|
196
|
ECDSA is using deterministic `k` value generation as per [RFC6979][0]. Most of
|
197
|
the curve operations are performed on non-affine coordinates (either projective
|
198
|
or extended), various windowing techniques are used for different cases.
|
199
|
|
200
|
All operations are performed in reduction context using [bn.js][1], hashing is
|
201
|
provided by [hash.js][2]
|
202
|
|
203
|
### Related projects
|
204
|
|
205
|
* [eccrypto][3]: isomorphic implementation of ECDSA, ECDH and ECIES for both
|
206
|
browserify and node (uses `elliptic` for browser and [secp256k1-node][4] for
|
207
|
node)
|
208
|
|
209
|
#### LICENSE
|
210
|
|
211
|
This software is licensed under the MIT License.
|
212
|
|
213
|
Copyright Fedor Indutny, 2014.
|
214
|
|
215
|
Permission is hereby granted, free of charge, to any person obtaining a
|
216
|
copy of this software and associated documentation files (the
|
217
|
"Software"), to deal in the Software without restriction, including
|
218
|
without limitation the rights to use, copy, modify, merge, publish,
|
219
|
distribute, sublicense, and/or sell copies of the Software, and to permit
|
220
|
persons to whom the Software is furnished to do so, subject to the
|
221
|
following conditions:
|
222
|
|
223
|
The above copyright notice and this permission notice shall be included
|
224
|
in all copies or substantial portions of the Software.
|
225
|
|
226
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
227
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
228
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
229
|
NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
230
|
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
231
|
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
232
|
USE OR OTHER DEALINGS IN THE SOFTWARE.
|
233
|
|
234
|
[0]: http://tools.ietf.org/html/rfc6979
|
235
|
[1]: https://github.com/indutny/bn.js
|
236
|
[2]: https://github.com/indutny/hash.js
|
237
|
[3]: https://github.com/bitchan/eccrypto
|
238
|
[4]: https://github.com/wanderer/secp256k1-node
|