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
|