indutny/elliptic
GitHub: indutny/elliptic
纯 JavaScript 实现的高性能椭圆曲线密码学库,支持 ECDSA、EdDSA 签名和 ECDH 密钥交换。
Stars: 1764 | Forks: 508
# Elliptic [](http://travis-ci.org/indutny/elliptic) [](https://coveralls.io/github/indutny/elliptic?branch=master) [](https://codeclimate.com/github/indutny/elliptic)
[](https://saucelabs.com/u/gh-indutny-elliptic)
纯 JavaScript 实现的快速椭圆曲线密码学。
注意:在为你的密码学操作选择曲线之前,请查看 http://safecurves.cr.yp.to/
## 动机
ECC 比普通的 RSA 密码学慢得多,而 JS 的实现甚至更慢。
## 基准测试
```
$ node benchmarks/index.js
Benchmarking: sign
elliptic#sign x 262 ops/sec ±0.51% (177 runs sampled)
eccjs#sign x 55.91 ops/sec ±0.90% (144 runs sampled)
------------------------
Fastest is elliptic#sign
========================
Benchmarking: verify
elliptic#verify x 113 ops/sec ±0.50% (166 runs sampled)
eccjs#verify x 48.56 ops/sec ±0.36% (125 runs sampled)
------------------------
Fastest is elliptic#verify
========================
Benchmarking: gen
elliptic#gen x 294 ops/sec ±0.43% (176 runs sampled)
eccjs#gen x 62.25 ops/sec ±0.63% (129 runs sampled)
------------------------
Fastest is elliptic#gen
========================
Benchmarking: ecdh
elliptic#ecdh x 136 ops/sec ±0.85% (156 runs sampled)
------------------------
Fastest is elliptic#ecdh
========================
```
## API
### ECDSA
```
var EC = require('elliptic').ec;
// Create and initialize EC context
// (better do it once and reuse it)
var ec = new EC('secp256k1');
// Generate keys
var key = ec.genKeyPair();
// Sign the message's hash (input must be an array, or a hex-string)
var msgHash = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
var signature = key.sign(msgHash);
// Export DER encoded signature in Array
var derSign = signature.toDER();
// Verify signature
console.log(key.verify(msgHash, derSign));
// CHECK WITH NO PRIVATE KEY
var pubPoint = key.getPublic();
var x = pubPoint.getX();
var y = pubPoint.getY();
// Public Key MUST be either:
// 1) '04' + hex string of x + hex string of y; or
// 2) object with two hex string properties (x and y); or
// 3) object with two buffer properties (x and y)
var pub = pubPoint.encode('hex'); // case 1
var pub = { x: x.toString('hex'), y: y.toString('hex') }; // case 2
var pub = { x: x.toBuffer(), y: y.toBuffer() }; // case 3
var pub = { x: x.toArrayLike(Buffer), y: y.toArrayLike(Buffer) }; // case 3
// Import public key
var key = ec.keyFromPublic(pub, 'hex');
// Signature MUST be either:
// 1) DER-encoded signature as hex-string; or
// 2) DER-encoded signature as buffer; or
// 3) object with two hex-string properties (r and s); or
// 4) object with two buffer properties (r and s)
var signature = '3046022100...'; // case 1
var signature = new Buffer('...'); // case 2
var signature = { r: 'b1fc...', s: '9c42...' }; // case 3
// Verify signature
console.log(key.verify(msgHash, signature));
```
### EdDSA
```
var EdDSA = require('elliptic').eddsa;
// Create and initialize EdDSA context
// (better do it once and reuse it)
var ec = new EdDSA('ed25519');
// Create key pair from secret
var key = ec.keyFromSecret('693e3c...'); // hex string, array or Buffer
// Sign the message's hash (input must be an array, or a hex-string)
var msgHash = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
var signature = key.sign(msgHash).toHex();
// Verify signature
console.log(key.verify(msgHash, signature));
// CHECK WITH NO PRIVATE KEY
// Import public key
var pub = '0a1af638...';
var key = ec.keyFromPublic(pub, 'hex');
// Verify signature
var signature = '70bed1...';
console.log(key.verify(msgHash, signature));
```
### ECDH
```
var EC = require('elliptic').ec;
var ec = new EC('curve25519');
// Generate keys
var key1 = ec.genKeyPair();
var key2 = ec.genKeyPair();
var shared1 = key1.derive(key2.getPublic());
var shared2 = key2.derive(key1.getPublic());
console.log('Both shared secrets are BN instances');
console.log(shared1.toString(16));
console.log(shared2.toString(16));
```
三个及更多成员:
```
var EC = require('elliptic').ec;
var ec = new EC('curve25519');
var A = ec.genKeyPair();
var B = ec.genKeyPair();
var C = ec.genKeyPair();
var AB = A.getPublic().mul(B.getPrivate())
var BC = B.getPublic().mul(C.getPrivate())
var CA = C.getPublic().mul(A.getPrivate())
var ABC = AB.mul(C.getPrivate())
var BCA = BC.mul(A.getPrivate())
var CAB = CA.mul(B.getPrivate())
console.log(ABC.getX().toString(16))
console.log(BCA.getX().toString(16))
console.log(CAB.getX().toString(16))
```
注意:`.derive()` 返回一个 [BN][1] 实例。
## 支持的曲线
Elliptic.js 支持以下曲线类型:
* Short Weierstrass
* Montgomery
* Edwards
* Twisted Edwards
以下曲线“预设”已内置于库中:
* `secp256k1`
* `p192`
* `p224`
* `p256`
* `p384`
* `p521`
* `curve25519`
* `ed25519`
注意:`curve25519` 不能用于 ECDSA,请改用 `ed25519`。
### 实现细节
ECDSA 使用符合 [RFC6979][0] 的确定性 `k` 值生成。大多数曲线操作在非仿射坐标(投射坐标或扩展坐标)上执行,针对不同情况使用了各种窗口技术。
所有操作均使用 [bn.js][1] 在归约上下文中执行,哈希由 [hash.js][2] 提供。
### 相关项目
* [eccrypto][3]:ECDSA、ECDH 和 ECIES 的同构实现,适用于 browserify 和 node(浏览器端使用 `elliptic`,node 端使用 [secp256k1-node][4])
#### 许可证
本软件基于 MIT 许可证授权。
Copyright Fedor Indutny, 2014.
特此免费授予任何获得本软件副本和相关文档文件(“软件”)的人不受限制地处置该软件的权利,包括不受限制地使用、复制、修改、合并、发布、分发、再授权和/或销售软件副本的权利,以及再授权给配备了这些软件的人的权利,但须满足以下条件:
上述版权声明和本许可声明应包含在该软件的所有副本或实质性成分中。
本软件按“原样”提供,不提供任何形式的担保,无论是明示或暗示的,包括但不限于适销性、特定用途适用性和非侵权性的担保。在任何情况下,作者或版权持有人均不对任何索赔、损害或其他责任负责,无论是在合同诉讼、侵权行为还是其他方面,由软件或软件的使用或其他交易引起、与之相关或与之相关联。
标签:CMS安全, CVE, ECC, ECDH, ECDSA, EdDSA, GNU通用公共许可证, JavaScript, meg, MITM代理, Node.js, secp256k1, Web加密, 信息安全, 加密库, 区块链基础, 密码学, 密钥交换, 手动系统调用, 数字签名, 数据可视化, 椭圆曲线加密, 纯JS实现, 自定义脚本, 自定义脚本