mirror of
https://github.com/fluencelabs/js-libp2p-crypto
synced 2025-07-18 21:22:09 +00:00
Compare commits
144 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
934390acd3 | ||
|
8b80b46667 | ||
|
e8efad546f | ||
|
e8cbf13d85 | ||
|
c7e0409c1c | ||
|
f4c00893ad | ||
|
b05e77f375 | ||
|
ad478454d8 | ||
|
8c69ffb20f | ||
|
e689a402a3 | ||
|
4bd032a6ae | ||
|
50c61ba46e | ||
|
3a90f70350 | ||
|
743c69524c | ||
|
1a347fa04c | ||
|
71339e08e7 | ||
|
0ab2c2d2d6 | ||
|
cdcca5f828 | ||
|
2c0dc706b7 | ||
|
21d4c8b74e | ||
|
285b6ca392 | ||
|
7d96dd3243 | ||
|
b3421284f9 | ||
|
f3cb8ced36 | ||
|
0a6f63dce5 | ||
|
0ce5f34a08 | ||
|
a826968e71 | ||
|
7608fdd858 | ||
|
bf9b532067 | ||
|
5296f8a42f | ||
|
3a91ae2ed8 | ||
|
e7c11a8e01 | ||
|
9bb96dc2bf | ||
|
957fdd37e9 | ||
|
83257bc4bd | ||
|
cb7fae7fcc | ||
|
7669847c17 | ||
|
dc2793f138 | ||
|
e0b916ace9 | ||
|
0a71af7b89 | ||
|
46adafb207 | ||
|
9e977c7d44 | ||
|
f20267b962 | ||
|
1b6a070fa8 | ||
|
1471e07bf9 | ||
|
bc554d1407 | ||
|
83d2d52205 | ||
|
301c779f49 | ||
|
d552fd423a | ||
|
306504c386 | ||
|
bf80e8e511 | ||
|
4e619e60f5 | ||
|
a958f52a5c | ||
|
dfc476c4f6 | ||
|
71eb33a44f | ||
|
310733726e | ||
|
0efc94bd20 | ||
|
68f4b5f496 | ||
|
2f8e234044 | ||
|
c2c6fde394 | ||
|
14dde32177 | ||
|
5bc30297de | ||
|
a5ad8cf444 | ||
|
be64372a5e | ||
|
2b0b7abd78 | ||
|
17f2065d21 | ||
|
2f065167fa | ||
|
e0ecce18ce | ||
|
cea1140ec6 | ||
|
e5b7c1f622 | ||
|
20326199d9 | ||
|
4e56e1724f | ||
|
7d63f698c0 | ||
|
a49df7786c | ||
|
c73adb00cc | ||
|
8a95de4700 | ||
|
c35a65133f | ||
|
4eb4aa05de | ||
|
21f96a4eb7 | ||
|
39b5124526 | ||
|
93e50dde10 | ||
|
e383da5d44 | ||
|
9b687f380c | ||
|
82abede64a | ||
|
a56ab406e4 | ||
|
d753941c6e | ||
|
6022eb0838 | ||
|
1c6d0912cd | ||
|
e18804c31e | ||
|
133a2c8833 | ||
|
fad0865b2b | ||
|
4edef07182 | ||
|
19c6ce7c06 | ||
|
3fa76a874f | ||
|
6e0fd6f257 | ||
|
c91d9b61c8 | ||
|
76eeb5aa18 | ||
|
843b5e33d6 | ||
|
308ac7cd1a | ||
|
6c8f978ea4 | ||
|
b93b410357 | ||
|
99a5245fa3 | ||
|
34856d58ab | ||
|
d59c6af7c0 | ||
|
1683bf1dc8 | ||
|
a4edf8b99b | ||
|
27524354af | ||
|
a1f054ca8e | ||
|
5c61c89391 | ||
|
c138a04d2d | ||
|
7c913c0769 | ||
|
1a2d468369 | ||
|
98bc0bbc5f | ||
|
c45bdf602e | ||
|
e92bab1736 | ||
|
c57d1e4d4f | ||
|
04682acd86 | ||
|
fba4833aef | ||
|
2842df7944 | ||
|
74c0d28f86 | ||
|
cf7ed6fa49 | ||
|
c1ffa41697 | ||
|
933119445f | ||
|
a4e6f9dd83 | ||
|
e252db300c | ||
|
98b37d49c4 | ||
|
f979fcd3c2 | ||
|
0af48bbebc | ||
|
3f9d8d557c | ||
|
91a3b50ac9 | ||
|
148d16ab25 | ||
|
6d15450438 | ||
|
ebe1cecdeb | ||
|
904cfb27bd | ||
|
7790beb207 | ||
|
6308461f0f | ||
|
95a0f1f0c2 | ||
|
0c64122342 | ||
|
ce5044b4d7 | ||
|
1daf429a74 | ||
|
22e95bc8a4 | ||
|
9994023490 | ||
|
393fa17512 | ||
|
3cc26d167f |
1
.eslintignore
Normal file
1
.eslintignore
Normal file
@@ -0,0 +1 @@
|
|||||||
|
src/keys/keys.proto.js
|
13
.gitignore
vendored
13
.gitignore
vendored
@@ -1,6 +1,11 @@
|
|||||||
|
docs
|
||||||
|
package-lock.json
|
||||||
|
yarn.lock
|
||||||
|
|
||||||
**/node_modules/
|
**/node_modules/
|
||||||
**/*.log
|
**/*.log
|
||||||
test/repo-tests*
|
test/repo-tests*
|
||||||
|
**/bundle.js
|
||||||
|
|
||||||
# Logs
|
# Logs
|
||||||
logs
|
logs
|
||||||
@@ -31,4 +36,12 @@ build
|
|||||||
# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
|
# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
|
||||||
node_modules
|
node_modules
|
||||||
|
|
||||||
|
lib
|
||||||
dist
|
dist
|
||||||
|
test/test-data/go-ipfs-repo/LOCK
|
||||||
|
test/test-data/go-ipfs-repo/LOG
|
||||||
|
test/test-data/go-ipfs-repo/LOG.old
|
||||||
|
|
||||||
|
# while testing npm5
|
||||||
|
package-lock.json
|
||||||
|
yarn.lock
|
||||||
|
18
.travis.yml
18
.travis.yml
@@ -1,27 +1,21 @@
|
|||||||
|
# Warning: This file is automatically synced from https://github.com/ipfs/ci-sync so if you want to change it, please change it there and ask someone to sync all repositories.
|
||||||
sudo: false
|
sudo: false
|
||||||
language: node_js
|
language: node_js
|
||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- node_js: 4
|
|
||||||
env: CXX=g++-4.8
|
|
||||||
- node_js: 6
|
- node_js: 6
|
||||||
env:
|
|
||||||
- SAUCE=true
|
|
||||||
- CXX=g++-4.8
|
|
||||||
- node_js: stable
|
|
||||||
env: CXX=g++-4.8
|
env: CXX=g++-4.8
|
||||||
|
- node_js: 8
|
||||||
# Make sure we have new NPM.
|
env: CXX=g++-4.8
|
||||||
before_install:
|
# - node_js: stable
|
||||||
- npm install -g npm
|
# env: CXX=g++-4.8
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- npm run lint
|
- npm run lint
|
||||||
- npm test
|
- npm run test
|
||||||
- npm run coverage
|
- npm run coverage
|
||||||
|
|
||||||
|
|
||||||
before_script:
|
before_script:
|
||||||
- export DISPLAY=:99.0
|
- export DISPLAY=:99.0
|
||||||
- sh -e /etc/init.d/xvfb start
|
- sh -e /etc/init.d/xvfb start
|
||||||
|
162
CHANGELOG.md
Normal file
162
CHANGELOG.md
Normal file
@@ -0,0 +1,162 @@
|
|||||||
|
<a name="0.14.0"></a>
|
||||||
|
# [0.14.0](https://github.com/libp2p/js-libp2p-crypto/compare/v0.13.0...v0.14.0) (2018-09-17)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* windows build ([c7e0409](https://github.com/libp2p/js-libp2p-crypto/commit/c7e0409))
|
||||||
|
* **lint:** use ~ for ursa-optional version ([e8cbf13](https://github.com/libp2p/js-libp2p-crypto/commit/e8cbf13))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* use ursa-optional for lightning fast key generation ([b05e77f](https://github.com/libp2p/js-libp2p-crypto/commit/b05e77f))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.13.0"></a>
|
||||||
|
# [0.13.0](https://github.com/libp2p/js-libp2p-crypto/compare/v0.12.1...v0.13.0) (2018-04-05)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.12.1"></a>
|
||||||
|
## [0.12.1](https://github.com/libp2p/js-libp2p-crypto/compare/v0.12.0...v0.12.1) (2018-02-12)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.12.0"></a>
|
||||||
|
# [0.12.0](https://github.com/libp2p/js-libp2p-crypto/compare/v0.11.0...v0.12.0) (2018-01-27)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* improve perf ([#117](https://github.com/libp2p/js-libp2p-crypto/issues/117)) ([cdcca5f](https://github.com/libp2p/js-libp2p-crypto/commit/cdcca5f))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.11.0"></a>
|
||||||
|
# [0.11.0](https://github.com/libp2p/js-libp2p-crypto/compare/v0.10.4...v0.11.0) (2017-12-20)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* key exchange with jsrsasign ([#115](https://github.com/libp2p/js-libp2p-crypto/issues/115)) ([b342128](https://github.com/libp2p/js-libp2p-crypto/commit/b342128))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.10.4"></a>
|
||||||
|
## [0.10.4](https://github.com/libp2p/js-libp2p-crypto/compare/v0.10.3...v0.10.4) (2017-12-01)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* catch error when unmarshaling instead of crashing ([#113](https://github.com/libp2p/js-libp2p-crypto/issues/113)) ([7608fdd](https://github.com/libp2p/js-libp2p-crypto/commit/7608fdd))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.10.3"></a>
|
||||||
|
## [0.10.3](https://github.com/libp2p/js-libp2p-crypto/compare/v0.10.2...v0.10.3) (2017-09-07)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* switch protocol-buffers to protons ([#110](https://github.com/libp2p/js-libp2p-crypto/issues/110)) ([3a91ae2](https://github.com/libp2p/js-libp2p-crypto/commit/3a91ae2))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.10.2"></a>
|
||||||
|
## [0.10.2](https://github.com/libp2p/js-libp2p-crypto/compare/v0.10.1...v0.10.2) (2017-09-06)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* use regular protocol-buffers until protobufjs is fixed ([#109](https://github.com/libp2p/js-libp2p-crypto/issues/109)) ([957fdd3](https://github.com/libp2p/js-libp2p-crypto/commit/957fdd3))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **deps:** upgrade to aegir@12 and browserify-aes@1.0.8 ([83257bc](https://github.com/libp2p/js-libp2p-crypto/commit/83257bc))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.10.1"></a>
|
||||||
|
## [0.10.1](https://github.com/libp2p/js-libp2p-crypto/compare/v0.10.0...v0.10.1) (2017-09-05)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* switch to protobufjs ([#107](https://github.com/libp2p/js-libp2p-crypto/issues/107)) ([dc2793f](https://github.com/libp2p/js-libp2p-crypto/commit/dc2793f))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.10.0"></a>
|
||||||
|
# [0.10.0](https://github.com/libp2p/js-libp2p-crypto/compare/v0.9.4...v0.10.0) (2017-09-03)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* p2p addrs situation ([#106](https://github.com/libp2p/js-libp2p-crypto/issues/106)) ([9e977c7](https://github.com/libp2p/js-libp2p-crypto/commit/9e977c7))
|
||||||
|
* skip nextTick in nodeify ([#103](https://github.com/libp2p/js-libp2p-crypto/issues/103)) ([f20267b](https://github.com/libp2p/js-libp2p-crypto/commit/f20267b))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.9.4"></a>
|
||||||
|
## [0.9.4](https://github.com/libp2p/js-libp2p-crypto/compare/v0.9.3...v0.9.4) (2017-07-22)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* circular circular dep -> DI ([bc554d1](https://github.com/libp2p/js-libp2p-crypto/commit/bc554d1))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.9.3"></a>
|
||||||
|
## [0.9.3](https://github.com/libp2p/js-libp2p-crypto/compare/v0.9.2...v0.9.3) (2017-07-22)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.9.2"></a>
|
||||||
|
## [0.9.2](https://github.com/libp2p/js-libp2p-crypto/compare/v0.9.1...v0.9.2) (2017-07-22)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.9.1"></a>
|
||||||
|
## [0.9.1](https://github.com/libp2p/js-libp2p-crypto/compare/v0.9.0...v0.9.1) (2017-07-22)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.9.0"></a>
|
||||||
|
# [0.9.0](https://github.com/libp2p/js-libp2p-crypto/compare/v0.8.8...v0.9.0) (2017-07-22)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.8.8"></a>
|
||||||
|
## [0.8.8](https://github.com/libp2p/js-libp2p-crypto/compare/v0.8.7...v0.8.8) (2017-04-11)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **ecdh:** allow base64 to be left-0-padded, needed for JWK format ([be64372](https://github.com/libp2p/js-libp2p-crypto/commit/be64372)), closes [#97](https://github.com/libp2p/js-libp2p-crypto/issues/97)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.8.7"></a>
|
||||||
|
## [0.8.7](https://github.com/libp2p/js-libp2p-crypto/compare/v0.8.6...v0.8.7) (2017-03-21)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.8.6"></a>
|
||||||
|
## [0.8.6](https://github.com/libp2p/js-libp2p-crypto/compare/v0.8.5...v0.8.6) (2017-03-03)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **package:** update tweetnacl to version 1.0.0-rc.1 ([4e56e17](https://github.com/libp2p/js-libp2p-crypto/commit/4e56e17))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **keys:** implement generateKeyPairFromSeed for ed25519 ([e5b7c1f](https://github.com/libp2p/js-libp2p-crypto/commit/e5b7c1f))
|
||||||
|
|
||||||
|
|
||||||
|
|
211
README.md
211
README.md
@@ -10,38 +10,37 @@
|
|||||||
[](https://david-dm.org/libp2p/js-libp2p-crypto)
|
[](https://david-dm.org/libp2p/js-libp2p-crypto)
|
||||||
[](https://github.com/feross/standard)
|
[](https://github.com/feross/standard)
|
||||||

|

|
||||||

|

|
||||||
|
|
||||||
[](https://saucelabs.com/u/ipfs-js-
|
|
||||||
libp2p-crypto)
|
|
||||||
|
|
||||||
> Crypto primitives for libp2p in JavaScript
|
> Crypto primitives for libp2p in JavaScript
|
||||||
|
|
||||||
This repo contains the JavaScript implementation of the crypto primitives
|
This repo contains the JavaScript implementation of the crypto primitives needed for libp2p. This is based on this [go implementation](https://github.com/libp2p/go-libp2p-crypto).
|
||||||
needed for libp2p. This is based on this [go implementation](https://github.com/libp2p/go-libp2p-crypto).
|
|
||||||
|
## Lead Maintainer
|
||||||
|
|
||||||
|
[Friedel Ziegelmayer](https://github.com/dignifiedquire/)
|
||||||
|
|
||||||
## Table of Contents
|
## Table of Contents
|
||||||
|
|
||||||
- [Install](#install)
|
- [Install](#install)
|
||||||
- [Usage](#usage)
|
|
||||||
- [Example](#example)
|
|
||||||
- [API](#api)
|
- [API](#api)
|
||||||
- [`hmac`](#hmac)
|
- [`crypto.hmac`](#hmac)
|
||||||
- [`create(hash, secret, callback)`](#createhash-secret-callback)
|
- [`create(hash, secret, callback)`](#createhash-secret-callback)
|
||||||
- [`digest(data, callback)`](#digestdata-callback)
|
- [`digest(data, callback)`](#digestdata-callback)
|
||||||
- [`aes`](#aes)
|
- [`crypto.aes`](#aes)
|
||||||
- [`create(key, iv, callback)`](#createkey-iv-callback)
|
- [`create(key, iv, callback)`](#createkey-iv-callback)
|
||||||
- [`encrypt(data, callback)`](#encryptdata-callback)
|
- [`encrypt(data, callback)`](#encryptdata-callback)
|
||||||
- [`encrypt(data, callback)`](#encryptdata-callback)
|
- [`decrypt(data, callback)`](#decryptdata-callback)
|
||||||
- [`webcrypto`](#webcrypto)
|
|
||||||
- [`keys`](#keys)
|
- [`keys`](#keys)
|
||||||
- [`generateKeyPair(type, bits, callback)`](#generatekeypairtype-bits-callback)
|
- [`generateKeyPair(type, bits, callback)`](#generatekeypairtype-bits-callback)
|
||||||
- [`generateEphemeralKeyPair(curve, callback)`](#generateephemeralkeypaircurve-callback)
|
- [`generateEphemeralKeyPair(curve, callback)`](#generateephemeralkeypaircurve-callback)
|
||||||
- [`keyStretcher(cipherType, hashType, secret, callback)`](#keystretcherciphertype-hashtype-secret-callback)
|
- [`keyStretcher(cipherType, hashType, secret, callback)`](#keystretcherciphertype-hashtype-secret-callback)
|
||||||
- [`marshalPublicKey(key[, type], callback)`](#marshalpublickeykey-type-callback)
|
- [`marshalPublicKey(key[, type], callback)`](#marshalpublickeykey-type-callback)
|
||||||
- [`unmarshalPublicKey(buf)`](#unmarshalpublickeybuf)
|
- [`unmarshalPublicKey(buf)`](#unmarshalpublickeybuf)
|
||||||
- [`marshalPrivateKey(key[, type])`](#marshalprivatekeykey-type)
|
- [`marshalPrivateKey(key[, type])`](#marshalprivatekeykey-type)
|
||||||
- [`unmarshalPrivateKey(buf, callback)`](#unmarshalprivatekeybuf-callback)
|
- [`unmarshalPrivateKey(buf, callback)`](#unmarshalprivatekeybuf-callback)
|
||||||
|
- [`import(pem, password, callback)`](#importpem-password-callback)
|
||||||
|
- [`webcrypto`](#webcrypto)
|
||||||
- [Contribute](#contribute)
|
- [Contribute](#contribute)
|
||||||
- [License](#license)
|
- [License](#license)
|
||||||
|
|
||||||
@@ -51,24 +50,82 @@ needed for libp2p. This is based on this [go implementation](https://github.com/
|
|||||||
npm install --save libp2p-crypto
|
npm install --save libp2p-crypto
|
||||||
```
|
```
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
### Example
|
|
||||||
|
|
||||||
```js
|
|
||||||
const crypto = require('libp2p-crypto')
|
|
||||||
|
|
||||||
crypto.generateKeyPair('RSA', 2048, (err, key) => {
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
## API
|
## API
|
||||||
|
|
||||||
### `hmac`
|
### `crypto.aes`
|
||||||
|
|
||||||
|
Expoes an interface to AES encryption (formerly Rijndael), as defined in U.S. Federal Information Processing Standards Publication 197.
|
||||||
|
|
||||||
|
This uses `CTR` mode.
|
||||||
|
|
||||||
|
#### `crypto.aes.create(key, iv, callback)`
|
||||||
|
|
||||||
|
- `key: Buffer` The key, if length `16` then `AES 128` is used. For length `32`, `AES 256` is used.
|
||||||
|
- `iv: Buffer` Must have length `16`.
|
||||||
|
- `callback: Function`
|
||||||
|
|
||||||
|
##### `decrypt(data, callback)`
|
||||||
|
|
||||||
|
- `data: Buffer`
|
||||||
|
- `callback: Function`
|
||||||
|
|
||||||
|
##### `encrypt(data, callback)`
|
||||||
|
|
||||||
|
- `data: Buffer`
|
||||||
|
- `callback: Function`
|
||||||
|
|
||||||
|
```js
|
||||||
|
var crypto = require('libp2p-crypto')
|
||||||
|
|
||||||
|
// Setting up Key and IV
|
||||||
|
|
||||||
|
// A 16 bytes array, 128 Bits, AES-128 is chosen
|
||||||
|
var key128 = Buffer.from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15])
|
||||||
|
|
||||||
|
// A 16 bytes array, 128 Bits,
|
||||||
|
var IV = Buffer.from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15])
|
||||||
|
|
||||||
|
async function main () {
|
||||||
|
let decryptedMessage = 'Hello, world!'
|
||||||
|
let encryptedMessage
|
||||||
|
|
||||||
|
// Encrypting
|
||||||
|
await crypto.aes.create(key128, IV, (err, cipher) => {
|
||||||
|
if (!err) {
|
||||||
|
cipher.encrypt(Buffer.from(decryptedMessage), (err, encryptedBuffer) => {
|
||||||
|
if (!err) {
|
||||||
|
console.log(encryptedBuffer)
|
||||||
|
// prints: <Buffer 42 f1 67 d9 2e 42 d0 32 9e b1 f8 3c>
|
||||||
|
encryptedMessage = encryptedBuffer
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Decrypting
|
||||||
|
await crypto.aes.create(key128, IV, (err, cipher) => {
|
||||||
|
if (!err) {
|
||||||
|
cipher.decrypt(encryptedMessage, (err, decryptedBuffer) => {
|
||||||
|
if (!err) {
|
||||||
|
console.log(decryptedBuffer)
|
||||||
|
// prints: <Buffer 42 f1 67 d9 2e 42 d0 32 9e b1 f8 3c>
|
||||||
|
|
||||||
|
console.log(decryptedBuffer.toString('utf-8'))
|
||||||
|
// prints: Hello, world!
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
main()
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### `crypto.hmac`
|
||||||
|
|
||||||
Exposes an interface to the Keyed-Hash Message Authentication Code (HMAC) as defined in U.S. Federal Information Processing Standards Publication 198. An HMAC is a cryptographic hash that uses a key to sign a message. The receiver verifies the hash by recomputing it using the same key.
|
Exposes an interface to the Keyed-Hash Message Authentication Code (HMAC) as defined in U.S. Federal Information Processing Standards Publication 198. An HMAC is a cryptographic hash that uses a key to sign a message. The receiver verifies the hash by recomputing it using the same key.
|
||||||
|
|
||||||
#### `create(hash, secret, callback)`
|
#### `crypto.hmac.create(hash, secret, callback)`
|
||||||
|
|
||||||
- `hash: String`
|
- `hash: String`
|
||||||
- `secret: Buffer`
|
- `secret: Buffer`
|
||||||
@@ -79,43 +136,43 @@ Exposes an interface to the Keyed-Hash Message Authentication Code (HMAC) as def
|
|||||||
- `data: Buffer`
|
- `data: Buffer`
|
||||||
- `callback: Function`
|
- `callback: Function`
|
||||||
|
|
||||||
### `aes`
|
Example:
|
||||||
Expoes an interface to AES encryption (formerly Rijndael), as defined in U.S. Federal Information Processing Standards Publication 197.
|
|
||||||
|
|
||||||
This uses `CTR` mode.
|
```js
|
||||||
|
var crypto = require('libp2p-crypto')
|
||||||
|
|
||||||
#### `create(key, iv, callback)`
|
let hash = 'SHA1' // 'SHA256' || 'SHA512'
|
||||||
|
|
||||||
- `key: Buffer` The key, if length `16` then `AES 128` is used. For length `32`, `AES 256` is used.
|
crypto.hmac.create(hash, Buffer.from('secret'), (err, hmac) => {
|
||||||
- `iv: Buffer` Must have length `16`.
|
if (!err) {
|
||||||
- `callback: Function`
|
hmac.digest(Buffer.from('hello world'), (err, sig) => {
|
||||||
|
if (!err) {
|
||||||
|
console.log(sig)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
##### `encrypt(data, callback)`
|
### `crypto.keys`
|
||||||
|
|
||||||
- `data: Buffer`
|
**Supported Key Types**
|
||||||
- `callback: Function`
|
|
||||||
|
|
||||||
##### `encrypt(data, callback)`
|
The [`generateKeyPair`](#generatekeypairtype-bits-callback), [`marshalPublicKey`](#marshalpublickeykey-type-callback), and [`marshalPrivateKey`](#marshalprivatekeykey-type) functions accept a string `type` argument.
|
||||||
|
|
||||||
- `data: Buffer`
|
Currently the `'RSA'` and `'ed25519'` types are supported, although ed25519 keys support only signing and verification of messages. For encryption / decryption support, RSA keys should be used.
|
||||||
- `callback: Function`
|
|
||||||
|
|
||||||
|
Installing the [libp2p-crypto-secp256k1](https://github.com/libp2p/js-libp2p-crypto-secp256k1) module adds support for the `'secp256k1'` type, which supports ECDSA signatures using the secp256k1 elliptic curve popularized by Bitcoin. This module is not installed by default, and should be explicitly depended on if your project requires secp256k1 support.
|
||||||
|
|
||||||
### `webcrypto`
|
### `crypto.keys.generateKeyPair(type, bits, callback)`
|
||||||
|
|
||||||
Depending on the environment this is either an instance of [node-webcrypto-ossl](https://github.com/PeculiarVentures/node-webcrypto-ossl) or the result of `window.crypto`.
|
- `type: String`, see [Supported Key Types](#supported-key-types) above.
|
||||||
|
|
||||||
### `keys`
|
|
||||||
|
|
||||||
### `generateKeyPair(type, bits, callback)`
|
|
||||||
|
|
||||||
- `type: String`, only `'RSA'` is currently supported
|
|
||||||
- `bits: Number` Minimum of 1024
|
- `bits: Number` Minimum of 1024
|
||||||
- `callback: Function`
|
- `callback: Function`
|
||||||
|
|
||||||
Generates a keypair of the given type and bitsize.
|
Generates a keypair of the given type and bitsize.
|
||||||
|
|
||||||
### `generateEphemeralKeyPair(curve, callback)`
|
### `crypto.keys.generateEphemeralKeyPair(curve, callback)`
|
||||||
|
|
||||||
- `curve: String`, one of `'P-256'`, `'P-384'`, `'P-521'` is currently supported
|
- `curve: String`, one of `'P-256'`, `'P-384'`, `'P-521'` is currently supported
|
||||||
- `callback: Function`
|
- `callback: Function`
|
||||||
@@ -133,7 +190,7 @@ Calls back with an object of the form
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### `keyStretcher(cipherType, hashType, secret, callback)`
|
### `crypto.keys.keyStretcher(cipherType, hashType, secret, callback)`
|
||||||
|
|
||||||
- `cipherType: String`, one of `'AES-128'`, `'AES-256'`, `'Blowfish'`
|
- `cipherType: String`, one of `'AES-128'`, `'AES-256'`, `'Blowfish'`
|
||||||
- `hashType: String`, one of `'SHA1'`, `SHA256`, `SHA512`
|
- `hashType: String`, one of `'SHA1'`, `SHA256`, `SHA512`
|
||||||
@@ -142,7 +199,8 @@ Calls back with an object of the form
|
|||||||
|
|
||||||
Generates a set of keys for each party by stretching the shared key.
|
Generates a set of keys for each party by stretching the shared key.
|
||||||
|
|
||||||
Calls back with an object of the form
|
Calls back with an object of the form:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
{
|
{
|
||||||
k1: {
|
k1: {
|
||||||
@@ -158,33 +216,56 @@ Calls back with an object of the form
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### `marshalPublicKey(key[, type], callback)`
|
### `crypto.keys.marshalPublicKey(key[, type], callback)`
|
||||||
|
|
||||||
- `key: crypto.rsa.RsaPublicKey`
|
- `key: keys.rsa.RsaPublicKey | keys.ed25519.Ed25519PublicKey | require('libp2p-crypto-secp256k1').Secp256k1PublicKey`
|
||||||
- `type: String`, only `'RSA'` is currently supported
|
- `type: String`, see [Supported Key Types](#supported-key-types) above.
|
||||||
|
|
||||||
Converts a public key object into a protobuf serialized public key.
|
Converts a public key object into a protobuf serialized public key.
|
||||||
|
|
||||||
### `unmarshalPublicKey(buf)`
|
### `crypto.keys.unmarshalPublicKey(buf)`
|
||||||
|
|
||||||
- `buf: Buffer`
|
- `buf: Buffer`
|
||||||
|
|
||||||
Converts a protobuf serialized public key into its representative object.
|
Converts a protobuf serialized public key into its representative object.
|
||||||
|
|
||||||
### `marshalPrivateKey(key[, type])`
|
### `crypto.keys.marshalPrivateKey(key[, type])`
|
||||||
|
|
||||||
- `key: crypto.rsa.RsaPrivateKey`
|
- `key: keys.rsa.RsaPrivateKey | keys.ed25519.Ed25519PrivateKey | require('libp2p-crypto-secp256k1').Secp256k1PrivateKey`
|
||||||
- `type: String`, only `'RSA'` is currently supported
|
- `type: String`, see [Supported Key Types](#supported-key-types) above.
|
||||||
|
|
||||||
Converts a private key object into a protobuf serialized private key.
|
Converts a private key object into a protobuf serialized private key.
|
||||||
|
|
||||||
### `unmarshalPrivateKey(buf, callback)`
|
### `crypto.keys.unmarshalPrivateKey(buf, callback)`
|
||||||
|
|
||||||
- `buf: Buffer`
|
- `buf: Buffer`
|
||||||
- `callback: Function`
|
- `callback: Function`
|
||||||
|
|
||||||
Converts a protobuf serialized private key into its representative object.
|
Converts a protobuf serialized private key into its representative object.
|
||||||
|
|
||||||
|
### `crypto.keys.import(pem, password, callback)`
|
||||||
|
|
||||||
|
- `pem: string`
|
||||||
|
- `password: string`
|
||||||
|
- `callback: Function`
|
||||||
|
|
||||||
|
Converts a PEM password protected private key into its representative object.
|
||||||
|
|
||||||
|
### `crypto.randomBytes(number)`
|
||||||
|
|
||||||
|
- `number: Number`
|
||||||
|
|
||||||
|
Generates a Buffer with length `number` populated by random bytes.
|
||||||
|
|
||||||
|
### `crypto.pbkdf2(password, salt, iterations, keySize, hash)`
|
||||||
|
|
||||||
|
- `password: String`
|
||||||
|
- `salt: String`
|
||||||
|
- `iterations: Number`
|
||||||
|
- `keySize: Number` in bytes
|
||||||
|
- `hash: String` the hashing algorithm ('sha1', 'sha2-512', ...)
|
||||||
|
|
||||||
|
Computes the Password Based Key Derivation Function 2; returning a new password.
|
||||||
|
|
||||||
## Contribute
|
## Contribute
|
||||||
|
|
||||||
@@ -196,4 +277,4 @@ This repository falls under the IPFS [Code of Conduct](https://github.com/ipfs/c
|
|||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
[MIT](LICENSE)
|
[MIT](./LICENSE)
|
||||||
|
29
appveyor.yml
Normal file
29
appveyor.yml
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
# Warning: This file is automatically synced from https://github.com/ipfs/ci-sync so if you want to change it, please change it there and ask someone to sync all repositories.
|
||||||
|
version: "{build}"
|
||||||
|
|
||||||
|
environment:
|
||||||
|
matrix:
|
||||||
|
- nodejs_version: "6"
|
||||||
|
- nodejs_version: "8"
|
||||||
|
|
||||||
|
matrix:
|
||||||
|
fast_finish: true
|
||||||
|
|
||||||
|
install:
|
||||||
|
# Install Node.js
|
||||||
|
- ps: Install-Product node $env:nodejs_version
|
||||||
|
|
||||||
|
# Upgrade npm
|
||||||
|
- npm install -g npm
|
||||||
|
|
||||||
|
# Output our current versions for debugging
|
||||||
|
- node --version
|
||||||
|
- npm --version
|
||||||
|
|
||||||
|
# Install our package dependencies
|
||||||
|
- npm install
|
||||||
|
|
||||||
|
test_script:
|
||||||
|
- npm run test:node
|
||||||
|
|
||||||
|
build: off
|
@@ -10,28 +10,18 @@ const curves = ['P-256', 'P-384', 'P-521']
|
|||||||
|
|
||||||
curves.forEach((curve) => {
|
curves.forEach((curve) => {
|
||||||
suite.add(`ephemeral key with secrect ${curve}`, (d) => {
|
suite.add(`ephemeral key with secrect ${curve}`, (d) => {
|
||||||
crypto.generateEphemeralKeyPair('P-256', (err, res) => {
|
crypto.keys.generateEphemeralKeyPair('P-256', (err, res) => {
|
||||||
if (err) {
|
if (err) { throw err }
|
||||||
throw err
|
|
||||||
}
|
|
||||||
res.genSharedKey(res.key, (err, secret) => {
|
res.genSharedKey(res.key, (err, secret) => {
|
||||||
if (err) {
|
if (err) { throw err }
|
||||||
throw err
|
|
||||||
}
|
|
||||||
secrets.push(secret)
|
secrets.push(secret)
|
||||||
|
|
||||||
d.resolve()
|
d.resolve()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}, {
|
}, { defer: true })
|
||||||
defer: true
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
suite
|
suite
|
||||||
.on('cycle', (event) => {
|
.on('cycle', (event) => console.log(String(event.target)))
|
||||||
console.log(String(event.target))
|
.run({async: true})
|
||||||
})
|
|
||||||
.run({
|
|
||||||
'async': true
|
|
||||||
})
|
|
||||||
|
@@ -1,6 +1,8 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const Benchmark = require('benchmark')
|
const Benchmark = require('benchmark')
|
||||||
|
const async = require('async')
|
||||||
|
|
||||||
const crypto = require('../src')
|
const crypto = require('../src')
|
||||||
|
|
||||||
const suite = new Benchmark.Suite('key-stretcher')
|
const suite = new Benchmark.Suite('key-stretcher')
|
||||||
@@ -10,38 +12,28 @@ const keys = []
|
|||||||
const ciphers = ['AES-128', 'AES-256', 'Blowfish']
|
const ciphers = ['AES-128', 'AES-256', 'Blowfish']
|
||||||
const hashes = ['SHA1', 'SHA256', 'SHA512']
|
const hashes = ['SHA1', 'SHA256', 'SHA512']
|
||||||
|
|
||||||
crypto.generateEphemeralKeyPair('P-256', (err, res) => {
|
async.waterfall([
|
||||||
if (err) {
|
(cb) => crypto.keys.generateEphemeralKeyPair('P-256', cb),
|
||||||
throw err
|
(res, cb) => res.genSharedKey(res.key, cb)
|
||||||
}
|
], (err, secret) => {
|
||||||
|
if (err) { throw err }
|
||||||
|
|
||||||
res.genSharedKey(res.key, (err, secret) => {
|
ciphers.forEach((cipher) => hashes.forEach((hash) => {
|
||||||
if (err) {
|
setup(cipher, hash, secret)
|
||||||
throw err
|
}))
|
||||||
}
|
|
||||||
ciphers.forEach((cipher) => {
|
|
||||||
hashes.forEach((hash) => {
|
|
||||||
suite.add(`keyStretcher ${cipher} ${hash}`, (d) => {
|
|
||||||
crypto.keyStretcher(cipher, hash, secret, (err, k) => {
|
|
||||||
if (err) {
|
|
||||||
throw err
|
|
||||||
}
|
|
||||||
|
|
||||||
keys.push(k)
|
suite
|
||||||
d.resolve()
|
.on('cycle', (event) => console.log(String(event.target)))
|
||||||
})
|
.run({async: true})
|
||||||
}, {
|
|
||||||
defer: true
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
suite
|
function setup (cipher, hash, secret) {
|
||||||
.on('cycle', (event) => {
|
suite.add(`keyStretcher ${cipher} ${hash}`, (d) => {
|
||||||
console.log(String(event.target))
|
crypto.keys.keyStretcher(cipher, hash, secret, (err, k) => {
|
||||||
})
|
if (err) { throw err }
|
||||||
.run({
|
|
||||||
'async': true
|
keys.push(k)
|
||||||
})
|
d.resolve()
|
||||||
|
})
|
||||||
|
}, { defer: true })
|
||||||
|
}
|
||||||
|
@@ -10,8 +10,8 @@ const bits = [1024, 2048, 4096]
|
|||||||
|
|
||||||
bits.forEach((bit) => {
|
bits.forEach((bit) => {
|
||||||
suite.add(`generateKeyPair ${bit}bits`, (d) => {
|
suite.add(`generateKeyPair ${bit}bits`, (d) => {
|
||||||
crypto.generateKeyPair('RSA', bit, (err, key) => {
|
crypto.keys.generateKeyPair('RSA', bit, (err, key) => {
|
||||||
if (err) throw err
|
if (err) { throw err }
|
||||||
keys.push(key)
|
keys.push(key)
|
||||||
d.resolve()
|
d.resolve()
|
||||||
})
|
})
|
||||||
@@ -25,17 +25,11 @@ suite.add('sign and verify', (d) => {
|
|||||||
const text = key.genSecret()
|
const text = key.genSecret()
|
||||||
|
|
||||||
key.sign(text, (err, sig) => {
|
key.sign(text, (err, sig) => {
|
||||||
if (err) {
|
if (err) { throw err }
|
||||||
throw err
|
|
||||||
}
|
|
||||||
|
|
||||||
key.public.verify(text, sig, (err, res) => {
|
key.public.verify(text, sig, (err, res) => {
|
||||||
if (err) {
|
if (err) { throw err }
|
||||||
throw err
|
if (res !== true) { throw new Error('failed to verify') }
|
||||||
}
|
|
||||||
if (res !== true) {
|
|
||||||
throw new Error('failed to verify')
|
|
||||||
}
|
|
||||||
d.resolve()
|
d.resolve()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -44,9 +38,5 @@ suite.add('sign and verify', (d) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
suite
|
suite
|
||||||
.on('cycle', (event) => {
|
.on('cycle', (event) => console.log(String(event.target)))
|
||||||
console.log(String(event.target))
|
.run({async: true})
|
||||||
})
|
|
||||||
.run({
|
|
||||||
'async': true
|
|
||||||
})
|
|
||||||
|
2
ci/Jenkinsfile
vendored
Normal file
2
ci/Jenkinsfile
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
// Warning: This file is automatically synced from https://github.com/ipfs/ci-sync so if you want to change it, please change it there and ask someone to sync all repositories.
|
||||||
|
javascript()
|
@@ -1,3 +1,4 @@
|
|||||||
|
# Warning: This file is automatically synced from https://github.com/ipfs/ci-sync so if you want to change it, please change it there and ask someone to sync all repositories.
|
||||||
machine:
|
machine:
|
||||||
node:
|
node:
|
||||||
version: stable
|
version: stable
|
||||||
@@ -5,8 +6,10 @@ machine:
|
|||||||
dependencies:
|
dependencies:
|
||||||
pre:
|
pre:
|
||||||
- google-chrome --version
|
- google-chrome --version
|
||||||
- wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add -
|
- curl -L -o google-chrome.deb https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
|
||||||
- sudo sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list'
|
- sudo dpkg -i google-chrome.deb || true
|
||||||
- sudo apt-get update
|
- sudo apt-get update
|
||||||
- sudo apt-get --only-upgrade install google-chrome-stable
|
- sudo apt-get install -f
|
||||||
|
- sudo apt-get install --only-upgrade lsb-base
|
||||||
|
- sudo dpkg -i google-chrome.deb
|
||||||
- google-chrome --version
|
- google-chrome --version
|
||||||
|
86
package.json
86
package.json
@@ -1,25 +1,26 @@
|
|||||||
{
|
{
|
||||||
"name": "libp2p-crypto",
|
"name": "libp2p-crypto",
|
||||||
"version": "0.7.0",
|
"version": "0.14.0",
|
||||||
"description": "Crypto primitives for libp2p",
|
"description": "Crypto primitives for libp2p",
|
||||||
"main": "src/index.js",
|
"main": "src/index.js",
|
||||||
|
"leadMaintainer": "Friedel Ziegelmayer <dignifiedquire@gmail.com>",
|
||||||
"browser": {
|
"browser": {
|
||||||
"node-webcrypto-ossl": false,
|
"./src/hmac/index.js": "./src/hmac/index-browser.js",
|
||||||
"./src/crypto/webcrypto.js": "./src/crypto/webcrypto-browser.js",
|
"./src/keys/ecdh.js": "./src/keys/ecdh-browser.js",
|
||||||
"./src/crypto/hmac.js": "./src/crypto/hmac-browser.js",
|
"./src/aes/ciphers.js": "./src/aes/ciphers-browser.js",
|
||||||
"./src/crypto/aes.js": "./src/crypto/aes-browser.js"
|
"./src/keys/rsa.js": "./src/keys/rsa-browser.js"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"lint": "aegir-lint",
|
"lint": "aegir lint",
|
||||||
"build": "aegir-build",
|
"build": "aegir build",
|
||||||
"test": "aegir-test",
|
"build-proto": "pbjs --wrap commonjs --target static-module src/keys/keys.proto > src/keys/keys.proto.js",
|
||||||
"test:node": "aegir-test --env node",
|
"test": "aegir test",
|
||||||
"test:browser": "aegir-test --env browser",
|
"test:node": "aegir test -t node",
|
||||||
"release": "aegir-release",
|
"test:browser": "aegir test -t browser -t webworker",
|
||||||
"release-minor": "aegir-release --type minor",
|
"release": "aegir release",
|
||||||
"release-major": "aegir-release --type major",
|
"release-minor": "aegir release --type minor",
|
||||||
"coverage": "aegir-coverage",
|
"release-major": "aegir release --type major",
|
||||||
"coverage-publish": "aegir-coverage publish"
|
"coverage": "aegir coverage --ignore src/keys/keys.proto.js"
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"IPFS",
|
"IPFS",
|
||||||
@@ -27,43 +28,56 @@
|
|||||||
"crypto",
|
"crypto",
|
||||||
"rsa"
|
"rsa"
|
||||||
],
|
],
|
||||||
"author": "Friedel Ziegelmayer <dignifiedqurie@gmail.com>",
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"asn1.js": "^4.8.1",
|
"asn1.js": "^5.0.1",
|
||||||
"async": "^2.1.2",
|
"async": "^2.6.1",
|
||||||
"multihashing-async": "^0.2.0",
|
"browserify-aes": "^1.2.0",
|
||||||
"node-webcrypto-ossl": "^1.0.7",
|
"bs58": "^4.0.1",
|
||||||
"nodeify": "^1.0.0",
|
"keypair": "^1.0.1",
|
||||||
"protocol-buffers": "^3.1.6",
|
"libp2p-crypto-secp256k1": "~0.2.2",
|
||||||
|
"multihashing-async": "~0.5.1",
|
||||||
|
"node-forge": "~0.7.6",
|
||||||
|
"pem-jwk": "^1.5.1",
|
||||||
|
"protons": "^1.0.1",
|
||||||
|
"rsa-pem-to-jwk": "^1.1.3",
|
||||||
|
"tweetnacl": "^1.0.0",
|
||||||
|
"ursa-optional": "~0.9.8",
|
||||||
"webcrypto-shim": "github:dignifiedquire/webcrypto-shim#master"
|
"webcrypto-shim": "github:dignifiedquire/webcrypto-shim#master"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"aegir": "^9.0.1",
|
"aegir": "^15.2.0",
|
||||||
"benchmark": "^2.1.2",
|
"benchmark": "^2.1.4",
|
||||||
"chai": "^3.5.0",
|
"chai": "^4.1.2",
|
||||||
"pre-commit": "^1.1.3"
|
"chai-string": "^1.5.0",
|
||||||
|
"dirty-chai": "^2.0.1"
|
||||||
},
|
},
|
||||||
"pre-commit": [
|
|
||||||
"lint",
|
|
||||||
"test"
|
|
||||||
],
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=4.0.0"
|
"node": ">=6.0.0",
|
||||||
|
"npm": ">=3.0.0"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/ipfs/js-libp2p-crypto.git"
|
"url": "https://github.com/libp2p/js-libp2p-crypto.git"
|
||||||
},
|
},
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/ipfs/js-libp2p-crypto/issues"
|
"url": "https://github.com/libp2p/js-libp2p-crypto/issues"
|
||||||
},
|
},
|
||||||
"homepage": "https://github.com/ipfs/js-libp2p-crypto",
|
"homepage": "https://github.com/libp2p/js-libp2p-crypto",
|
||||||
"contributors": [
|
"contributors": [
|
||||||
"David Dias <daviddias.p@gmail.com>",
|
"David Dias <daviddias.p@gmail.com>",
|
||||||
|
"Dmitriy Ryajov <dryajov@gmail.com>",
|
||||||
"Friedel Ziegelmayer <dignifiedquire@gmail.com>",
|
"Friedel Ziegelmayer <dignifiedquire@gmail.com>",
|
||||||
|
"Greenkeeper <support@greenkeeper.io>",
|
||||||
|
"Jack Kleeman <jackkleeman@gmail.com>",
|
||||||
|
"Joao Santos <jrmsantos15@gmail.com>",
|
||||||
|
"Maciej Krüger <mkg20001@gmail.com>",
|
||||||
"Richard Littauer <richard.littauer@gmail.com>",
|
"Richard Littauer <richard.littauer@gmail.com>",
|
||||||
"greenkeeperio-bot <support@greenkeeper.io>",
|
"Richard Schneider <makaretu@gmail.com>",
|
||||||
|
"Tom Swindell <t.swindell@rubyx.co.uk>",
|
||||||
|
"Victor Bjelkholm <victorbjelkholm@gmail.com>",
|
||||||
|
"Yusef Napora <yusef@napora.org>",
|
||||||
|
"greenkeeper[bot] <greenkeeper[bot]@users.noreply.github.com>",
|
||||||
"nikuda <nikuda@gmail.com>"
|
"nikuda <nikuda@gmail.com>"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
8
src/aes/ciphers-browser.js
Normal file
8
src/aes/ciphers-browser.js
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const crypto = require('browserify-aes')
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
createCipheriv: crypto.createCipheriv,
|
||||||
|
createDecipheriv: crypto.createDecipheriv
|
||||||
|
}
|
8
src/aes/ciphers.js
Normal file
8
src/aes/ciphers.js
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const crypto = require('crypto')
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
createCipheriv: crypto.createCipheriv,
|
||||||
|
createDecipheriv: crypto.createDecipheriv
|
||||||
|
}
|
55
src/aes/index-browser.js
Normal file
55
src/aes/index-browser.js
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const asm = require('asmcrypto.js')
|
||||||
|
const setImmediate = require('async/setImmediate')
|
||||||
|
|
||||||
|
exports.create = function (key, iv, callback) {
|
||||||
|
const done = (err, res) => setImmediate(() => callback(err, res))
|
||||||
|
|
||||||
|
if (key.length !== 16 && key.length !== 32) {
|
||||||
|
return done(new Error('Invalid key length'))
|
||||||
|
}
|
||||||
|
|
||||||
|
const enc = new asm.AES_CTR.Encrypt({
|
||||||
|
key: key,
|
||||||
|
nonce: iv
|
||||||
|
})
|
||||||
|
const dec = new asm.AES_CTR.Decrypt({
|
||||||
|
key: key,
|
||||||
|
nonce: iv
|
||||||
|
})
|
||||||
|
|
||||||
|
const res = {
|
||||||
|
encrypt (data, cb) {
|
||||||
|
const done = (err, res) => setImmediate(() => cb(err, res))
|
||||||
|
|
||||||
|
let res
|
||||||
|
try {
|
||||||
|
res = Buffer.from(
|
||||||
|
enc.process(data).result
|
||||||
|
)
|
||||||
|
} catch (err) {
|
||||||
|
return done(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
done(null, res)
|
||||||
|
},
|
||||||
|
|
||||||
|
decrypt (data, cb) {
|
||||||
|
const done = (err, res) => setImmediate(() => cb(err, res))
|
||||||
|
|
||||||
|
let res
|
||||||
|
try {
|
||||||
|
res = Buffer.from(
|
||||||
|
dec.process(data).result
|
||||||
|
)
|
||||||
|
} catch (err) {
|
||||||
|
return done(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
done(null, res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
done(null, res)
|
||||||
|
}
|
@@ -1,20 +1,20 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const crypto = require('crypto')
|
const ciphers = require('./ciphers')
|
||||||
|
|
||||||
const ciphers = {
|
const CIPHER_MODES = {
|
||||||
16: 'aes-128-ctr',
|
16: 'aes-128-ctr',
|
||||||
32: 'aes-256-ctr'
|
32: 'aes-256-ctr'
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.create = function (key, iv, callback) {
|
exports.create = function (key, iv, callback) {
|
||||||
const name = ciphers[key.length]
|
const mode = CIPHER_MODES[key.length]
|
||||||
if (!name) {
|
if (!mode) {
|
||||||
return callback(new Error('Invalid key length'))
|
return callback(new Error('Invalid key length'))
|
||||||
}
|
}
|
||||||
|
|
||||||
const cipher = crypto.createCipheriv(name, key, iv)
|
const cipher = ciphers.createCipheriv(mode, key, iv)
|
||||||
const decipher = crypto.createDecipheriv(name, key, iv)
|
const decipher = ciphers.createDecipheriv(mode, key, iv)
|
||||||
|
|
||||||
const res = {
|
const res = {
|
||||||
encrypt (data, cb) {
|
encrypt (data, cb) {
|
@@ -1,7 +0,0 @@
|
|||||||
'use strict'
|
|
||||||
|
|
||||||
exports.webcrypto = require('./crypto/webcrypto')()
|
|
||||||
exports.hmac = require('./crypto/hmac')
|
|
||||||
exports.ecdh = require('./crypto/ecdh')
|
|
||||||
exports.aes = require('./crypto/aes')
|
|
||||||
exports.rsa = require('./crypto/rsa')
|
|
@@ -1,52 +0,0 @@
|
|||||||
'use strict'
|
|
||||||
|
|
||||||
const nodeify = require('nodeify')
|
|
||||||
|
|
||||||
const crypto = require('./webcrypto')()
|
|
||||||
|
|
||||||
exports.create = function (key, iv, callback) {
|
|
||||||
nodeify(crypto.subtle.importKey(
|
|
||||||
'raw',
|
|
||||||
key,
|
|
||||||
{
|
|
||||||
name: 'AES-CTR'
|
|
||||||
},
|
|
||||||
false,
|
|
||||||
['encrypt', 'decrypt']
|
|
||||||
).then((key) => {
|
|
||||||
const counter = copy(iv)
|
|
||||||
|
|
||||||
return {
|
|
||||||
encrypt (data, cb) {
|
|
||||||
nodeify(crypto.subtle.encrypt(
|
|
||||||
{
|
|
||||||
name: 'AES-CTR',
|
|
||||||
counter: counter,
|
|
||||||
length: 128
|
|
||||||
},
|
|
||||||
key,
|
|
||||||
data
|
|
||||||
).then((raw) => Buffer.from(raw)), cb)
|
|
||||||
},
|
|
||||||
|
|
||||||
decrypt (data, cb) {
|
|
||||||
nodeify(crypto.subtle.decrypt(
|
|
||||||
{
|
|
||||||
name: 'AES-CTR',
|
|
||||||
counter: counter,
|
|
||||||
length: 128
|
|
||||||
},
|
|
||||||
key,
|
|
||||||
data
|
|
||||||
).then((raw) => Buffer.from(raw)), cb)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}), callback)
|
|
||||||
}
|
|
||||||
|
|
||||||
function copy (buf) {
|
|
||||||
const fresh = new Buffer(buf.length)
|
|
||||||
buf.copy(fresh)
|
|
||||||
|
|
||||||
return fresh
|
|
||||||
}
|
|
@@ -1,101 +0,0 @@
|
|||||||
'use strict'
|
|
||||||
|
|
||||||
const crypto = require('./webcrypto')()
|
|
||||||
const nodeify = require('nodeify')
|
|
||||||
const BN = require('asn1.js').bignum
|
|
||||||
|
|
||||||
const util = require('./util')
|
|
||||||
const toBase64 = util.toBase64
|
|
||||||
const toBn = util.toBn
|
|
||||||
|
|
||||||
exports.generateEphmeralKeyPair = function (curve, callback) {
|
|
||||||
nodeify(crypto.subtle.generateKey(
|
|
||||||
{
|
|
||||||
name: 'ECDH',
|
|
||||||
namedCurve: curve
|
|
||||||
},
|
|
||||||
true,
|
|
||||||
['deriveBits']
|
|
||||||
).then((pair) => {
|
|
||||||
// forcePrivate is used for testing only
|
|
||||||
const genSharedKey = (theirPub, forcePrivate, cb) => {
|
|
||||||
if (typeof forcePrivate === 'function') {
|
|
||||||
cb = forcePrivate
|
|
||||||
forcePrivate = undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
const privateKey = forcePrivate || pair.privateKey
|
|
||||||
nodeify(crypto.subtle.importKey(
|
|
||||||
'jwk',
|
|
||||||
unmarshalPublicKey(curve, theirPub),
|
|
||||||
{
|
|
||||||
name: 'ECDH',
|
|
||||||
namedCurve: curve
|
|
||||||
},
|
|
||||||
false,
|
|
||||||
[]
|
|
||||||
).then((publicKey) => {
|
|
||||||
return crypto.subtle.deriveBits(
|
|
||||||
{
|
|
||||||
name: 'ECDH',
|
|
||||||
namedCurve: curve,
|
|
||||||
public: publicKey
|
|
||||||
},
|
|
||||||
privateKey,
|
|
||||||
256
|
|
||||||
)
|
|
||||||
}).then((bits) => {
|
|
||||||
// return p.derive(pub.getPublic()).toBuffer('be')
|
|
||||||
return Buffer.from(bits)
|
|
||||||
}), cb)
|
|
||||||
}
|
|
||||||
|
|
||||||
return crypto.subtle.exportKey(
|
|
||||||
'jwk',
|
|
||||||
pair.publicKey
|
|
||||||
).then((publicKey) => {
|
|
||||||
return {
|
|
||||||
key: marshalPublicKey(publicKey),
|
|
||||||
genSharedKey
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}), callback)
|
|
||||||
}
|
|
||||||
|
|
||||||
const curveLengths = {
|
|
||||||
'P-256': 32,
|
|
||||||
'P-384': 48,
|
|
||||||
'P-521': 66
|
|
||||||
}
|
|
||||||
|
|
||||||
// Marshal converts a jwk encodec ECDH public key into the
|
|
||||||
// form specified in section 4.3.6 of ANSI X9.62. (This is the format
|
|
||||||
// go-ipfs uses)
|
|
||||||
function marshalPublicKey (jwk) {
|
|
||||||
const byteLen = curveLengths[jwk.crv]
|
|
||||||
|
|
||||||
return Buffer.concat([
|
|
||||||
Buffer([4]), // uncompressed point
|
|
||||||
toBn(jwk.x).toBuffer('be', byteLen),
|
|
||||||
toBn(jwk.y).toBuffer('be', byteLen)
|
|
||||||
], 1 + byteLen * 2)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unmarshal converts a point, serialized by Marshal, into an jwk encoded key
|
|
||||||
function unmarshalPublicKey (curve, key) {
|
|
||||||
const byteLen = curveLengths[curve]
|
|
||||||
|
|
||||||
if (!key.slice(0, 1).equals(Buffer([4]))) {
|
|
||||||
throw new Error('Invalid key format')
|
|
||||||
}
|
|
||||||
const x = new BN(key.slice(1, byteLen + 1))
|
|
||||||
const y = new BN(key.slice(1 + byteLen))
|
|
||||||
|
|
||||||
return {
|
|
||||||
kty: 'EC',
|
|
||||||
crv: curve,
|
|
||||||
x: toBase64(x),
|
|
||||||
y: toBase64(y),
|
|
||||||
ext: true
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,14 +0,0 @@
|
|||||||
'use strict'
|
|
||||||
|
|
||||||
module.exports = function getWebCrypto () {
|
|
||||||
if (typeof window !== 'undefined') {
|
|
||||||
// This is only a shim for interfaces, not for functionality
|
|
||||||
require('webcrypto-shim')(window)
|
|
||||||
|
|
||||||
if (window.crypto) {
|
|
||||||
return window.crypto
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new Error('Please use an environment with crypto support')
|
|
||||||
}
|
|
@@ -1,7 +0,0 @@
|
|||||||
'use strict'
|
|
||||||
|
|
||||||
module.exports = function getWebCrypto () {
|
|
||||||
const WebCrypto = require('node-webcrypto-ossl')
|
|
||||||
const webCrypto = new WebCrypto()
|
|
||||||
return webCrypto
|
|
||||||
}
|
|
@@ -1,9 +1,9 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const nodeify = require('nodeify')
|
const nodeify = require('../nodeify')
|
||||||
|
|
||||||
const crypto = require('./webcrypto')()
|
const crypto = require('../webcrypto.js')()
|
||||||
const lengths = require('./hmac-lengths')
|
const lengths = require('./lengths')
|
||||||
|
|
||||||
const hashTypes = {
|
const hashTypes = {
|
||||||
SHA1: 'SHA-1',
|
SHA1: 'SHA-1',
|
||||||
@@ -11,6 +11,11 @@ const hashTypes = {
|
|||||||
SHA512: 'SHA-512'
|
SHA512: 'SHA-512'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const sign = (key, data, cb) => {
|
||||||
|
nodeify(crypto.subtle.sign({name: 'HMAC'}, key, data)
|
||||||
|
.then((raw) => Buffer.from(raw)), cb)
|
||||||
|
}
|
||||||
|
|
||||||
exports.create = function (hashType, secret, callback) {
|
exports.create = function (hashType, secret, callback) {
|
||||||
const hash = hashTypes[hashType]
|
const hash = hashTypes[hashType]
|
||||||
|
|
||||||
@@ -26,11 +31,7 @@ exports.create = function (hashType, secret, callback) {
|
|||||||
).then((key) => {
|
).then((key) => {
|
||||||
return {
|
return {
|
||||||
digest (data, cb) {
|
digest (data, cb) {
|
||||||
nodeify(crypto.subtle.sign(
|
sign(key, data, cb)
|
||||||
{name: 'HMAC'},
|
|
||||||
key,
|
|
||||||
data
|
|
||||||
).then((raw) => Buffer.from(raw)), cb)
|
|
||||||
},
|
},
|
||||||
length: lengths[hashType]
|
length: lengths[hashType]
|
||||||
}
|
}
|
@@ -1,13 +1,13 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const crypto = require('crypto')
|
const crypto = require('crypto')
|
||||||
|
const lengths = require('./lengths')
|
||||||
const lengths = require('./hmac-lengths')
|
|
||||||
|
|
||||||
exports.create = function (hash, secret, callback) {
|
exports.create = function (hash, secret, callback) {
|
||||||
const res = {
|
const res = {
|
||||||
digest (data, cb) {
|
digest (data, cb) {
|
||||||
const hmac = genFresh()
|
const hmac = crypto.createHmac(hash.toLowerCase(), secret)
|
||||||
|
|
||||||
hmac.update(data)
|
hmac.update(data)
|
||||||
|
|
||||||
setImmediate(() => {
|
setImmediate(() => {
|
||||||
@@ -17,8 +17,5 @@ exports.create = function (hash, secret, callback) {
|
|||||||
length: lengths[hash]
|
length: lengths[hash]
|
||||||
}
|
}
|
||||||
|
|
||||||
function genFresh () {
|
|
||||||
return crypto.createHmac(hash.toLowerCase(), secret)
|
|
||||||
}
|
|
||||||
callback(null, res)
|
callback(null, res)
|
||||||
}
|
}
|
78
src/index.js
78
src/index.js
@@ -1,73 +1,13 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const protobuf = require('protocol-buffers')
|
const hmac = require('./hmac')
|
||||||
const pbm = protobuf(require('./crypto.proto'))
|
const aes = require('./aes')
|
||||||
const c = require('./crypto')
|
const keys = require('./keys')
|
||||||
|
|
||||||
exports.hmac = c.hmac
|
exports = module.exports
|
||||||
exports.aes = c.aes
|
|
||||||
exports.webcrypto = c.webcrypto
|
|
||||||
|
|
||||||
const keys = exports.keys = require('./keys')
|
exports.aes = aes
|
||||||
exports.keyStretcher = require('./key-stretcher')
|
exports.hmac = hmac
|
||||||
exports.generateEphemeralKeyPair = require('./ephemeral-keys')
|
exports.keys = keys
|
||||||
|
exports.randomBytes = require('./random-bytes')
|
||||||
// Generates a keypair of the given type and bitsize
|
exports.pbkdf2 = require('./pbkdf2')
|
||||||
exports.generateKeyPair = (type, bits, cb) => {
|
|
||||||
let key = keys[type.toLowerCase()]
|
|
||||||
if (!key) {
|
|
||||||
return cb(new Error('invalid or unsupported key type'))
|
|
||||||
}
|
|
||||||
|
|
||||||
key.generateKeyPair(bits, cb)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Converts a protobuf serialized public key into its
|
|
||||||
// representative object
|
|
||||||
exports.unmarshalPublicKey = (buf) => {
|
|
||||||
const decoded = pbm.PublicKey.decode(buf)
|
|
||||||
|
|
||||||
switch (decoded.Type) {
|
|
||||||
case pbm.KeyType.RSA:
|
|
||||||
return keys.rsa.unmarshalRsaPublicKey(decoded.Data)
|
|
||||||
default:
|
|
||||||
throw new Error('invalid or unsupported key type')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Converts a public key object into a protobuf serialized public key
|
|
||||||
exports.marshalPublicKey = (key, type) => {
|
|
||||||
type = (type || 'rsa').toLowerCase()
|
|
||||||
|
|
||||||
// for now only rsa is supported
|
|
||||||
if (type !== 'rsa') {
|
|
||||||
throw new Error('invalid or unsupported key type')
|
|
||||||
}
|
|
||||||
|
|
||||||
return key.bytes
|
|
||||||
}
|
|
||||||
|
|
||||||
// Converts a protobuf serialized private key into its
|
|
||||||
// representative object
|
|
||||||
exports.unmarshalPrivateKey = (buf, callback) => {
|
|
||||||
const decoded = pbm.PrivateKey.decode(buf)
|
|
||||||
|
|
||||||
switch (decoded.Type) {
|
|
||||||
case pbm.KeyType.RSA:
|
|
||||||
return keys.rsa.unmarshalRsaPrivateKey(decoded.Data, callback)
|
|
||||||
default:
|
|
||||||
callback(new Error('invalid or unsupported key type'))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Converts a private key object into a protobuf serialized private key
|
|
||||||
exports.marshalPrivateKey = (key, type) => {
|
|
||||||
type = (type || 'rsa').toLowerCase()
|
|
||||||
|
|
||||||
// for now only rsa is supported
|
|
||||||
if (type !== 'rsa') {
|
|
||||||
throw new Error('invalid or unsupported key type')
|
|
||||||
}
|
|
||||||
|
|
||||||
return key.bytes
|
|
||||||
}
|
|
||||||
|
127
src/keys/ecdh-browser.js
Normal file
127
src/keys/ecdh-browser.js
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const webcrypto = require('../webcrypto.js')()
|
||||||
|
const nodeify = require('../nodeify')
|
||||||
|
const BN = require('asn1.js').bignum
|
||||||
|
|
||||||
|
const util = require('../util')
|
||||||
|
const toBase64 = util.toBase64
|
||||||
|
const toBn = util.toBn
|
||||||
|
|
||||||
|
const bits = {
|
||||||
|
'P-256': 256,
|
||||||
|
'P-384': 384,
|
||||||
|
'P-521': 521
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.generateEphmeralKeyPair = function (curve, callback) {
|
||||||
|
nodeify(webcrypto.subtle.generateKey(
|
||||||
|
{
|
||||||
|
name: 'ECDH',
|
||||||
|
namedCurve: curve
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
['deriveBits']
|
||||||
|
).then((pair) => {
|
||||||
|
// forcePrivate is used for testing only
|
||||||
|
const genSharedKey = (theirPub, forcePrivate, cb) => {
|
||||||
|
if (typeof forcePrivate === 'function') {
|
||||||
|
cb = forcePrivate
|
||||||
|
forcePrivate = undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
let privateKey
|
||||||
|
|
||||||
|
if (forcePrivate) {
|
||||||
|
privateKey = webcrypto.subtle.importKey(
|
||||||
|
'jwk',
|
||||||
|
unmarshalPrivateKey(curve, forcePrivate),
|
||||||
|
{
|
||||||
|
name: 'ECDH',
|
||||||
|
namedCurve: curve
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
['deriveBits']
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
privateKey = Promise.resolve(pair.privateKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
const keys = Promise.all([
|
||||||
|
webcrypto.subtle.importKey(
|
||||||
|
'jwk',
|
||||||
|
unmarshalPublicKey(curve, theirPub),
|
||||||
|
{
|
||||||
|
name: 'ECDH',
|
||||||
|
namedCurve: curve
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
[]
|
||||||
|
),
|
||||||
|
privateKey
|
||||||
|
])
|
||||||
|
|
||||||
|
nodeify(keys.then((keys) => webcrypto.subtle.deriveBits(
|
||||||
|
{
|
||||||
|
name: 'ECDH',
|
||||||
|
namedCurve: curve,
|
||||||
|
public: keys[0]
|
||||||
|
},
|
||||||
|
keys[1],
|
||||||
|
bits[curve]
|
||||||
|
)).then((bits) => Buffer.from(bits)), cb)
|
||||||
|
}
|
||||||
|
|
||||||
|
return webcrypto.subtle.exportKey('jwk', pair.publicKey)
|
||||||
|
.then((publicKey) => {
|
||||||
|
return {
|
||||||
|
key: marshalPublicKey(publicKey),
|
||||||
|
genSharedKey
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}), callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
const curveLengths = {
|
||||||
|
'P-256': 32,
|
||||||
|
'P-384': 48,
|
||||||
|
'P-521': 66
|
||||||
|
}
|
||||||
|
|
||||||
|
// Marshal converts a jwk encodec ECDH public key into the
|
||||||
|
// form specified in section 4.3.6 of ANSI X9.62. (This is the format
|
||||||
|
// go-ipfs uses)
|
||||||
|
function marshalPublicKey (jwk) {
|
||||||
|
const byteLen = curveLengths[jwk.crv]
|
||||||
|
|
||||||
|
return Buffer.concat([
|
||||||
|
Buffer.from([4]), // uncompressed point
|
||||||
|
toBn(jwk.x).toArrayLike(Buffer, 'be', byteLen),
|
||||||
|
toBn(jwk.y).toArrayLike(Buffer, 'be', byteLen)
|
||||||
|
], 1 + byteLen * 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unmarshal converts a point, serialized by Marshal, into an jwk encoded key
|
||||||
|
function unmarshalPublicKey (curve, key) {
|
||||||
|
const byteLen = curveLengths[curve]
|
||||||
|
|
||||||
|
if (!key.slice(0, 1).equals(Buffer.from([4]))) {
|
||||||
|
throw new Error('Invalid key format')
|
||||||
|
}
|
||||||
|
const x = new BN(key.slice(1, byteLen + 1))
|
||||||
|
const y = new BN(key.slice(1 + byteLen))
|
||||||
|
|
||||||
|
return {
|
||||||
|
kty: 'EC',
|
||||||
|
crv: curve,
|
||||||
|
x: toBase64(x, byteLen),
|
||||||
|
y: toBase64(y, byteLen),
|
||||||
|
ext: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function unmarshalPrivateKey (curve, key) {
|
||||||
|
const result = unmarshalPublicKey(curve, key.public)
|
||||||
|
result.d = toBase64(new BN(key.private))
|
||||||
|
return result
|
||||||
|
}
|
41
src/keys/ecdh.js
Normal file
41
src/keys/ecdh.js
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const crypto = require('crypto')
|
||||||
|
const setImmediate = require('async/setImmediate')
|
||||||
|
|
||||||
|
const curves = {
|
||||||
|
'P-256': 'prime256v1',
|
||||||
|
'P-384': 'secp384r1',
|
||||||
|
'P-521': 'secp521r1'
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.generateEphmeralKeyPair = function (curve, callback) {
|
||||||
|
if (!curves[curve]) {
|
||||||
|
return callback(new Error(`Unkown curve: ${curve}`))
|
||||||
|
}
|
||||||
|
const ecdh = crypto.createECDH(curves[curve])
|
||||||
|
ecdh.generateKeys()
|
||||||
|
|
||||||
|
setImmediate(() => callback(null, {
|
||||||
|
key: ecdh.getPublicKey(),
|
||||||
|
genSharedKey (theirPub, forcePrivate, cb) {
|
||||||
|
if (typeof forcePrivate === 'function') {
|
||||||
|
cb = forcePrivate
|
||||||
|
forcePrivate = null
|
||||||
|
}
|
||||||
|
|
||||||
|
if (forcePrivate) {
|
||||||
|
ecdh.setPrivateKey(forcePrivate.private)
|
||||||
|
}
|
||||||
|
|
||||||
|
let secret
|
||||||
|
try {
|
||||||
|
secret = ecdh.computeSecret(theirPub)
|
||||||
|
} catch (err) {
|
||||||
|
return cb(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
setImmediate(() => cb(null, secret))
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
}
|
183
src/keys/ed25519-class.js
Normal file
183
src/keys/ed25519-class.js
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const multihashing = require('multihashing-async')
|
||||||
|
const protobuf = require('protons')
|
||||||
|
const bs58 = require('bs58')
|
||||||
|
|
||||||
|
const crypto = require('./ed25519')
|
||||||
|
const pbm = protobuf(require('./keys.proto'))
|
||||||
|
|
||||||
|
class Ed25519PublicKey {
|
||||||
|
constructor (key) {
|
||||||
|
this._key = ensureKey(key, crypto.publicKeyLength)
|
||||||
|
}
|
||||||
|
|
||||||
|
verify (data, sig, callback) {
|
||||||
|
ensure(callback)
|
||||||
|
crypto.hashAndVerify(this._key, sig, data, callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
marshal () {
|
||||||
|
return Buffer.from(this._key)
|
||||||
|
}
|
||||||
|
|
||||||
|
get bytes () {
|
||||||
|
return pbm.PublicKey.encode({
|
||||||
|
Type: pbm.KeyType.Ed25519,
|
||||||
|
Data: this.marshal()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
equals (key) {
|
||||||
|
return this.bytes.equals(key.bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
hash (callback) {
|
||||||
|
ensure(callback)
|
||||||
|
multihashing(this.bytes, 'sha2-256', callback)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Ed25519PrivateKey {
|
||||||
|
// key - 64 byte Uint8Array or Buffer containing private key
|
||||||
|
// publicKey - 32 byte Uint8Array or Buffer containing public key
|
||||||
|
constructor (key, publicKey) {
|
||||||
|
this._key = ensureKey(key, crypto.privateKeyLength)
|
||||||
|
this._publicKey = ensureKey(publicKey, crypto.publicKeyLength)
|
||||||
|
}
|
||||||
|
|
||||||
|
sign (message, callback) {
|
||||||
|
ensure(callback)
|
||||||
|
crypto.hashAndSign(this._key, message, callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
get public () {
|
||||||
|
if (!this._publicKey) {
|
||||||
|
throw new Error('public key not provided')
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Ed25519PublicKey(this._publicKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
marshal () {
|
||||||
|
return Buffer.concat([Buffer.from(this._key), Buffer.from(this._publicKey)])
|
||||||
|
}
|
||||||
|
|
||||||
|
get bytes () {
|
||||||
|
return pbm.PrivateKey.encode({
|
||||||
|
Type: pbm.KeyType.Ed25519,
|
||||||
|
Data: this.marshal()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
equals (key) {
|
||||||
|
return this.bytes.equals(key.bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
hash (callback) {
|
||||||
|
ensure(callback)
|
||||||
|
multihashing(this.bytes, 'sha2-256', callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the ID of the key.
|
||||||
|
*
|
||||||
|
* The key id is the base58 encoding of the SHA-256 multihash of its public key.
|
||||||
|
* The public key is a protobuf encoding containing a type and the DER encoding
|
||||||
|
* of the PKCS SubjectPublicKeyInfo.
|
||||||
|
*
|
||||||
|
* @param {function(Error, id)} callback
|
||||||
|
* @returns {undefined}
|
||||||
|
*/
|
||||||
|
id (callback) {
|
||||||
|
this.public.hash((err, hash) => {
|
||||||
|
if (err) {
|
||||||
|
return callback(err)
|
||||||
|
}
|
||||||
|
callback(null, bs58.encode(hash))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function unmarshalEd25519PrivateKey (bytes, callback) {
|
||||||
|
try {
|
||||||
|
bytes = ensureKey(bytes, crypto.privateKeyLength + crypto.publicKeyLength)
|
||||||
|
} catch (err) {
|
||||||
|
return callback(err)
|
||||||
|
}
|
||||||
|
const privateKeyBytes = bytes.slice(0, crypto.privateKeyLength)
|
||||||
|
const publicKeyBytes = bytes.slice(crypto.privateKeyLength, bytes.length)
|
||||||
|
callback(null, new Ed25519PrivateKey(privateKeyBytes, publicKeyBytes))
|
||||||
|
}
|
||||||
|
|
||||||
|
function unmarshalEd25519PublicKey (bytes) {
|
||||||
|
bytes = ensureKey(bytes, crypto.publicKeyLength)
|
||||||
|
return new Ed25519PublicKey(bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateKeyPair (_bits, cb) {
|
||||||
|
if (cb === undefined && typeof _bits === 'function') {
|
||||||
|
cb = _bits
|
||||||
|
}
|
||||||
|
|
||||||
|
crypto.generateKey((err, keys) => {
|
||||||
|
if (err) {
|
||||||
|
return cb(err)
|
||||||
|
}
|
||||||
|
let privkey
|
||||||
|
try {
|
||||||
|
privkey = new Ed25519PrivateKey(keys.secretKey, keys.publicKey)
|
||||||
|
} catch (err) {
|
||||||
|
cb(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
cb(null, privkey)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateKeyPairFromSeed (seed, _bits, cb) {
|
||||||
|
if (cb === undefined && typeof _bits === 'function') {
|
||||||
|
cb = _bits
|
||||||
|
}
|
||||||
|
|
||||||
|
crypto.generateKeyFromSeed(seed, (err, keys) => {
|
||||||
|
if (err) {
|
||||||
|
return cb(err)
|
||||||
|
}
|
||||||
|
let privkey
|
||||||
|
try {
|
||||||
|
privkey = new Ed25519PrivateKey(keys.secretKey, keys.publicKey)
|
||||||
|
} catch (err) {
|
||||||
|
cb(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
cb(null, privkey)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function ensure (cb) {
|
||||||
|
if (typeof cb !== 'function') {
|
||||||
|
throw new Error('callback is required')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function ensureKey (key, length) {
|
||||||
|
if (Buffer.isBuffer(key)) {
|
||||||
|
key = new Uint8Array(key)
|
||||||
|
}
|
||||||
|
if (!(key instanceof Uint8Array) || key.length !== length) {
|
||||||
|
throw new Error('Key must be a Uint8Array or Buffer of length ' + length)
|
||||||
|
}
|
||||||
|
return key
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
Ed25519PublicKey,
|
||||||
|
Ed25519PrivateKey,
|
||||||
|
unmarshalEd25519PrivateKey,
|
||||||
|
unmarshalEd25519PublicKey,
|
||||||
|
generateKeyPair,
|
||||||
|
generateKeyPairFromSeed
|
||||||
|
}
|
51
src/keys/ed25519.js
Normal file
51
src/keys/ed25519.js
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const nacl = require('tweetnacl')
|
||||||
|
const setImmediate = require('async/setImmediate')
|
||||||
|
|
||||||
|
exports.publicKeyLength = nacl.sign.publicKeyLength
|
||||||
|
exports.privateKeyLength = nacl.sign.secretKeyLength
|
||||||
|
|
||||||
|
exports.generateKey = function (callback) {
|
||||||
|
setImmediate(() => {
|
||||||
|
let result
|
||||||
|
try {
|
||||||
|
result = nacl.sign.keyPair()
|
||||||
|
} catch (err) {
|
||||||
|
return callback(err)
|
||||||
|
}
|
||||||
|
callback(null, result)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// seed should be a 32 byte uint8array
|
||||||
|
exports.generateKeyFromSeed = function (seed, callback) {
|
||||||
|
setImmediate(() => {
|
||||||
|
let result
|
||||||
|
try {
|
||||||
|
result = nacl.sign.keyPair.fromSeed(seed)
|
||||||
|
} catch (err) {
|
||||||
|
return callback(err)
|
||||||
|
}
|
||||||
|
callback(null, result)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.hashAndSign = function (key, msg, callback) {
|
||||||
|
setImmediate(() => {
|
||||||
|
callback(null, Buffer.from(nacl.sign.detached(msg, key)))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.hashAndVerify = function (key, sig, msg, callback) {
|
||||||
|
setImmediate(() => {
|
||||||
|
let result
|
||||||
|
try {
|
||||||
|
result = nacl.sign.detached.verify(msg, sig, key)
|
||||||
|
} catch (err) {
|
||||||
|
return callback(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
callback(null, result)
|
||||||
|
})
|
||||||
|
}
|
@@ -1,11 +1,11 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const crypto = require('./crypto')
|
const ecdh = require('./ecdh')
|
||||||
|
|
||||||
// Generates an ephemeral public key and returns a function that will compute
|
// Generates an ephemeral public key and returns a function that will compute
|
||||||
// the shared secret key.
|
// the shared secret key.
|
||||||
//
|
//
|
||||||
// Focuses only on ECDH now, but can be made more general in the future.
|
// Focuses only on ECDH now, but can be made more general in the future.
|
||||||
module.exports = (curve, callback) => {
|
module.exports = (curve, callback) => {
|
||||||
crypto.ecdh.generateEphmeralKeyPair(curve, callback)
|
ecdh.generateEphmeralKeyPair(curve, callback)
|
||||||
}
|
}
|
@@ -1,5 +1,132 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
module.exports = {
|
const protobuf = require('protons')
|
||||||
rsa: require('./rsa')
|
const keysPBM = protobuf(require('./keys.proto'))
|
||||||
|
const forge = require('node-forge')
|
||||||
|
|
||||||
|
exports = module.exports
|
||||||
|
|
||||||
|
const supportedKeys = {
|
||||||
|
rsa: require('./rsa-class'),
|
||||||
|
ed25519: require('./ed25519-class'),
|
||||||
|
secp256k1: require('libp2p-crypto-secp256k1')(keysPBM, require('../random-bytes'))
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.supportedKeys = supportedKeys
|
||||||
|
exports.keysPBM = keysPBM
|
||||||
|
|
||||||
|
function isValidKeyType (keyType) {
|
||||||
|
const key = supportedKeys[keyType.toLowerCase()]
|
||||||
|
return key !== undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.keyStretcher = require('./key-stretcher')
|
||||||
|
exports.generateEphemeralKeyPair = require('./ephemeral-keys')
|
||||||
|
|
||||||
|
// Generates a keypair of the given type and bitsize
|
||||||
|
exports.generateKeyPair = (type, bits, cb) => {
|
||||||
|
let key = supportedKeys[type.toLowerCase()]
|
||||||
|
|
||||||
|
if (!key) {
|
||||||
|
return cb(new Error('invalid or unsupported key type'))
|
||||||
|
}
|
||||||
|
|
||||||
|
key.generateKeyPair(bits, cb)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates a keypair of the given type and bitsize
|
||||||
|
// seed is a 32 byte uint8array
|
||||||
|
exports.generateKeyPairFromSeed = (type, seed, bits, cb) => {
|
||||||
|
let key = supportedKeys[type.toLowerCase()]
|
||||||
|
if (!key) {
|
||||||
|
return cb(new Error('invalid or unsupported key type'))
|
||||||
|
}
|
||||||
|
if (type.toLowerCase() !== 'ed25519') {
|
||||||
|
return cb(new Error('Seed key derivation is unimplemented for RSA or secp256k1'))
|
||||||
|
}
|
||||||
|
key.generateKeyPairFromSeed(seed, bits, cb)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Converts a protobuf serialized public key into its
|
||||||
|
// representative object
|
||||||
|
exports.unmarshalPublicKey = (buf) => {
|
||||||
|
const decoded = keysPBM.PublicKey.decode(buf)
|
||||||
|
const data = decoded.Data
|
||||||
|
|
||||||
|
switch (decoded.Type) {
|
||||||
|
case keysPBM.KeyType.RSA:
|
||||||
|
return supportedKeys.rsa.unmarshalRsaPublicKey(data)
|
||||||
|
case keysPBM.KeyType.Ed25519:
|
||||||
|
return supportedKeys.ed25519.unmarshalEd25519PublicKey(data)
|
||||||
|
case keysPBM.KeyType.Secp256k1:
|
||||||
|
if (supportedKeys.secp256k1) {
|
||||||
|
return supportedKeys.secp256k1.unmarshalSecp256k1PublicKey(data)
|
||||||
|
} else {
|
||||||
|
throw new Error('secp256k1 support requires libp2p-crypto-secp256k1 package')
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
throw new Error('invalid or unsupported key type')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Converts a public key object into a protobuf serialized public key
|
||||||
|
exports.marshalPublicKey = (key, type) => {
|
||||||
|
type = (type || 'rsa').toLowerCase()
|
||||||
|
if (!isValidKeyType(type)) {
|
||||||
|
throw new Error('invalid or unsupported key type')
|
||||||
|
}
|
||||||
|
|
||||||
|
return key.bytes
|
||||||
|
}
|
||||||
|
|
||||||
|
// Converts a protobuf serialized private key into its
|
||||||
|
// representative object
|
||||||
|
exports.unmarshalPrivateKey = (buf, callback) => {
|
||||||
|
let decoded
|
||||||
|
try {
|
||||||
|
decoded = keysPBM.PrivateKey.decode(buf)
|
||||||
|
} catch (err) {
|
||||||
|
return callback(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = decoded.Data
|
||||||
|
|
||||||
|
switch (decoded.Type) {
|
||||||
|
case keysPBM.KeyType.RSA:
|
||||||
|
return supportedKeys.rsa.unmarshalRsaPrivateKey(data, callback)
|
||||||
|
case keysPBM.KeyType.Ed25519:
|
||||||
|
return supportedKeys.ed25519.unmarshalEd25519PrivateKey(data, callback)
|
||||||
|
case keysPBM.KeyType.Secp256k1:
|
||||||
|
if (supportedKeys.secp256k1) {
|
||||||
|
return supportedKeys.secp256k1.unmarshalSecp256k1PrivateKey(data, callback)
|
||||||
|
} else {
|
||||||
|
return callback(new Error('secp256k1 support requires libp2p-crypto-secp256k1 package'))
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
callback(new Error('invalid or unsupported key type'))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Converts a private key object into a protobuf serialized private key
|
||||||
|
exports.marshalPrivateKey = (key, type) => {
|
||||||
|
type = (type || 'rsa').toLowerCase()
|
||||||
|
if (!isValidKeyType(type)) {
|
||||||
|
throw new Error('invalid or unsupported key type')
|
||||||
|
}
|
||||||
|
|
||||||
|
return key.bytes
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.import = (pem, password, callback) => {
|
||||||
|
try {
|
||||||
|
const key = forge.pki.decryptRsaPrivateKey(pem, password)
|
||||||
|
if (key === null) {
|
||||||
|
throw new Error('Cannot read the key, most likely the password is wrong or not a RSA key')
|
||||||
|
}
|
||||||
|
let der = forge.asn1.toDer(forge.pki.privateKeyToAsn1(key))
|
||||||
|
der = Buffer.from(der.getBytes(), 'binary')
|
||||||
|
return supportedKeys.rsa.unmarshalRsaPrivateKey(der, callback)
|
||||||
|
} catch (err) {
|
||||||
|
callback(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const crypto = require('./crypto')
|
|
||||||
const whilst = require('async/whilst')
|
const whilst = require('async/whilst')
|
||||||
|
const hmac = require('../hmac')
|
||||||
|
|
||||||
const cipherMap = {
|
const cipherMap = {
|
||||||
'AES-128': {
|
'AES-128': {
|
||||||
@@ -37,7 +37,7 @@ module.exports = (cipherType, hash, secret, callback) => {
|
|||||||
const seed = Buffer.from('key expansion')
|
const seed = Buffer.from('key expansion')
|
||||||
const resultLength = 2 * (ivSize + cipherKeySize + hmacKeySize)
|
const resultLength = 2 * (ivSize + cipherKeySize + hmacKeySize)
|
||||||
|
|
||||||
crypto.hmac.create(hash, secret, (err, m) => {
|
hmac.create(hash, secret, (err, m) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
return callback(err)
|
return callback(err)
|
||||||
}
|
}
|
@@ -2,14 +2,14 @@
|
|||||||
|
|
||||||
module.exports = `enum KeyType {
|
module.exports = `enum KeyType {
|
||||||
RSA = 0;
|
RSA = 0;
|
||||||
|
Ed25519 = 1;
|
||||||
|
Secp256k1 = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
message PublicKey {
|
message PublicKey {
|
||||||
required KeyType Type = 1;
|
required KeyType Type = 1;
|
||||||
required bytes Data = 2;
|
required bytes Data = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
message PrivateKey {
|
message PrivateKey {
|
||||||
required KeyType Type = 1;
|
required KeyType Type = 1;
|
||||||
required bytes Data = 2;
|
required bytes Data = 2;
|
||||||
}`
|
}`
|
117
src/keys/rsa-browser.js
Normal file
117
src/keys/rsa-browser.js
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const nodeify = require('../nodeify')
|
||||||
|
|
||||||
|
const webcrypto = require('../webcrypto.js')()
|
||||||
|
|
||||||
|
exports.utils = require('./rsa-utils')
|
||||||
|
|
||||||
|
exports.generateKey = function (bits, callback) {
|
||||||
|
nodeify(webcrypto.subtle.generateKey(
|
||||||
|
{
|
||||||
|
name: 'RSASSA-PKCS1-v1_5',
|
||||||
|
modulusLength: bits,
|
||||||
|
publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
|
||||||
|
hash: {name: 'SHA-256'}
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
['sign', 'verify']
|
||||||
|
)
|
||||||
|
.then(exportKey)
|
||||||
|
.then((keys) => ({
|
||||||
|
privateKey: keys[0],
|
||||||
|
publicKey: keys[1]
|
||||||
|
})), callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Takes a jwk key
|
||||||
|
exports.unmarshalPrivateKey = function (key, callback) {
|
||||||
|
const privateKey = webcrypto.subtle.importKey(
|
||||||
|
'jwk',
|
||||||
|
key,
|
||||||
|
{
|
||||||
|
name: 'RSASSA-PKCS1-v1_5',
|
||||||
|
hash: {name: 'SHA-256'}
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
['sign']
|
||||||
|
)
|
||||||
|
|
||||||
|
nodeify(Promise.all([
|
||||||
|
privateKey,
|
||||||
|
derivePublicFromPrivate(key)
|
||||||
|
]).then((keys) => exportKey({
|
||||||
|
privateKey: keys[0],
|
||||||
|
publicKey: keys[1]
|
||||||
|
})).then((keys) => ({
|
||||||
|
privateKey: keys[0],
|
||||||
|
publicKey: keys[1]
|
||||||
|
})), callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.getRandomValues = function (arr) {
|
||||||
|
return Buffer.from(webcrypto.getRandomValues(arr))
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.hashAndSign = function (key, msg, callback) {
|
||||||
|
nodeify(webcrypto.subtle.importKey(
|
||||||
|
'jwk',
|
||||||
|
key,
|
||||||
|
{
|
||||||
|
name: 'RSASSA-PKCS1-v1_5',
|
||||||
|
hash: {name: 'SHA-256'}
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
['sign']
|
||||||
|
).then((privateKey) => {
|
||||||
|
return webcrypto.subtle.sign(
|
||||||
|
{name: 'RSASSA-PKCS1-v1_5'},
|
||||||
|
privateKey,
|
||||||
|
Uint8Array.from(msg)
|
||||||
|
)
|
||||||
|
}).then((sig) => Buffer.from(sig)), callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.hashAndVerify = function (key, sig, msg, callback) {
|
||||||
|
nodeify(webcrypto.subtle.importKey(
|
||||||
|
'jwk',
|
||||||
|
key,
|
||||||
|
{
|
||||||
|
name: 'RSASSA-PKCS1-v1_5',
|
||||||
|
hash: {name: 'SHA-256'}
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
['verify']
|
||||||
|
).then((publicKey) => {
|
||||||
|
return webcrypto.subtle.verify(
|
||||||
|
{name: 'RSASSA-PKCS1-v1_5'},
|
||||||
|
publicKey,
|
||||||
|
sig,
|
||||||
|
msg
|
||||||
|
)
|
||||||
|
}), callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
function exportKey (pair) {
|
||||||
|
return Promise.all([
|
||||||
|
webcrypto.subtle.exportKey('jwk', pair.privateKey),
|
||||||
|
webcrypto.subtle.exportKey('jwk', pair.publicKey)
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
function derivePublicFromPrivate (jwKey) {
|
||||||
|
return webcrypto.subtle.importKey(
|
||||||
|
'jwk',
|
||||||
|
{
|
||||||
|
kty: jwKey.kty,
|
||||||
|
n: jwKey.n,
|
||||||
|
e: jwKey.e
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'RSASSA-PKCS1-v1_5',
|
||||||
|
hash: {name: 'SHA-256'}
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
['verify']
|
||||||
|
)
|
||||||
|
}
|
211
src/keys/rsa-class.js
Normal file
211
src/keys/rsa-class.js
Normal file
@@ -0,0 +1,211 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const multihashing = require('multihashing-async')
|
||||||
|
const protobuf = require('protons')
|
||||||
|
const bs58 = require('bs58')
|
||||||
|
|
||||||
|
const crypto = require('./rsa')
|
||||||
|
const pbm = protobuf(require('./keys.proto'))
|
||||||
|
const forge = require('node-forge')
|
||||||
|
const setImmediate = require('async/setImmediate')
|
||||||
|
|
||||||
|
class RsaPublicKey {
|
||||||
|
constructor (key) {
|
||||||
|
this._key = key
|
||||||
|
}
|
||||||
|
|
||||||
|
verify (data, sig, callback) {
|
||||||
|
ensure(callback)
|
||||||
|
crypto.hashAndVerify(this._key, sig, data, callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
marshal () {
|
||||||
|
return crypto.utils.jwkToPkix(this._key)
|
||||||
|
}
|
||||||
|
|
||||||
|
get bytes () {
|
||||||
|
return pbm.PublicKey.encode({
|
||||||
|
Type: pbm.KeyType.RSA,
|
||||||
|
Data: this.marshal()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
encrypt (bytes) {
|
||||||
|
return this._key.encrypt(bytes, 'RSAES-PKCS1-V1_5')
|
||||||
|
}
|
||||||
|
|
||||||
|
equals (key) {
|
||||||
|
return this.bytes.equals(key.bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
hash (callback) {
|
||||||
|
ensure(callback)
|
||||||
|
multihashing(this.bytes, 'sha2-256', callback)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class RsaPrivateKey {
|
||||||
|
// key - Object of the jwk format
|
||||||
|
// publicKey - Buffer of the spki format
|
||||||
|
constructor (key, publicKey) {
|
||||||
|
this._key = key
|
||||||
|
this._publicKey = publicKey
|
||||||
|
}
|
||||||
|
|
||||||
|
genSecret () {
|
||||||
|
return crypto.getRandomValues(new Uint8Array(16))
|
||||||
|
}
|
||||||
|
|
||||||
|
sign (message, callback) {
|
||||||
|
ensure(callback)
|
||||||
|
crypto.hashAndSign(this._key, message, callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
get public () {
|
||||||
|
if (!this._publicKey) {
|
||||||
|
throw new Error('public key not provided')
|
||||||
|
}
|
||||||
|
|
||||||
|
return new RsaPublicKey(this._publicKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
decrypt (msg, callback) {
|
||||||
|
crypto.decrypt(this._key, msg, callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
marshal () {
|
||||||
|
return crypto.utils.jwkToPkcs1(this._key)
|
||||||
|
}
|
||||||
|
|
||||||
|
get bytes () {
|
||||||
|
return pbm.PrivateKey.encode({
|
||||||
|
Type: pbm.KeyType.RSA,
|
||||||
|
Data: this.marshal()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
equals (key) {
|
||||||
|
return this.bytes.equals(key.bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
hash (callback) {
|
||||||
|
ensure(callback)
|
||||||
|
multihashing(this.bytes, 'sha2-256', callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the ID of the key.
|
||||||
|
*
|
||||||
|
* The key id is the base58 encoding of the SHA-256 multihash of its public key.
|
||||||
|
* The public key is a protobuf encoding containing a type and the DER encoding
|
||||||
|
* of the PKCS SubjectPublicKeyInfo.
|
||||||
|
*
|
||||||
|
* @param {function(Error, id)} callback
|
||||||
|
* @returns {undefined}
|
||||||
|
*/
|
||||||
|
id (callback) {
|
||||||
|
this.public.hash((err, hash) => {
|
||||||
|
if (err) {
|
||||||
|
return callback(err)
|
||||||
|
}
|
||||||
|
callback(null, bs58.encode(hash))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exports the key into a password protected PEM format
|
||||||
|
*
|
||||||
|
* @param {string} [format] - Defaults to 'pkcs-8'.
|
||||||
|
* @param {string} password - The password to read the encrypted PEM
|
||||||
|
* @param {function(Error, KeyInfo)} callback
|
||||||
|
* @returns {undefined}
|
||||||
|
*/
|
||||||
|
export (format, password, callback) {
|
||||||
|
if (typeof password === 'function') {
|
||||||
|
callback = password
|
||||||
|
password = format
|
||||||
|
format = 'pkcs-8'
|
||||||
|
}
|
||||||
|
|
||||||
|
ensure(callback)
|
||||||
|
|
||||||
|
setImmediate(() => {
|
||||||
|
let err = null
|
||||||
|
let pem = null
|
||||||
|
try {
|
||||||
|
const buffer = new forge.util.ByteBuffer(this.marshal())
|
||||||
|
const asn1 = forge.asn1.fromDer(buffer)
|
||||||
|
const privateKey = forge.pki.privateKeyFromAsn1(asn1)
|
||||||
|
|
||||||
|
if (format === 'pkcs-8') {
|
||||||
|
const options = {
|
||||||
|
algorithm: 'aes256',
|
||||||
|
count: 10000,
|
||||||
|
saltSize: 128 / 8,
|
||||||
|
prfAlgorithm: 'sha512'
|
||||||
|
}
|
||||||
|
pem = forge.pki.encryptRsaPrivateKey(privateKey, password, options)
|
||||||
|
} else {
|
||||||
|
err = new Error(`Unknown export format '${format}'`)
|
||||||
|
}
|
||||||
|
} catch (_err) {
|
||||||
|
err = _err
|
||||||
|
}
|
||||||
|
|
||||||
|
callback(err, pem)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function unmarshalRsaPrivateKey (bytes, callback) {
|
||||||
|
const jwk = crypto.utils.pkcs1ToJwk(bytes)
|
||||||
|
|
||||||
|
crypto.unmarshalPrivateKey(jwk, (err, keys) => {
|
||||||
|
if (err) {
|
||||||
|
return callback(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
callback(null, new RsaPrivateKey(keys.privateKey, keys.publicKey))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function unmarshalRsaPublicKey (bytes) {
|
||||||
|
const jwk = crypto.utils.pkixToJwk(bytes)
|
||||||
|
|
||||||
|
return new RsaPublicKey(jwk)
|
||||||
|
}
|
||||||
|
|
||||||
|
function fromJwk (jwk, callback) {
|
||||||
|
crypto.unmarshalPrivateKey(jwk, (err, keys) => {
|
||||||
|
if (err) {
|
||||||
|
return callback(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
callback(null, new RsaPrivateKey(keys.privateKey, keys.publicKey))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateKeyPair (bits, callback) {
|
||||||
|
crypto.generateKey(bits, (err, keys) => {
|
||||||
|
if (err) {
|
||||||
|
return callback(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
callback(null, new RsaPrivateKey(keys.privateKey, keys.publicKey))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function ensure (callback) {
|
||||||
|
if (typeof callback !== 'function') {
|
||||||
|
throw new Error('callback is required')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
RsaPublicKey,
|
||||||
|
RsaPrivateKey,
|
||||||
|
unmarshalRsaPublicKey,
|
||||||
|
unmarshalRsaPrivateKey,
|
||||||
|
generateKeyPair,
|
||||||
|
fromJwk
|
||||||
|
}
|
@@ -1,124 +1,10 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const nodeify = require('nodeify')
|
|
||||||
const asn1 = require('asn1.js')
|
const asn1 = require('asn1.js')
|
||||||
|
|
||||||
const util = require('./util')
|
const util = require('./../util')
|
||||||
const toBase64 = util.toBase64
|
const toBase64 = util.toBase64
|
||||||
const toBn = util.toBn
|
const toBn = util.toBn
|
||||||
const crypto = require('./webcrypto')()
|
|
||||||
|
|
||||||
exports.generateKey = function (bits, callback) {
|
|
||||||
nodeify(crypto.subtle.generateKey(
|
|
||||||
{
|
|
||||||
name: 'RSASSA-PKCS1-v1_5',
|
|
||||||
modulusLength: bits,
|
|
||||||
publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
|
|
||||||
hash: {name: 'SHA-256'}
|
|
||||||
},
|
|
||||||
true,
|
|
||||||
['sign', 'verify']
|
|
||||||
)
|
|
||||||
.then(exportKey)
|
|
||||||
.then((keys) => ({
|
|
||||||
privateKey: keys[0],
|
|
||||||
publicKey: keys[1]
|
|
||||||
})), callback)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Takes a jwk key
|
|
||||||
exports.unmarshalPrivateKey = function (key, callback) {
|
|
||||||
const privateKey = crypto.subtle.importKey(
|
|
||||||
'jwk',
|
|
||||||
key,
|
|
||||||
{
|
|
||||||
name: 'RSASSA-PKCS1-v1_5',
|
|
||||||
hash: {name: 'SHA-256'}
|
|
||||||
},
|
|
||||||
true,
|
|
||||||
['sign']
|
|
||||||
)
|
|
||||||
|
|
||||||
nodeify(Promise.all([
|
|
||||||
privateKey,
|
|
||||||
derivePublicFromPrivate(key)
|
|
||||||
]).then((keys) => exportKey({
|
|
||||||
privateKey: keys[0],
|
|
||||||
publicKey: keys[1]
|
|
||||||
})).then((keys) => ({
|
|
||||||
privateKey: keys[0],
|
|
||||||
publicKey: keys[1]
|
|
||||||
})), callback)
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.getRandomValues = function (arr) {
|
|
||||||
return Buffer.from(crypto.getRandomValues(arr))
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.hashAndSign = function (key, msg, callback) {
|
|
||||||
nodeify(crypto.subtle.importKey(
|
|
||||||
'jwk',
|
|
||||||
key,
|
|
||||||
{
|
|
||||||
name: 'RSASSA-PKCS1-v1_5',
|
|
||||||
hash: {name: 'SHA-256'}
|
|
||||||
},
|
|
||||||
false,
|
|
||||||
['sign']
|
|
||||||
).then((privateKey) => {
|
|
||||||
return crypto.subtle.sign(
|
|
||||||
{name: 'RSASSA-PKCS1-v1_5'},
|
|
||||||
privateKey,
|
|
||||||
Uint8Array.from(msg)
|
|
||||||
)
|
|
||||||
}).then((sig) => Buffer.from(sig)), callback)
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.hashAndVerify = function (key, sig, msg, callback) {
|
|
||||||
nodeify(crypto.subtle.importKey(
|
|
||||||
'jwk',
|
|
||||||
key,
|
|
||||||
{
|
|
||||||
name: 'RSASSA-PKCS1-v1_5',
|
|
||||||
hash: {name: 'SHA-256'}
|
|
||||||
},
|
|
||||||
false,
|
|
||||||
['verify']
|
|
||||||
).then((publicKey) => {
|
|
||||||
return crypto.subtle.verify(
|
|
||||||
{name: 'RSASSA-PKCS1-v1_5'},
|
|
||||||
publicKey,
|
|
||||||
sig,
|
|
||||||
msg
|
|
||||||
)
|
|
||||||
}), callback)
|
|
||||||
}
|
|
||||||
|
|
||||||
function exportKey (pair) {
|
|
||||||
return Promise.all([
|
|
||||||
crypto.subtle.exportKey('jwk', pair.privateKey),
|
|
||||||
crypto.subtle.exportKey('jwk', pair.publicKey)
|
|
||||||
])
|
|
||||||
}
|
|
||||||
|
|
||||||
function derivePublicFromPrivate (jwKey) {
|
|
||||||
return crypto.subtle.importKey(
|
|
||||||
'jwk',
|
|
||||||
{
|
|
||||||
kty: jwKey.kty,
|
|
||||||
n: jwKey.n,
|
|
||||||
e: jwKey.e,
|
|
||||||
alg: jwKey.alg,
|
|
||||||
kid: jwKey.kid
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'RSASSA-PKCS1-v1_5',
|
|
||||||
hash: {name: 'SHA-256'}
|
|
||||||
},
|
|
||||||
true,
|
|
||||||
['verify']
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const RSAPrivateKey = asn1.define('RSAPrivateKey', function () {
|
const RSAPrivateKey = asn1.define('RSAPrivateKey', function () {
|
||||||
this.seq().obj(
|
this.seq().obj(
|
184
src/keys/rsa.js
184
src/keys/rsa.js
@@ -1,133 +1,99 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const multihashing = require('multihashing-async')
|
const crypto = require('crypto')
|
||||||
const protobuf = require('protocol-buffers')
|
let keypair
|
||||||
|
try {
|
||||||
const crypto = require('../crypto').rsa
|
if (process.env.LP2P_FORCE_CRYPTO_LIB === 'keypair') {
|
||||||
const pbm = protobuf(require('../crypto.proto'))
|
throw new Error('Force keypair usage')
|
||||||
|
|
||||||
class RsaPublicKey {
|
|
||||||
constructor (key) {
|
|
||||||
this._key = key
|
|
||||||
}
|
}
|
||||||
|
|
||||||
verify (data, sig, callback) {
|
const ursa = require('ursa-optional') // throws if not compiled
|
||||||
ensure(callback)
|
keypair = ({bits}) => {
|
||||||
crypto.hashAndVerify(this._key, sig, data, callback)
|
const key = ursa.generatePrivateKey(bits)
|
||||||
}
|
return {
|
||||||
|
private: key.toPrivatePem(),
|
||||||
marshal () {
|
public: key.toPublicPem()
|
||||||
return crypto.jwkToPkix(this._key)
|
|
||||||
}
|
|
||||||
|
|
||||||
get bytes () {
|
|
||||||
return pbm.PublicKey.encode({
|
|
||||||
Type: pbm.KeyType.RSA,
|
|
||||||
Data: this.marshal()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
encrypt (bytes) {
|
|
||||||
return this._key.encrypt(bytes, 'RSAES-PKCS1-V1_5')
|
|
||||||
}
|
|
||||||
|
|
||||||
equals (key) {
|
|
||||||
return this.bytes.equals(key.bytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
hash (callback) {
|
|
||||||
ensure(callback)
|
|
||||||
multihashing(this.bytes, 'sha2-256', callback)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class RsaPrivateKey {
|
|
||||||
// key - Object of the jwk format
|
|
||||||
// publicKey - Buffer of the spki format
|
|
||||||
constructor (key, publicKey) {
|
|
||||||
this._key = key
|
|
||||||
this._publicKey = publicKey
|
|
||||||
}
|
|
||||||
|
|
||||||
genSecret () {
|
|
||||||
return crypto.getRandomValues(new Uint8Array(16))
|
|
||||||
}
|
|
||||||
|
|
||||||
sign (message, callback) {
|
|
||||||
ensure(callback)
|
|
||||||
crypto.hashAndSign(this._key, message, callback)
|
|
||||||
}
|
|
||||||
|
|
||||||
get public () {
|
|
||||||
if (!this._publicKey) {
|
|
||||||
throw new Error('public key not provided')
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return new RsaPublicKey(this._publicKey)
|
} catch (e) {
|
||||||
|
if (process.env.LP2P_FORCE_CRYPTO_LIB === 'ursa') {
|
||||||
|
throw e
|
||||||
}
|
}
|
||||||
|
|
||||||
decrypt (msg, callback) {
|
keypair = require('keypair')
|
||||||
crypto.decrypt(this._key, msg, callback)
|
|
||||||
}
|
|
||||||
|
|
||||||
marshal () {
|
|
||||||
return crypto.jwkToPkcs1(this._key)
|
|
||||||
}
|
|
||||||
|
|
||||||
get bytes () {
|
|
||||||
return pbm.PrivateKey.encode({
|
|
||||||
Type: pbm.KeyType.RSA,
|
|
||||||
Data: this.marshal()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
equals (key) {
|
|
||||||
return this.bytes.equals(key.bytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
hash (callback) {
|
|
||||||
ensure(callback)
|
|
||||||
multihashing(this.bytes, 'sha2-256', callback)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
const setImmediate = require('async/setImmediate')
|
||||||
|
const pemToJwk = require('pem-jwk').pem2jwk
|
||||||
|
const jwkToPem = require('pem-jwk').jwk2pem
|
||||||
|
|
||||||
function unmarshalRsaPrivateKey (bytes, callback) {
|
exports.utils = require('./rsa-utils')
|
||||||
const jwk = crypto.pkcs1ToJwk(bytes)
|
|
||||||
crypto.unmarshalPrivateKey(jwk, (err, keys) => {
|
exports.generateKey = function (bits, callback) {
|
||||||
if (err) {
|
setImmediate(() => {
|
||||||
|
let result
|
||||||
|
try {
|
||||||
|
const key = keypair({ bits: bits })
|
||||||
|
result = {
|
||||||
|
privateKey: pemToJwk(key.private),
|
||||||
|
publicKey: pemToJwk(key.public)
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
return callback(err)
|
return callback(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
callback(null, new RsaPrivateKey(keys.privateKey, keys.publicKey))
|
callback(null, result)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function unmarshalRsaPublicKey (bytes) {
|
// Takes a jwk key
|
||||||
const jwk = crypto.pkixToJwk(bytes)
|
exports.unmarshalPrivateKey = function (key, callback) {
|
||||||
|
setImmediate(() => {
|
||||||
return new RsaPublicKey(jwk)
|
if (!key) {
|
||||||
|
return callback(new Error('Key is invalid'))
|
||||||
|
}
|
||||||
|
callback(null, {
|
||||||
|
privateKey: key,
|
||||||
|
publicKey: {
|
||||||
|
kty: key.kty,
|
||||||
|
n: key.n,
|
||||||
|
e: key.e
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function generateKeyPair (bits, cb) {
|
exports.getRandomValues = function (arr) {
|
||||||
crypto.generateKey(bits, (err, keys) => {
|
return crypto.randomBytes(arr.length)
|
||||||
if (err) {
|
}
|
||||||
return cb(err)
|
|
||||||
|
exports.hashAndSign = function (key, msg, callback) {
|
||||||
|
setImmediate(() => {
|
||||||
|
let result
|
||||||
|
try {
|
||||||
|
const sign = crypto.createSign('RSA-SHA256')
|
||||||
|
sign.update(msg)
|
||||||
|
const pem = jwkToPem(key)
|
||||||
|
result = sign.sign(pem)
|
||||||
|
} catch (err) {
|
||||||
|
return callback(new Error('Key or message is invalid!: ' + err.message))
|
||||||
}
|
}
|
||||||
|
|
||||||
cb(null, new RsaPrivateKey(keys.privateKey, keys.publicKey))
|
callback(null, result)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function ensure (cb) {
|
exports.hashAndVerify = function (key, sig, msg, callback) {
|
||||||
if (typeof cb !== 'function') {
|
setImmediate(() => {
|
||||||
throw new Error('callback is required')
|
let result
|
||||||
}
|
try {
|
||||||
}
|
const verify = crypto.createVerify('RSA-SHA256')
|
||||||
|
verify.update(msg)
|
||||||
|
const pem = jwkToPem(key)
|
||||||
|
result = verify.verify(pem, sig)
|
||||||
|
} catch (err) {
|
||||||
|
return callback(new Error('Key or message is invalid!:' + err.message))
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
callback(null, result)
|
||||||
RsaPublicKey,
|
})
|
||||||
RsaPrivateKey,
|
|
||||||
unmarshalRsaPublicKey,
|
|
||||||
unmarshalRsaPrivateKey,
|
|
||||||
generateKeyPair
|
|
||||||
}
|
}
|
||||||
|
11
src/nodeify.js
Normal file
11
src/nodeify.js
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
// Based on npmjs.com/nodeify but without additional `nextTick` calls
|
||||||
|
// to keep the overhead low
|
||||||
|
module.exports = function nodeify (promise, cb) {
|
||||||
|
return promise.then((res) => {
|
||||||
|
cb(null, res)
|
||||||
|
}, (err) => {
|
||||||
|
cb(err)
|
||||||
|
})
|
||||||
|
}
|
42
src/pbkdf2.js
Normal file
42
src/pbkdf2.js
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const forge = require('node-forge')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maps an IPFS hash name to its node-forge equivalent.
|
||||||
|
*
|
||||||
|
* See https://github.com/multiformats/multihash/blob/master/hashtable.csv
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
const hashName = {
|
||||||
|
sha1: 'sha1',
|
||||||
|
'sha2-256': 'sha256',
|
||||||
|
'sha2-512': 'sha512'
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes the Password-Based Key Derivation Function 2.
|
||||||
|
*
|
||||||
|
* @param {string} password
|
||||||
|
* @param {string} salt
|
||||||
|
* @param {number} iterations
|
||||||
|
* @param {number} keySize (in bytes)
|
||||||
|
* @param {string} hash - The hash name ('sha1', 'sha2-512, ...)
|
||||||
|
* @returns {string} - A new password
|
||||||
|
*/
|
||||||
|
function pbkdf2 (password, salt, iterations, keySize, hash) {
|
||||||
|
const hasher = hashName[hash]
|
||||||
|
if (!hasher) {
|
||||||
|
throw new Error(`Hash '${hash}' is unknown or not supported`)
|
||||||
|
}
|
||||||
|
const dek = forge.pkcs5.pbkdf2(
|
||||||
|
password,
|
||||||
|
salt,
|
||||||
|
iterations,
|
||||||
|
keySize,
|
||||||
|
hasher)
|
||||||
|
return forge.util.encode64(dek)
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = pbkdf2
|
13
src/random-bytes.js
Normal file
13
src/random-bytes.js
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const rsa = require('./keys/rsa')
|
||||||
|
|
||||||
|
function randomBytes (number) {
|
||||||
|
if (!number || typeof number !== 'number') {
|
||||||
|
throw new Error('first argument must be a Number bigger than 0')
|
||||||
|
}
|
||||||
|
|
||||||
|
return rsa.getRandomValues(new Uint8Array(number))
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = randomBytes
|
@@ -4,13 +4,14 @@ const BN = require('asn1.js').bignum
|
|||||||
|
|
||||||
// Convert a BN.js instance to a base64 encoded string without padding
|
// Convert a BN.js instance to a base64 encoded string without padding
|
||||||
// Adapted from https://tools.ietf.org/html/draft-ietf-jose-json-web-signature-41#appendix-C
|
// Adapted from https://tools.ietf.org/html/draft-ietf-jose-json-web-signature-41#appendix-C
|
||||||
exports.toBase64 = function toBase64 (bn) {
|
exports.toBase64 = function toBase64 (bn, len) {
|
||||||
let s = bn.toBuffer('be').toString('base64')
|
// if len is defined then the bytes are leading-0 padded to the length
|
||||||
|
let s = bn.toArrayLike(Buffer, 'be', len).toString('base64')
|
||||||
|
|
||||||
return s
|
return s
|
||||||
.replace(/(=*)$/, '') // Remove any trailing '='s
|
.replace(/(=*)$/, '') // Remove any trailing '='s
|
||||||
.replace(/\+/g, '-') // 62nd char of encoding
|
.replace(/\+/g, '-') // 62nd char of encoding
|
||||||
.replace(/\//g, '_') // 63rd char of encoding
|
.replace(/\//g, '_') // 63rd char of encoding
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert a base64 encoded string to a BN.js instance
|
// Convert a base64 encoded string to a BN.js instance
|
16
src/webcrypto.js
Normal file
16
src/webcrypto.js
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
/* global self */
|
||||||
|
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
module.exports = () => {
|
||||||
|
// This is only a shim for interfaces, not for functionality
|
||||||
|
if (typeof self !== 'undefined') {
|
||||||
|
require('webcrypto-shim')(self)
|
||||||
|
|
||||||
|
if (self.crypto) {
|
||||||
|
return self.crypto
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error('Please use an environment with crypto support')
|
||||||
|
}
|
@@ -1,37 +0,0 @@
|
|||||||
/* eslint max-nested-callbacks: ["error", 8] */
|
|
||||||
/* eslint-env mocha */
|
|
||||||
'use strict'
|
|
||||||
|
|
||||||
const expect = require('chai').expect
|
|
||||||
const crypto = require('../src')
|
|
||||||
|
|
||||||
const bytes = {
|
|
||||||
16: 'AES-128',
|
|
||||||
32: 'AES-256'
|
|
||||||
}
|
|
||||||
|
|
||||||
describe('AES-CTR', () => {
|
|
||||||
Object.keys(bytes).forEach((byte) => {
|
|
||||||
it(`${bytes[byte]} - encrypt and decrypt`, (done) => {
|
|
||||||
const key = new Buffer(parseInt(byte, 10))
|
|
||||||
key.fill(5)
|
|
||||||
|
|
||||||
const iv = new Buffer(16)
|
|
||||||
iv.fill(1)
|
|
||||||
|
|
||||||
crypto.aes.create(key, iv, (err, cipher) => {
|
|
||||||
expect(err).to.not.exist
|
|
||||||
|
|
||||||
cipher.encrypt(new Buffer('hello'), (err, res) => {
|
|
||||||
expect(err).to.not.exist
|
|
||||||
|
|
||||||
cipher.decrypt(res, (err, res) => {
|
|
||||||
expect(err).to.not.exist
|
|
||||||
expect(res).to.be.eql(new Buffer('hello'))
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
119
test/aes/aes.spec.js
Normal file
119
test/aes/aes.spec.js
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
/* eslint max-nested-callbacks: ["error", 8] */
|
||||||
|
/* eslint-env mocha */
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
const chai = require('chai')
|
||||||
|
const dirtyChai = require('dirty-chai')
|
||||||
|
const expect = chai.expect
|
||||||
|
chai.use(dirtyChai)
|
||||||
|
const series = require('async/series')
|
||||||
|
|
||||||
|
const crypto = require('../../src')
|
||||||
|
const fixtures = require('./../fixtures/aes')
|
||||||
|
const goFixtures = require('./../fixtures/go-aes')
|
||||||
|
|
||||||
|
const bytes = {
|
||||||
|
16: 'AES-128',
|
||||||
|
32: 'AES-256'
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('AES-CTR', () => {
|
||||||
|
Object.keys(bytes).forEach((byte) => {
|
||||||
|
it(`${bytes[byte]} - encrypt and decrypt`, (done) => {
|
||||||
|
const key = Buffer.alloc(parseInt(byte, 10))
|
||||||
|
key.fill(5)
|
||||||
|
|
||||||
|
const iv = Buffer.alloc(16)
|
||||||
|
iv.fill(1)
|
||||||
|
|
||||||
|
crypto.aes.create(key, iv, (err, cipher) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
|
||||||
|
series([
|
||||||
|
encryptAndDecrypt(cipher),
|
||||||
|
encryptAndDecrypt(cipher),
|
||||||
|
encryptAndDecrypt(cipher),
|
||||||
|
encryptAndDecrypt(cipher),
|
||||||
|
encryptAndDecrypt(cipher)
|
||||||
|
], done)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Object.keys(bytes).forEach((byte) => {
|
||||||
|
it(`${bytes[byte]} - fixed - encrypt and decrypt`, (done) => {
|
||||||
|
const key = Buffer.alloc(parseInt(byte, 10))
|
||||||
|
key.fill(5)
|
||||||
|
|
||||||
|
const iv = Buffer.alloc(16)
|
||||||
|
iv.fill(1)
|
||||||
|
|
||||||
|
crypto.aes.create(key, iv, (err, cipher) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
|
||||||
|
series(fixtures[byte].inputs.map((rawIn, i) => (cb) => {
|
||||||
|
const input = Buffer.from(rawIn)
|
||||||
|
const output = Buffer.from(fixtures[byte].outputs[i])
|
||||||
|
cipher.encrypt(input, (err, res) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
expect(res).to.have.length(output.length)
|
||||||
|
expect(res).to.eql(output)
|
||||||
|
cipher.decrypt(res, (err, res) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
expect(res).to.eql(input)
|
||||||
|
cb()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}), done)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Object.keys(bytes).forEach((byte) => {
|
||||||
|
if (!goFixtures[byte]) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
it(`${bytes[byte]} - go interop - encrypt and decrypt`, (done) => {
|
||||||
|
const key = Buffer.alloc(parseInt(byte, 10))
|
||||||
|
key.fill(5)
|
||||||
|
|
||||||
|
const iv = Buffer.alloc(16)
|
||||||
|
iv.fill(1)
|
||||||
|
|
||||||
|
crypto.aes.create(key, iv, (err, cipher) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
|
||||||
|
series(goFixtures[byte].inputs.map((rawIn, i) => (cb) => {
|
||||||
|
const input = Buffer.from(rawIn)
|
||||||
|
const output = Buffer.from(goFixtures[byte].outputs[i])
|
||||||
|
cipher.encrypt(input, (err, res) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
expect(res).to.have.length(output.length)
|
||||||
|
expect(res).to.be.eql(output)
|
||||||
|
cipher.decrypt(res, (err, res) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
expect(res).to.be.eql(input)
|
||||||
|
cb()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}), done)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
function encryptAndDecrypt (cipher) {
|
||||||
|
const data = Buffer.alloc(100)
|
||||||
|
data.fill(Math.ceil(Math.random() * 100))
|
||||||
|
return (cb) => {
|
||||||
|
cipher.encrypt(data, (err, res) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
cipher.decrypt(res, (err, res) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
expect(res).to.be.eql(data)
|
||||||
|
cb()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
150
test/crypto.spec.js
Normal file
150
test/crypto.spec.js
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
/* eslint max-nested-callbacks: ["error", 8] */
|
||||||
|
/* eslint-env mocha */
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
const chai = require('chai')
|
||||||
|
const dirtyChai = require('dirty-chai')
|
||||||
|
const expect = chai.expect
|
||||||
|
chai.use(dirtyChai)
|
||||||
|
const crypto = require('../src')
|
||||||
|
const fixtures = require('./fixtures/go-key-rsa')
|
||||||
|
|
||||||
|
describe('libp2p-crypto', function () {
|
||||||
|
this.timeout(20 * 1000)
|
||||||
|
let key
|
||||||
|
before((done) => {
|
||||||
|
crypto.keys.generateKeyPair('RSA', 512, (err, _key) => {
|
||||||
|
if (err) {
|
||||||
|
return done(err)
|
||||||
|
}
|
||||||
|
key = _key
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('marshalPublicKey and unmarshalPublicKey', () => {
|
||||||
|
const key2 = crypto.keys.unmarshalPublicKey(
|
||||||
|
crypto.keys.marshalPublicKey(key.public))
|
||||||
|
|
||||||
|
expect(key2.equals(key.public)).to.be.eql(true)
|
||||||
|
|
||||||
|
expect(() => {
|
||||||
|
crypto.keys.marshalPublicKey(key.public, 'invalid-key-type')
|
||||||
|
}).to.throw()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('marshalPrivateKey and unmarshalPrivateKey', (done) => {
|
||||||
|
expect(() => {
|
||||||
|
crypto.keys.marshalPrivateKey(key, 'invalid-key-type')
|
||||||
|
}).to.throw()
|
||||||
|
|
||||||
|
crypto.keys.unmarshalPrivateKey(crypto.keys.marshalPrivateKey(key), (err, key2) => {
|
||||||
|
if (err) {
|
||||||
|
return done(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(key2.equals(key)).to.be.eql(true)
|
||||||
|
expect(key2.public.equals(key.public)).to.be.eql(true)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// marshalled keys seem to be slightly different
|
||||||
|
// unsure as to if this is just a difference in encoding
|
||||||
|
// or a bug
|
||||||
|
describe('go interop', () => {
|
||||||
|
it('unmarshals private key', (done) => {
|
||||||
|
crypto.keys.unmarshalPrivateKey(fixtures.private.key, (err, key) => {
|
||||||
|
if (err) {
|
||||||
|
return done(err)
|
||||||
|
}
|
||||||
|
const hash = fixtures.private.hash
|
||||||
|
expect(fixtures.private.key).to.eql(key.bytes)
|
||||||
|
|
||||||
|
key.hash((err, digest) => {
|
||||||
|
if (err) {
|
||||||
|
return done(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(digest).to.eql(hash)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('unmarshals public key', (done) => {
|
||||||
|
const key = crypto.keys.unmarshalPublicKey(fixtures.public.key)
|
||||||
|
const hash = fixtures.public.hash
|
||||||
|
|
||||||
|
expect(crypto.keys.marshalPublicKey(key)).to.eql(fixtures.public.key)
|
||||||
|
|
||||||
|
key.hash((err, digest) => {
|
||||||
|
if (err) {
|
||||||
|
return done(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(digest).to.eql(hash)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('unmarshal -> marshal, private key', (done) => {
|
||||||
|
crypto.keys.unmarshalPrivateKey(fixtures.private.key, (err, key) => {
|
||||||
|
if (err) {
|
||||||
|
return done(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
const marshalled = crypto.keys.marshalPrivateKey(key)
|
||||||
|
expect(marshalled).to.eql(fixtures.private.key)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('unmarshal -> marshal, public key', () => {
|
||||||
|
const key = crypto.keys.unmarshalPublicKey(fixtures.public.key)
|
||||||
|
const marshalled = crypto.keys.marshalPublicKey(key)
|
||||||
|
expect(fixtures.public.key.equals(marshalled)).to.eql(true)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('pbkdf2', () => {
|
||||||
|
it('generates a derived password using sha1', () => {
|
||||||
|
const p1 = crypto.pbkdf2('password', 'at least 16 character salt', 500, 512 / 8, 'sha1')
|
||||||
|
expect(p1).to.exist()
|
||||||
|
expect(p1).to.be.a('string')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('generates a derived password using sha2-512', () => {
|
||||||
|
const p1 = crypto.pbkdf2('password', 'at least 16 character salt', 500, 512 / 8, 'sha2-512')
|
||||||
|
expect(p1).to.exist()
|
||||||
|
expect(p1).to.be.a('string')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('generates the same derived password with the same options', () => {
|
||||||
|
const p1 = crypto.pbkdf2('password', 'at least 16 character salt', 10, 512 / 8, 'sha1')
|
||||||
|
const p2 = crypto.pbkdf2('password', 'at least 16 character salt', 10, 512 / 8, 'sha1')
|
||||||
|
const p3 = crypto.pbkdf2('password', 'at least 16 character salt', 11, 512 / 8, 'sha1')
|
||||||
|
expect(p2).to.equal(p1)
|
||||||
|
expect(p3).to.not.equal(p2)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('throws on invalid hash name', () => {
|
||||||
|
expect(() => crypto.pbkdf2('password', 'at least 16 character salt', 500, 512 / 8, 'shaX-xxx')).to.throw()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('randomBytes', () => {
|
||||||
|
it('throws with no number passed', () => {
|
||||||
|
expect(() => {
|
||||||
|
crypto.randomBytes()
|
||||||
|
}).to.throw()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('generates different random things', () => {
|
||||||
|
const buf1 = crypto.randomBytes(10)
|
||||||
|
expect(buf1.length).to.equal(10)
|
||||||
|
const buf2 = crypto.randomBytes(10)
|
||||||
|
expect(buf1).to.not.eql(buf2)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
@@ -1,53 +0,0 @@
|
|||||||
/* eslint max-nested-callbacks: ["error", 8] */
|
|
||||||
/* eslint-env mocha */
|
|
||||||
'use strict'
|
|
||||||
|
|
||||||
const expect = require('chai').expect
|
|
||||||
const parallel = require('async/parallel')
|
|
||||||
|
|
||||||
const fixtures = require('./fixtures/go-elliptic-key')
|
|
||||||
const crypto = require('../src')
|
|
||||||
|
|
||||||
const curves = ['P-256', 'P-384'] // 'P-521' fails in tests :( no clue why
|
|
||||||
const lengths = {
|
|
||||||
'P-256': 65,
|
|
||||||
'P-384': 97,
|
|
||||||
'P-521': 133
|
|
||||||
}
|
|
||||||
|
|
||||||
describe('generateEphemeralKeyPair', () => {
|
|
||||||
curves.forEach((curve) => {
|
|
||||||
it(`generate and shared key ${curve}`, (done) => {
|
|
||||||
parallel([
|
|
||||||
(cb) => crypto.generateEphemeralKeyPair(curve, cb),
|
|
||||||
(cb) => crypto.generateEphemeralKeyPair(curve, cb)
|
|
||||||
], (err, keys) => {
|
|
||||||
expect(err).to.not.exist
|
|
||||||
expect(keys[0].key).to.have.length(lengths[curve])
|
|
||||||
expect(keys[1].key).to.have.length(lengths[curve])
|
|
||||||
|
|
||||||
keys[0].genSharedKey(keys[1].key, (err, shared) => {
|
|
||||||
expect(err).to.not.exist
|
|
||||||
expect(shared).to.have.length(32)
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('go interop', () => {
|
|
||||||
it('generates a shared secret', (done) => {
|
|
||||||
const curve = fixtures.curve
|
|
||||||
|
|
||||||
crypto.generateEphemeralKeyPair(curve, (err, alice) => {
|
|
||||||
expect(err).to.not.exist
|
|
||||||
|
|
||||||
alice.genSharedKey(fixtures.bob.public, (err, s1) => {
|
|
||||||
expect(err).to.not.exist
|
|
||||||
expect(s1).to.have.length(32)
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
27
test/fixtures/aes.js
vendored
Normal file
27
test/fixtures/aes.js
vendored
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const fixes16 = [
|
||||||
|
require('./fix1.json'),
|
||||||
|
require('./fix2.json'),
|
||||||
|
require('./fix3.json'),
|
||||||
|
require('./fix4.json'),
|
||||||
|
require('./fix5.json')
|
||||||
|
]
|
||||||
|
const fixes32 = [
|
||||||
|
require('./fix6.json'),
|
||||||
|
require('./fix7.json'),
|
||||||
|
require('./fix8.json'),
|
||||||
|
require('./fix9.json'),
|
||||||
|
require('./fix10.json')
|
||||||
|
]
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
16: {
|
||||||
|
inputs: fixes16.map((f) => f.input),
|
||||||
|
outputs: fixes16.map((f) => f.output)
|
||||||
|
},
|
||||||
|
32: {
|
||||||
|
inputs: fixes32.map((f) => f.input),
|
||||||
|
outputs: fixes32.map((f) => f.output)
|
||||||
|
}
|
||||||
|
}
|
212
test/fixtures/fix1.json
vendored
Normal file
212
test/fixtures/fix1.json
vendored
Normal file
@@ -0,0 +1,212 @@
|
|||||||
|
{
|
||||||
|
"input": {
|
||||||
|
"type": "Buffer",
|
||||||
|
"data": [
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47,
|
||||||
|
47
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"output": {
|
||||||
|
"type": "Buffer",
|
||||||
|
"data": [
|
||||||
|
121,
|
||||||
|
104,
|
||||||
|
0,
|
||||||
|
151,
|
||||||
|
57,
|
||||||
|
137,
|
||||||
|
22,
|
||||||
|
239,
|
||||||
|
234,
|
||||||
|
151,
|
||||||
|
58,
|
||||||
|
15,
|
||||||
|
100,
|
||||||
|
22,
|
||||||
|
228,
|
||||||
|
110,
|
||||||
|
85,
|
||||||
|
248,
|
||||||
|
249,
|
||||||
|
15,
|
||||||
|
145,
|
||||||
|
128,
|
||||||
|
223,
|
||||||
|
25,
|
||||||
|
192,
|
||||||
|
175,
|
||||||
|
132,
|
||||||
|
169,
|
||||||
|
98,
|
||||||
|
203,
|
||||||
|
231,
|
||||||
|
106,
|
||||||
|
224,
|
||||||
|
102,
|
||||||
|
206,
|
||||||
|
244,
|
||||||
|
29,
|
||||||
|
213,
|
||||||
|
36,
|
||||||
|
2,
|
||||||
|
26,
|
||||||
|
213,
|
||||||
|
94,
|
||||||
|
29,
|
||||||
|
134,
|
||||||
|
219,
|
||||||
|
136,
|
||||||
|
73,
|
||||||
|
212,
|
||||||
|
176,
|
||||||
|
33,
|
||||||
|
95,
|
||||||
|
198,
|
||||||
|
91,
|
||||||
|
148,
|
||||||
|
139,
|
||||||
|
132,
|
||||||
|
252,
|
||||||
|
182,
|
||||||
|
115,
|
||||||
|
116,
|
||||||
|
160,
|
||||||
|
146,
|
||||||
|
194,
|
||||||
|
0,
|
||||||
|
97,
|
||||||
|
181,
|
||||||
|
0,
|
||||||
|
193,
|
||||||
|
149,
|
||||||
|
21,
|
||||||
|
51,
|
||||||
|
248,
|
||||||
|
97,
|
||||||
|
32,
|
||||||
|
62,
|
||||||
|
86,
|
||||||
|
153,
|
||||||
|
238,
|
||||||
|
67,
|
||||||
|
38,
|
||||||
|
34,
|
||||||
|
55,
|
||||||
|
143,
|
||||||
|
70,
|
||||||
|
193,
|
||||||
|
99,
|
||||||
|
107,
|
||||||
|
31,
|
||||||
|
67,
|
||||||
|
90,
|
||||||
|
97,
|
||||||
|
55,
|
||||||
|
63,
|
||||||
|
69,
|
||||||
|
203,
|
||||||
|
33,
|
||||||
|
233,
|
||||||
|
74,
|
||||||
|
237
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
212
test/fixtures/fix10.json
vendored
Normal file
212
test/fixtures/fix10.json
vendored
Normal file
@@ -0,0 +1,212 @@
|
|||||||
|
{
|
||||||
|
"input": {
|
||||||
|
"type": "Buffer",
|
||||||
|
"data": [
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72,
|
||||||
|
72
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"output": {
|
||||||
|
"type": "Buffer",
|
||||||
|
"data": [
|
||||||
|
201,
|
||||||
|
224,
|
||||||
|
56,
|
||||||
|
64,
|
||||||
|
167,
|
||||||
|
224,
|
||||||
|
124,
|
||||||
|
49,
|
||||||
|
19,
|
||||||
|
51,
|
||||||
|
208,
|
||||||
|
226,
|
||||||
|
216,
|
||||||
|
50,
|
||||||
|
12,
|
||||||
|
73,
|
||||||
|
15,
|
||||||
|
255,
|
||||||
|
156,
|
||||||
|
108,
|
||||||
|
98,
|
||||||
|
179,
|
||||||
|
144,
|
||||||
|
110,
|
||||||
|
33,
|
||||||
|
151,
|
||||||
|
43,
|
||||||
|
64,
|
||||||
|
227,
|
||||||
|
153,
|
||||||
|
120,
|
||||||
|
39,
|
||||||
|
21,
|
||||||
|
151,
|
||||||
|
41,
|
||||||
|
61,
|
||||||
|
245,
|
||||||
|
20,
|
||||||
|
31,
|
||||||
|
23,
|
||||||
|
109,
|
||||||
|
213,
|
||||||
|
109,
|
||||||
|
55,
|
||||||
|
35,
|
||||||
|
40,
|
||||||
|
122,
|
||||||
|
109,
|
||||||
|
41,
|
||||||
|
10,
|
||||||
|
32,
|
||||||
|
176,
|
||||||
|
25,
|
||||||
|
184,
|
||||||
|
91,
|
||||||
|
176,
|
||||||
|
177,
|
||||||
|
134,
|
||||||
|
138,
|
||||||
|
252,
|
||||||
|
160,
|
||||||
|
2,
|
||||||
|
108,
|
||||||
|
43,
|
||||||
|
222,
|
||||||
|
239,
|
||||||
|
174,
|
||||||
|
2,
|
||||||
|
145,
|
||||||
|
74,
|
||||||
|
34,
|
||||||
|
131,
|
||||||
|
237,
|
||||||
|
214,
|
||||||
|
235,
|
||||||
|
102,
|
||||||
|
26,
|
||||||
|
204,
|
||||||
|
124,
|
||||||
|
64,
|
||||||
|
101,
|
||||||
|
134,
|
||||||
|
186,
|
||||||
|
45,
|
||||||
|
55,
|
||||||
|
29,
|
||||||
|
52,
|
||||||
|
55,
|
||||||
|
171,
|
||||||
|
95,
|
||||||
|
172,
|
||||||
|
86,
|
||||||
|
242,
|
||||||
|
101,
|
||||||
|
141,
|
||||||
|
153,
|
||||||
|
222,
|
||||||
|
161,
|
||||||
|
128,
|
||||||
|
83
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
212
test/fixtures/fix2.json
vendored
Normal file
212
test/fixtures/fix2.json
vendored
Normal file
@@ -0,0 +1,212 @@
|
|||||||
|
{
|
||||||
|
"input": {
|
||||||
|
"type": "Buffer",
|
||||||
|
"data": [
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24,
|
||||||
|
24
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"output": {
|
||||||
|
"type": "Buffer",
|
||||||
|
"data": [
|
||||||
|
109,
|
||||||
|
172,
|
||||||
|
127,
|
||||||
|
179,
|
||||||
|
110,
|
||||||
|
222,
|
||||||
|
79,
|
||||||
|
219,
|
||||||
|
87,
|
||||||
|
76,
|
||||||
|
70,
|
||||||
|
204,
|
||||||
|
166,
|
||||||
|
110,
|
||||||
|
184,
|
||||||
|
229,
|
||||||
|
90,
|
||||||
|
49,
|
||||||
|
160,
|
||||||
|
252,
|
||||||
|
78,
|
||||||
|
58,
|
||||||
|
73,
|
||||||
|
51,
|
||||||
|
152,
|
||||||
|
218,
|
||||||
|
3,
|
||||||
|
200,
|
||||||
|
10,
|
||||||
|
124,
|
||||||
|
152,
|
||||||
|
117,
|
||||||
|
137,
|
||||||
|
40,
|
||||||
|
23,
|
||||||
|
127,
|
||||||
|
56,
|
||||||
|
57,
|
||||||
|
203,
|
||||||
|
31,
|
||||||
|
101,
|
||||||
|
227,
|
||||||
|
31,
|
||||||
|
198,
|
||||||
|
223,
|
||||||
|
86,
|
||||||
|
98,
|
||||||
|
120,
|
||||||
|
100,
|
||||||
|
86,
|
||||||
|
116,
|
||||||
|
144,
|
||||||
|
142,
|
||||||
|
127,
|
||||||
|
68,
|
||||||
|
175,
|
||||||
|
249,
|
||||||
|
232,
|
||||||
|
22,
|
||||||
|
83,
|
||||||
|
22,
|
||||||
|
68,
|
||||||
|
60,
|
||||||
|
230,
|
||||||
|
146,
|
||||||
|
22,
|
||||||
|
153,
|
||||||
|
193,
|
||||||
|
67,
|
||||||
|
5,
|
||||||
|
51,
|
||||||
|
253,
|
||||||
|
239,
|
||||||
|
210,
|
||||||
|
80,
|
||||||
|
31,
|
||||||
|
254,
|
||||||
|
103,
|
||||||
|
185,
|
||||||
|
145,
|
||||||
|
123,
|
||||||
|
99,
|
||||||
|
205,
|
||||||
|
175,
|
||||||
|
156,
|
||||||
|
144,
|
||||||
|
191,
|
||||||
|
67,
|
||||||
|
31,
|
||||||
|
236,
|
||||||
|
43,
|
||||||
|
98,
|
||||||
|
197,
|
||||||
|
235,
|
||||||
|
31,
|
||||||
|
50,
|
||||||
|
69,
|
||||||
|
228,
|
||||||
|
100,
|
||||||
|
64
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
212
test/fixtures/fix3.json
vendored
Normal file
212
test/fixtures/fix3.json
vendored
Normal file
@@ -0,0 +1,212 @@
|
|||||||
|
{
|
||||||
|
"input": {
|
||||||
|
"type": "Buffer",
|
||||||
|
"data": [
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"output": {
|
||||||
|
"type": "Buffer",
|
||||||
|
"data": [
|
||||||
|
191,
|
||||||
|
93,
|
||||||
|
126,
|
||||||
|
191,
|
||||||
|
180,
|
||||||
|
42,
|
||||||
|
118,
|
||||||
|
144,
|
||||||
|
28,
|
||||||
|
188,
|
||||||
|
211,
|
||||||
|
191,
|
||||||
|
211,
|
||||||
|
130,
|
||||||
|
170,
|
||||||
|
153,
|
||||||
|
134,
|
||||||
|
240,
|
||||||
|
179,
|
||||||
|
83,
|
||||||
|
75,
|
||||||
|
23,
|
||||||
|
42,
|
||||||
|
68,
|
||||||
|
158,
|
||||||
|
200,
|
||||||
|
123,
|
||||||
|
155,
|
||||||
|
57,
|
||||||
|
169,
|
||||||
|
152,
|
||||||
|
133,
|
||||||
|
33,
|
||||||
|
114,
|
||||||
|
90,
|
||||||
|
29,
|
||||||
|
131,
|
||||||
|
91,
|
||||||
|
70,
|
||||||
|
105,
|
||||||
|
83,
|
||||||
|
45,
|
||||||
|
40,
|
||||||
|
47,
|
||||||
|
77,
|
||||||
|
96,
|
||||||
|
97,
|
||||||
|
8,
|
||||||
|
40,
|
||||||
|
1,
|
||||||
|
110,
|
||||||
|
245,
|
||||||
|
106,
|
||||||
|
172,
|
||||||
|
152,
|
||||||
|
146,
|
||||||
|
5,
|
||||||
|
114,
|
||||||
|
132,
|
||||||
|
0,
|
||||||
|
179,
|
||||||
|
31,
|
||||||
|
44,
|
||||||
|
78,
|
||||||
|
19,
|
||||||
|
109,
|
||||||
|
92,
|
||||||
|
199,
|
||||||
|
226,
|
||||||
|
36,
|
||||||
|
12,
|
||||||
|
74,
|
||||||
|
180,
|
||||||
|
241,
|
||||||
|
224,
|
||||||
|
107,
|
||||||
|
83,
|
||||||
|
13,
|
||||||
|
167,
|
||||||
|
27,
|
||||||
|
251,
|
||||||
|
101,
|
||||||
|
193,
|
||||||
|
98,
|
||||||
|
49,
|
||||||
|
90,
|
||||||
|
225,
|
||||||
|
197,
|
||||||
|
75,
|
||||||
|
213,
|
||||||
|
144,
|
||||||
|
52,
|
||||||
|
235,
|
||||||
|
130,
|
||||||
|
92,
|
||||||
|
247,
|
||||||
|
219,
|
||||||
|
139,
|
||||||
|
209,
|
||||||
|
132
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
212
test/fixtures/fix4.json
vendored
Normal file
212
test/fixtures/fix4.json
vendored
Normal file
@@ -0,0 +1,212 @@
|
|||||||
|
{
|
||||||
|
"input": {
|
||||||
|
"type": "Buffer",
|
||||||
|
"data": [
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"output": {
|
||||||
|
"type": "Buffer",
|
||||||
|
"data": [
|
||||||
|
191,
|
||||||
|
110,
|
||||||
|
53,
|
||||||
|
190,
|
||||||
|
250,
|
||||||
|
44,
|
||||||
|
190,
|
||||||
|
136,
|
||||||
|
22,
|
||||||
|
209,
|
||||||
|
131,
|
||||||
|
200,
|
||||||
|
112,
|
||||||
|
31,
|
||||||
|
61,
|
||||||
|
183,
|
||||||
|
247,
|
||||||
|
95,
|
||||||
|
4,
|
||||||
|
249,
|
||||||
|
69,
|
||||||
|
147,
|
||||||
|
238,
|
||||||
|
74,
|
||||||
|
18,
|
||||||
|
71,
|
||||||
|
197,
|
||||||
|
115,
|
||||||
|
141,
|
||||||
|
226,
|
||||||
|
102,
|
||||||
|
92,
|
||||||
|
91,
|
||||||
|
128,
|
||||||
|
181,
|
||||||
|
172,
|
||||||
|
67,
|
||||||
|
109,
|
||||||
|
17,
|
||||||
|
165,
|
||||||
|
52,
|
||||||
|
10,
|
||||||
|
55,
|
||||||
|
31,
|
||||||
|
55,
|
||||||
|
225,
|
||||||
|
253,
|
||||||
|
140,
|
||||||
|
154,
|
||||||
|
35,
|
||||||
|
104,
|
||||||
|
62,
|
||||||
|
119,
|
||||||
|
103,
|
||||||
|
197,
|
||||||
|
152,
|
||||||
|
125,
|
||||||
|
134,
|
||||||
|
140,
|
||||||
|
181,
|
||||||
|
170,
|
||||||
|
76,
|
||||||
|
75,
|
||||||
|
114,
|
||||||
|
195,
|
||||||
|
188,
|
||||||
|
68,
|
||||||
|
197,
|
||||||
|
28,
|
||||||
|
47,
|
||||||
|
116,
|
||||||
|
82,
|
||||||
|
34,
|
||||||
|
128,
|
||||||
|
232,
|
||||||
|
122,
|
||||||
|
14,
|
||||||
|
229,
|
||||||
|
122,
|
||||||
|
161,
|
||||||
|
36,
|
||||||
|
212,
|
||||||
|
161,
|
||||||
|
164,
|
||||||
|
145,
|
||||||
|
86,
|
||||||
|
215,
|
||||||
|
233,
|
||||||
|
222,
|
||||||
|
50,
|
||||||
|
143,
|
||||||
|
89,
|
||||||
|
131,
|
||||||
|
32,
|
||||||
|
130,
|
||||||
|
196,
|
||||||
|
109,
|
||||||
|
36,
|
||||||
|
204,
|
||||||
|
254
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
212
test/fixtures/fix5.json
vendored
Normal file
212
test/fixtures/fix5.json
vendored
Normal file
@@ -0,0 +1,212 @@
|
|||||||
|
{
|
||||||
|
"input": {
|
||||||
|
"type": "Buffer",
|
||||||
|
"data": [
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
48
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"output": {
|
||||||
|
"type": "Buffer",
|
||||||
|
"data": [
|
||||||
|
97,
|
||||||
|
142,
|
||||||
|
8,
|
||||||
|
37,
|
||||||
|
69,
|
||||||
|
173,
|
||||||
|
124,
|
||||||
|
180,
|
||||||
|
97,
|
||||||
|
70,
|
||||||
|
45,
|
||||||
|
91,
|
||||||
|
196,
|
||||||
|
126,
|
||||||
|
184,
|
||||||
|
135,
|
||||||
|
213,
|
||||||
|
104,
|
||||||
|
171,
|
||||||
|
89,
|
||||||
|
231,
|
||||||
|
63,
|
||||||
|
43,
|
||||||
|
42,
|
||||||
|
7,
|
||||||
|
245,
|
||||||
|
75,
|
||||||
|
165,
|
||||||
|
205,
|
||||||
|
182,
|
||||||
|
24,
|
||||||
|
50,
|
||||||
|
170,
|
||||||
|
217,
|
||||||
|
128,
|
||||||
|
112,
|
||||||
|
114,
|
||||||
|
215,
|
||||||
|
209,
|
||||||
|
145,
|
||||||
|
135,
|
||||||
|
235,
|
||||||
|
179,
|
||||||
|
212,
|
||||||
|
5,
|
||||||
|
81,
|
||||||
|
142,
|
||||||
|
199,
|
||||||
|
53,
|
||||||
|
221,
|
||||||
|
39,
|
||||||
|
239,
|
||||||
|
167,
|
||||||
|
21,
|
||||||
|
237,
|
||||||
|
168,
|
||||||
|
145,
|
||||||
|
249,
|
||||||
|
250,
|
||||||
|
108,
|
||||||
|
2,
|
||||||
|
247,
|
||||||
|
89,
|
||||||
|
73,
|
||||||
|
228,
|
||||||
|
227,
|
||||||
|
255,
|
||||||
|
155,
|
||||||
|
121,
|
||||||
|
157,
|
||||||
|
205,
|
||||||
|
96,
|
||||||
|
43,
|
||||||
|
32,
|
||||||
|
112,
|
||||||
|
209,
|
||||||
|
173,
|
||||||
|
96,
|
||||||
|
143,
|
||||||
|
43,
|
||||||
|
220,
|
||||||
|
140,
|
||||||
|
26,
|
||||||
|
205,
|
||||||
|
34,
|
||||||
|
34,
|
||||||
|
53,
|
||||||
|
157,
|
||||||
|
41,
|
||||||
|
167,
|
||||||
|
125,
|
||||||
|
235,
|
||||||
|
243,
|
||||||
|
85,
|
||||||
|
13,
|
||||||
|
14,
|
||||||
|
93,
|
||||||
|
109,
|
||||||
|
233,
|
||||||
|
186
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
212
test/fixtures/fix6.json
vendored
Normal file
212
test/fixtures/fix6.json
vendored
Normal file
@@ -0,0 +1,212 @@
|
|||||||
|
{
|
||||||
|
"input": {
|
||||||
|
"type": "Buffer",
|
||||||
|
"data": [
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68,
|
||||||
|
68
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"output": {
|
||||||
|
"type": "Buffer",
|
||||||
|
"data": [
|
||||||
|
198,
|
||||||
|
59,
|
||||||
|
91,
|
||||||
|
107,
|
||||||
|
222,
|
||||||
|
214,
|
||||||
|
31,
|
||||||
|
230,
|
||||||
|
112,
|
||||||
|
1,
|
||||||
|
199,
|
||||||
|
174,
|
||||||
|
17,
|
||||||
|
224,
|
||||||
|
194,
|
||||||
|
225,
|
||||||
|
138,
|
||||||
|
65,
|
||||||
|
58,
|
||||||
|
160,
|
||||||
|
31,
|
||||||
|
249,
|
||||||
|
102,
|
||||||
|
16,
|
||||||
|
74,
|
||||||
|
46,
|
||||||
|
85,
|
||||||
|
30,
|
||||||
|
232,
|
||||||
|
249,
|
||||||
|
120,
|
||||||
|
108,
|
||||||
|
38,
|
||||||
|
165,
|
||||||
|
105,
|
||||||
|
27,
|
||||||
|
12,
|
||||||
|
98,
|
||||||
|
98,
|
||||||
|
108,
|
||||||
|
130,
|
||||||
|
163,
|
||||||
|
16,
|
||||||
|
137,
|
||||||
|
116,
|
||||||
|
104,
|
||||||
|
153,
|
||||||
|
188,
|
||||||
|
5,
|
||||||
|
251,
|
||||||
|
163,
|
||||||
|
244,
|
||||||
|
0,
|
||||||
|
58,
|
||||||
|
1,
|
||||||
|
207,
|
||||||
|
25,
|
||||||
|
78,
|
||||||
|
188,
|
||||||
|
210,
|
||||||
|
205,
|
||||||
|
221,
|
||||||
|
48,
|
||||||
|
132,
|
||||||
|
72,
|
||||||
|
209,
|
||||||
|
11,
|
||||||
|
67,
|
||||||
|
14,
|
||||||
|
42,
|
||||||
|
218,
|
||||||
|
71,
|
||||||
|
148,
|
||||||
|
252,
|
||||||
|
126,
|
||||||
|
183,
|
||||||
|
60,
|
||||||
|
32,
|
||||||
|
93,
|
||||||
|
36,
|
||||||
|
125,
|
||||||
|
103,
|
||||||
|
191,
|
||||||
|
117,
|
||||||
|
82,
|
||||||
|
241,
|
||||||
|
190,
|
||||||
|
176,
|
||||||
|
1,
|
||||||
|
129,
|
||||||
|
118,
|
||||||
|
112,
|
||||||
|
139,
|
||||||
|
153,
|
||||||
|
178,
|
||||||
|
56,
|
||||||
|
61,
|
||||||
|
91,
|
||||||
|
52,
|
||||||
|
198
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
212
test/fixtures/fix7.json
vendored
Normal file
212
test/fixtures/fix7.json
vendored
Normal file
@@ -0,0 +1,212 @@
|
|||||||
|
{
|
||||||
|
"input": {
|
||||||
|
"type": "Buffer",
|
||||||
|
"data": [
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
10
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"output": {
|
||||||
|
"type": "Buffer",
|
||||||
|
"data": [
|
||||||
|
206,
|
||||||
|
241,
|
||||||
|
99,
|
||||||
|
120,
|
||||||
|
248,
|
||||||
|
163,
|
||||||
|
57,
|
||||||
|
30,
|
||||||
|
216,
|
||||||
|
86,
|
||||||
|
255,
|
||||||
|
192,
|
||||||
|
89,
|
||||||
|
193,
|
||||||
|
176,
|
||||||
|
17,
|
||||||
|
78,
|
||||||
|
62,
|
||||||
|
80,
|
||||||
|
149,
|
||||||
|
189,
|
||||||
|
235,
|
||||||
|
27,
|
||||||
|
157,
|
||||||
|
175,
|
||||||
|
248,
|
||||||
|
7,
|
||||||
|
19,
|
||||||
|
222,
|
||||||
|
64,
|
||||||
|
111,
|
||||||
|
199,
|
||||||
|
204,
|
||||||
|
163,
|
||||||
|
26,
|
||||||
|
16,
|
||||||
|
95,
|
||||||
|
221,
|
||||||
|
70,
|
||||||
|
32,
|
||||||
|
239,
|
||||||
|
4,
|
||||||
|
58,
|
||||||
|
162,
|
||||||
|
253,
|
||||||
|
237,
|
||||||
|
8,
|
||||||
|
51,
|
||||||
|
94,
|
||||||
|
3,
|
||||||
|
165,
|
||||||
|
186,
|
||||||
|
223,
|
||||||
|
210,
|
||||||
|
116,
|
||||||
|
101,
|
||||||
|
228,
|
||||||
|
82,
|
||||||
|
103,
|
||||||
|
76,
|
||||||
|
74,
|
||||||
|
44,
|
||||||
|
51,
|
||||||
|
117,
|
||||||
|
189,
|
||||||
|
140,
|
||||||
|
132,
|
||||||
|
230,
|
||||||
|
188,
|
||||||
|
243,
|
||||||
|
24,
|
||||||
|
158,
|
||||||
|
149,
|
||||||
|
93,
|
||||||
|
147,
|
||||||
|
226,
|
||||||
|
113,
|
||||||
|
195,
|
||||||
|
31,
|
||||||
|
24,
|
||||||
|
9,
|
||||||
|
19,
|
||||||
|
27,
|
||||||
|
132,
|
||||||
|
180,
|
||||||
|
152,
|
||||||
|
26,
|
||||||
|
65,
|
||||||
|
125,
|
||||||
|
144,
|
||||||
|
86,
|
||||||
|
167,
|
||||||
|
41,
|
||||||
|
144,
|
||||||
|
158,
|
||||||
|
204,
|
||||||
|
76,
|
||||||
|
46,
|
||||||
|
181,
|
||||||
|
110
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
212
test/fixtures/fix8.json
vendored
Normal file
212
test/fixtures/fix8.json
vendored
Normal file
@@ -0,0 +1,212 @@
|
|||||||
|
{
|
||||||
|
"input": {
|
||||||
|
"type": "Buffer",
|
||||||
|
"data": [
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75,
|
||||||
|
75
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"output": {
|
||||||
|
"type": "Buffer",
|
||||||
|
"data": [
|
||||||
|
153,
|
||||||
|
161,
|
||||||
|
201,
|
||||||
|
66,
|
||||||
|
87,
|
||||||
|
46,
|
||||||
|
242,
|
||||||
|
87,
|
||||||
|
136,
|
||||||
|
238,
|
||||||
|
151,
|
||||||
|
198,
|
||||||
|
129,
|
||||||
|
122,
|
||||||
|
62,
|
||||||
|
205,
|
||||||
|
142,
|
||||||
|
252,
|
||||||
|
109,
|
||||||
|
187,
|
||||||
|
238,
|
||||||
|
183,
|
||||||
|
63,
|
||||||
|
95,
|
||||||
|
240,
|
||||||
|
97,
|
||||||
|
220,
|
||||||
|
209,
|
||||||
|
37,
|
||||||
|
144,
|
||||||
|
237,
|
||||||
|
84,
|
||||||
|
251,
|
||||||
|
149,
|
||||||
|
152,
|
||||||
|
222,
|
||||||
|
89,
|
||||||
|
200,
|
||||||
|
208,
|
||||||
|
119,
|
||||||
|
213,
|
||||||
|
38,
|
||||||
|
65,
|
||||||
|
19,
|
||||||
|
2,
|
||||||
|
252,
|
||||||
|
193,
|
||||||
|
125,
|
||||||
|
94,
|
||||||
|
76,
|
||||||
|
182,
|
||||||
|
198,
|
||||||
|
243,
|
||||||
|
121,
|
||||||
|
253,
|
||||||
|
16,
|
||||||
|
45,
|
||||||
|
254,
|
||||||
|
82,
|
||||||
|
47,
|
||||||
|
146,
|
||||||
|
206,
|
||||||
|
41,
|
||||||
|
105,
|
||||||
|
254,
|
||||||
|
237,
|
||||||
|
236,
|
||||||
|
141,
|
||||||
|
118,
|
||||||
|
214,
|
||||||
|
197,
|
||||||
|
228,
|
||||||
|
59,
|
||||||
|
125,
|
||||||
|
45,
|
||||||
|
200,
|
||||||
|
61,
|
||||||
|
24,
|
||||||
|
110,
|
||||||
|
26,
|
||||||
|
235,
|
||||||
|
92,
|
||||||
|
175,
|
||||||
|
255,
|
||||||
|
85,
|
||||||
|
119,
|
||||||
|
57,
|
||||||
|
160,
|
||||||
|
145,
|
||||||
|
107,
|
||||||
|
206,
|
||||||
|
28,
|
||||||
|
62,
|
||||||
|
10,
|
||||||
|
166,
|
||||||
|
89,
|
||||||
|
7,
|
||||||
|
20,
|
||||||
|
246,
|
||||||
|
243
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
212
test/fixtures/fix9.json
vendored
Normal file
212
test/fixtures/fix9.json
vendored
Normal file
@@ -0,0 +1,212 @@
|
|||||||
|
{
|
||||||
|
"input": {
|
||||||
|
"type": "Buffer",
|
||||||
|
"data": [
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35,
|
||||||
|
35
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"output": {
|
||||||
|
"type": "Buffer",
|
||||||
|
"data": [
|
||||||
|
79,
|
||||||
|
215,
|
||||||
|
22,
|
||||||
|
29,
|
||||||
|
132,
|
||||||
|
130,
|
||||||
|
214,
|
||||||
|
248,
|
||||||
|
237,
|
||||||
|
124,
|
||||||
|
234,
|
||||||
|
54,
|
||||||
|
215,
|
||||||
|
78,
|
||||||
|
0,
|
||||||
|
211,
|
||||||
|
246,
|
||||||
|
222,
|
||||||
|
54,
|
||||||
|
91,
|
||||||
|
53,
|
||||||
|
2,
|
||||||
|
49,
|
||||||
|
40,
|
||||||
|
0,
|
||||||
|
202,
|
||||||
|
188,
|
||||||
|
25,
|
||||||
|
184,
|
||||||
|
121,
|
||||||
|
164,
|
||||||
|
235,
|
||||||
|
189,
|
||||||
|
97,
|
||||||
|
14,
|
||||||
|
0,
|
||||||
|
83,
|
||||||
|
166,
|
||||||
|
88,
|
||||||
|
62,
|
||||||
|
55,
|
||||||
|
49,
|
||||||
|
79,
|
||||||
|
153,
|
||||||
|
136,
|
||||||
|
193,
|
||||||
|
133,
|
||||||
|
206,
|
||||||
|
172,
|
||||||
|
99,
|
||||||
|
207,
|
||||||
|
73,
|
||||||
|
246,
|
||||||
|
216,
|
||||||
|
192,
|
||||||
|
107,
|
||||||
|
50,
|
||||||
|
206,
|
||||||
|
167,
|
||||||
|
242,
|
||||||
|
25,
|
||||||
|
180,
|
||||||
|
63,
|
||||||
|
184,
|
||||||
|
201,
|
||||||
|
61,
|
||||||
|
90,
|
||||||
|
242,
|
||||||
|
223,
|
||||||
|
192,
|
||||||
|
13,
|
||||||
|
140,
|
||||||
|
31,
|
||||||
|
240,
|
||||||
|
112,
|
||||||
|
157,
|
||||||
|
250,
|
||||||
|
90,
|
||||||
|
142,
|
||||||
|
3,
|
||||||
|
40,
|
||||||
|
12,
|
||||||
|
106,
|
||||||
|
63,
|
||||||
|
73,
|
||||||
|
42,
|
||||||
|
79,
|
||||||
|
82,
|
||||||
|
20,
|
||||||
|
41,
|
||||||
|
187,
|
||||||
|
173,
|
||||||
|
23,
|
||||||
|
85,
|
||||||
|
59,
|
||||||
|
253,
|
||||||
|
212,
|
||||||
|
191,
|
||||||
|
109,
|
||||||
|
46
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
20
test/fixtures/go-aes.js
vendored
Normal file
20
test/fixtures/go-aes.js
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
16: {
|
||||||
|
inputs: [
|
||||||
|
[47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47],
|
||||||
|
[24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24],
|
||||||
|
[7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7],
|
||||||
|
[25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25],
|
||||||
|
[48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48]
|
||||||
|
],
|
||||||
|
outputs: [
|
||||||
|
[121, 104, 0, 151, 57, 137, 22, 239, 234, 151, 58, 15, 100, 22, 228, 110, 85, 248, 249, 15, 145, 128, 223, 25, 192, 175, 132, 169, 98, 203, 231, 106, 224, 102, 206, 244, 29, 213, 36, 2, 26, 213, 94, 29, 134, 219, 136, 73, 212, 176, 33, 95, 198, 91, 148, 139, 132, 252, 182, 115, 116, 160, 146, 194, 0, 97, 181, 0, 193, 149, 21, 51, 248, 97, 32, 62, 86, 153, 238, 67, 38, 34, 55, 143, 70, 193, 99, 107, 31, 67, 90, 97, 55, 63, 69, 203, 33, 233, 74, 237],
|
||||||
|
[109, 172, 127, 179, 110, 222, 79, 219, 87, 76, 70, 204, 166, 110, 184, 229, 90, 49, 160, 252, 78, 58, 73, 51, 152, 218, 3, 200, 10, 124, 152, 117, 137, 40, 23, 127, 56, 57, 203, 31, 101, 227, 31, 198, 223, 86, 98, 120, 100, 86, 116, 144, 142, 127, 68, 175, 249, 232, 22, 83, 22, 68, 60, 230, 146, 22, 153, 193, 67, 5, 51, 253, 239, 210, 80, 31, 254, 103, 185, 145, 123, 99, 205, 175, 156, 144, 191, 67, 31, 236, 43, 98, 197, 235, 31, 50, 69, 228, 100, 64],
|
||||||
|
[191, 93, 126, 191, 180, 42, 118, 144, 28, 188, 211, 191, 211, 130, 170, 153, 134, 240, 179, 83, 75, 23, 42, 68, 158, 200, 123, 155, 57, 169, 152, 133, 33, 114, 90, 29, 131, 91, 70, 105, 83, 45, 40, 47, 77, 96, 97, 8, 40, 1, 110, 245, 106, 172, 152, 146, 5, 114, 132, 0, 179, 31, 44, 78, 19, 109, 92, 199, 226, 36, 12, 74, 180, 241, 224, 107, 83, 13, 167, 27, 251, 101, 193, 98, 49, 90, 225, 197, 75, 213, 144, 52, 235, 130, 92, 247, 219, 139, 209, 132],
|
||||||
|
[191, 110, 53, 190, 250, 44, 190, 136, 22, 209, 131, 200, 112, 31, 61, 183, 247, 95, 4, 249, 69, 147, 238, 74, 18, 71, 197, 115, 141, 226, 102, 92, 91, 128, 181, 172, 67, 109, 17, 165, 52, 10, 55, 31, 55, 225, 253, 140, 154, 35, 104, 62, 119, 103, 197, 152, 125, 134, 140, 181, 170, 76, 75, 114, 195, 188, 68, 197, 28, 47, 116, 82, 34, 128, 232, 122, 14, 229, 122, 161, 36, 212, 161, 164, 145, 86, 215, 233, 222, 50, 143, 89, 131, 32, 130, 196, 109, 36, 204, 254],
|
||||||
|
[97, 142, 8, 37, 69, 173, 124, 180, 97, 70, 45, 91, 196, 126, 184, 135, 213, 104, 171, 89, 231, 63, 43, 42, 7, 245, 75, 165, 205, 182, 24, 50, 170, 217, 128, 112, 114, 215, 209, 145, 135, 235, 179, 212, 5, 81, 142, 199, 53, 221, 39, 239, 167, 21, 237, 168, 145, 249, 250, 108, 2, 247, 89, 73, 228, 227, 255, 155, 121, 157, 205, 96, 43, 32, 112, 209, 173, 96, 143, 43, 220, 140, 26, 205, 34, 34, 53, 157, 41, 167, 125, 235, 243, 85, 13, 14, 93, 109, 233, 186]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
6
test/fixtures/go-elliptic-key.js
vendored
6
test/fixtures/go-elliptic-key.js
vendored
@@ -3,10 +3,10 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
curve: 'P-256',
|
curve: 'P-256',
|
||||||
bob: {
|
bob: {
|
||||||
private: [
|
private: Buffer.from([
|
||||||
181, 217, 162, 151, 225, 36, 53, 253, 107, 66, 27, 27, 232, 72, 0, 0, 103, 167, 84, 62, 203, 91, 97, 137, 131, 193, 230, 126, 98, 242, 216, 170
|
181, 217, 162, 151, 225, 36, 53, 253, 107, 66, 27, 27, 232, 72, 0, 0, 103, 167, 84, 62, 203, 91, 97, 137, 131, 193, 230, 126, 98, 242, 216, 170
|
||||||
],
|
]),
|
||||||
public: new Buffer([
|
public: Buffer.from([
|
||||||
4, 53, 59, 128, 56, 162, 250, 72, 141, 206, 117, 232, 57, 96, 39, 39, 247, 7, 27, 57, 251, 232, 120, 186, 21, 239, 176, 139, 195, 129, 125, 85, 11, 188, 191, 32, 227, 0, 6, 163, 101, 68, 208, 1, 43, 131, 124, 112, 102, 91, 104, 79, 16, 119, 152, 208, 4, 147, 155, 83, 20, 146, 104, 55, 90
|
4, 53, 59, 128, 56, 162, 250, 72, 141, 206, 117, 232, 57, 96, 39, 39, 247, 7, 27, 57, 251, 232, 120, 186, 21, 239, 176, 139, 195, 129, 125, 85, 11, 188, 191, 32, 227, 0, 6, 163, 101, 68, 208, 1, 43, 131, 124, 112, 102, 91, 104, 79, 16, 119, 152, 208, 4, 147, 155, 83, 20, 146, 104, 55, 90
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
28
test/fixtures/go-key-ed25519.js
vendored
Normal file
28
test/fixtures/go-key-ed25519.js
vendored
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
// These were generated in a gore (https://github.com/motemen/gore) repl session:
|
||||||
|
//
|
||||||
|
// :import github.com/libp2p/go-libp2p-crypto
|
||||||
|
// :import crypto/rand
|
||||||
|
// priv, pub, err := crypto.GenerateEd25519Key(rand.Reader)
|
||||||
|
// pubkeyBytes, err := pub.Bytes()
|
||||||
|
// privkeyBytes, err := priv.Bytes()
|
||||||
|
// data := []byte("hello! and welcome to some awesome crypto primitives")
|
||||||
|
// sig, err := priv.Sign(data)
|
||||||
|
//
|
||||||
|
// :import io/ioutil
|
||||||
|
// ioutil.WriteFile("/tmp/pubkey_go.bin", pubkeyBytes, 0644)
|
||||||
|
// // etc..
|
||||||
|
//
|
||||||
|
// Then loaded into a node repl and dumped to arrays with:
|
||||||
|
//
|
||||||
|
// var pubkey = Array.from(fs.readFileSync('/tmp/pubkey_go.bin'))
|
||||||
|
// console.log(JSON.stringify(pubkey))
|
||||||
|
verify: {
|
||||||
|
privateKey: Buffer.from([8, 1, 18, 96, 201, 208, 1, 110, 176, 16, 230, 37, 66, 184, 149, 252, 78, 56, 206, 136, 2, 38, 118, 152, 226, 197, 117, 200, 54, 189, 156, 218, 184, 7, 118, 57, 233, 49, 221, 97, 164, 158, 241, 129, 73, 166, 225, 255, 193, 118, 22, 84, 55, 15, 249, 168, 225, 180, 198, 191, 14, 75, 187, 243, 150, 91, 232, 37, 233, 49, 221, 97, 164, 158, 241, 129, 73, 166, 225, 255, 193, 118, 22, 84, 55, 15, 249, 168, 225, 180, 198, 191, 14, 75, 187, 243, 150, 91, 232, 37]),
|
||||||
|
publicKey: Buffer.from([8, 1, 18, 32, 233, 49, 221, 97, 164, 158, 241, 129, 73, 166, 225, 255, 193, 118, 22, 84, 55, 15, 249, 168, 225, 180, 198, 191, 14, 75, 187, 243, 150, 91, 232, 37]),
|
||||||
|
data: Buffer.from([104, 101, 108, 108, 111, 33, 32, 97, 110, 100, 32, 119, 101, 108, 99, 111, 109, 101, 32, 116, 111, 32, 115, 111, 109, 101, 32, 97, 119, 101, 115, 111, 109, 101, 32, 99, 114, 121, 112, 116, 111, 32, 112, 114, 105, 109, 105, 116, 105, 118, 101, 115]),
|
||||||
|
signature: Buffer.from([7, 230, 175, 164, 228, 58, 78, 208, 62, 243, 73, 142, 83, 195, 176, 217, 166, 62, 41, 165, 168, 164, 75, 179, 163, 86, 102, 32, 18, 84, 150, 237, 39, 207, 213, 20, 134, 237, 50, 41, 176, 183, 229, 133, 38, 255, 42, 228, 68, 186, 100, 14, 175, 156, 243, 118, 125, 125, 120, 212, 124, 103, 252, 12])
|
||||||
|
}
|
||||||
|
}
|
14
test/fixtures/go-key-rsa.js
vendored
14
test/fixtures/go-key-rsa.js
vendored
@@ -2,29 +2,29 @@
|
|||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
private: {
|
private: {
|
||||||
hash: new Buffer([
|
hash: Buffer.from([
|
||||||
18, 32, 168, 125, 165, 65, 34, 157, 209, 4, 24, 158, 80, 196, 125, 86, 103, 0, 228, 145, 109, 252, 153, 7, 189, 9, 16, 37, 239, 36, 48, 78, 214, 212
|
18, 32, 168, 125, 165, 65, 34, 157, 209, 4, 24, 158, 80, 196, 125, 86, 103, 0, 228, 145, 109, 252, 153, 7, 189, 9, 16, 37, 239, 36, 48, 78, 214, 212
|
||||||
]),
|
]),
|
||||||
key: new Buffer([
|
key: Buffer.from([
|
||||||
8, 0, 18, 192, 2, 48, 130, 1, 60, 2, 1, 0, 2, 65, 0, 230, 157, 160, 242, 74, 222, 87, 0, 77, 180, 91, 175, 217, 166, 2, 95, 193, 239, 195, 140, 224, 57, 84, 207, 46, 172, 113, 196, 20, 133, 117, 205, 45, 7, 224, 41, 40, 195, 254, 124, 14, 84, 223, 147, 67, 198, 48, 36, 53, 161, 112, 46, 153, 90, 19, 123, 94, 247, 5, 116, 1, 238, 32, 15, 2, 3, 1, 0, 1, 2, 65, 0, 191, 59, 140, 255, 254, 23, 123, 91, 148, 19, 240, 71, 213, 26, 181, 51, 68, 181, 150, 153, 214, 65, 148, 83, 45, 103, 239, 250, 225, 237, 125, 173, 111, 244, 37, 124, 87, 178, 86, 10, 14, 207, 63, 105, 213, 37, 81, 23, 230, 4, 222, 179, 144, 40, 252, 163, 190, 7, 241, 221, 28, 54, 225, 209, 2, 33, 0, 235, 132, 229, 150, 99, 182, 176, 194, 198, 65, 210, 160, 184, 70, 82, 49, 235, 199, 14, 11, 92, 66, 237, 45, 220, 72, 235, 1, 244, 145, 205, 57, 2, 33, 0, 250, 171, 146, 180, 188, 194, 14, 152, 52, 64, 38, 52, 158, 86, 46, 109, 66, 100, 122, 43, 88, 167, 143, 98, 104, 143, 160, 60, 171, 185, 31, 135, 2, 33, 0, 206, 47, 255, 203, 100, 170, 137, 31, 75, 240, 78, 84, 212, 95, 4, 16, 158, 73, 27, 27, 136, 255, 50, 163, 166, 169, 211, 204, 87, 111, 217, 201, 2, 33, 0, 177, 51, 194, 213, 3, 175, 7, 84, 47, 115, 189, 206, 106, 180, 47, 195, 203, 48, 110, 112, 224, 14, 43, 189, 124, 127, 51, 222, 79, 226, 225, 87, 2, 32, 67, 23, 190, 222, 106, 22, 115, 139, 217, 244, 178, 53, 153, 99, 5, 176, 72, 77, 193, 61, 67, 134, 37, 238, 69, 66, 159, 28, 39, 5, 238, 125
|
8, 0, 18, 192, 2, 48, 130, 1, 60, 2, 1, 0, 2, 65, 0, 230, 157, 160, 242, 74, 222, 87, 0, 77, 180, 91, 175, 217, 166, 2, 95, 193, 239, 195, 140, 224, 57, 84, 207, 46, 172, 113, 196, 20, 133, 117, 205, 45, 7, 224, 41, 40, 195, 254, 124, 14, 84, 223, 147, 67, 198, 48, 36, 53, 161, 112, 46, 153, 90, 19, 123, 94, 247, 5, 116, 1, 238, 32, 15, 2, 3, 1, 0, 1, 2, 65, 0, 191, 59, 140, 255, 254, 23, 123, 91, 148, 19, 240, 71, 213, 26, 181, 51, 68, 181, 150, 153, 214, 65, 148, 83, 45, 103, 239, 250, 225, 237, 125, 173, 111, 244, 37, 124, 87, 178, 86, 10, 14, 207, 63, 105, 213, 37, 81, 23, 230, 4, 222, 179, 144, 40, 252, 163, 190, 7, 241, 221, 28, 54, 225, 209, 2, 33, 0, 235, 132, 229, 150, 99, 182, 176, 194, 198, 65, 210, 160, 184, 70, 82, 49, 235, 199, 14, 11, 92, 66, 237, 45, 220, 72, 235, 1, 244, 145, 205, 57, 2, 33, 0, 250, 171, 146, 180, 188, 194, 14, 152, 52, 64, 38, 52, 158, 86, 46, 109, 66, 100, 122, 43, 88, 167, 143, 98, 104, 143, 160, 60, 171, 185, 31, 135, 2, 33, 0, 206, 47, 255, 203, 100, 170, 137, 31, 75, 240, 78, 84, 212, 95, 4, 16, 158, 73, 27, 27, 136, 255, 50, 163, 166, 169, 211, 204, 87, 111, 217, 201, 2, 33, 0, 177, 51, 194, 213, 3, 175, 7, 84, 47, 115, 189, 206, 106, 180, 47, 195, 203, 48, 110, 112, 224, 14, 43, 189, 124, 127, 51, 222, 79, 226, 225, 87, 2, 32, 67, 23, 190, 222, 106, 22, 115, 139, 217, 244, 178, 53, 153, 99, 5, 176, 72, 77, 193, 61, 67, 134, 37, 238, 69, 66, 159, 28, 39, 5, 238, 125
|
||||||
])
|
])
|
||||||
},
|
},
|
||||||
public: {
|
public: {
|
||||||
hash: new Buffer([
|
hash: Buffer.from([
|
||||||
18, 32, 112, 151, 163, 167, 204, 243, 175, 123, 208, 162, 90, 84, 199, 174, 202, 110, 0, 119, 27, 202, 7, 149, 161, 251, 215, 168, 163, 54, 93, 54, 195, 20
|
18, 32, 112, 151, 163, 167, 204, 243, 175, 123, 208, 162, 90, 84, 199, 174, 202, 110, 0, 119, 27, 202, 7, 149, 161, 251, 215, 168, 163, 54, 93, 54, 195, 20
|
||||||
]),
|
]),
|
||||||
key: new Buffer([
|
key: Buffer.from([
|
||||||
8, 0, 18, 94, 48, 92, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0, 3, 75, 0, 48, 72, 2, 65, 0, 230, 157, 160, 242, 74, 222, 87, 0, 77, 180, 91, 175, 217, 166, 2, 95, 193, 239, 195, 140, 224, 57, 84, 207, 46, 172, 113, 196, 20, 133, 117, 205, 45, 7, 224, 41, 40, 195, 254, 124, 14, 84, 223, 147, 67, 198, 48, 36, 53, 161, 112, 46, 153, 90, 19, 123, 94, 247, 5, 116, 1, 238, 32, 15, 2, 3, 1, 0, 1
|
8, 0, 18, 94, 48, 92, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0, 3, 75, 0, 48, 72, 2, 65, 0, 230, 157, 160, 242, 74, 222, 87, 0, 77, 180, 91, 175, 217, 166, 2, 95, 193, 239, 195, 140, 224, 57, 84, 207, 46, 172, 113, 196, 20, 133, 117, 205, 45, 7, 224, 41, 40, 195, 254, 124, 14, 84, 223, 147, 67, 198, 48, 36, 53, 161, 112, 46, 153, 90, 19, 123, 94, 247, 5, 116, 1, 238, 32, 15, 2, 3, 1, 0, 1
|
||||||
])
|
])
|
||||||
},
|
},
|
||||||
verify: {
|
verify: {
|
||||||
signature: new Buffer([
|
signature: Buffer.from([
|
||||||
3, 116, 81, 57, 91, 194, 7, 1, 230, 236, 229, 142, 36, 209, 208, 107, 47, 52, 164, 236, 139, 35, 155, 97, 43, 64, 145, 91, 19, 218, 149, 63, 99, 164, 191, 110, 145, 37, 18, 7, 98, 112, 144, 35, 29, 186, 169, 150, 165, 88, 145, 170, 197, 110, 42, 163, 188, 10, 42, 63, 34, 93, 91, 94, 199, 110, 10, 82, 238, 80, 93, 93, 77, 130, 22, 216, 229, 172, 36, 229, 82, 162, 20, 78, 19, 46, 82, 243, 43, 80, 115, 125, 145, 231, 194, 224, 30, 187, 55, 228, 74, 52, 203, 191, 254, 148, 136, 218, 62, 147, 171, 130, 251, 181, 105, 29, 238, 207, 197, 249, 61, 105, 202, 172, 160, 174, 43, 124, 115, 130, 169, 30, 76, 41, 52, 200, 2, 26, 53, 190, 43, 20, 203, 10, 217, 250, 47, 102, 92, 103, 197, 22, 108, 184, 74, 218, 82, 202, 180, 98, 13, 114, 12, 92, 1, 139, 150, 170, 8, 92, 32, 116, 168, 219, 157, 162, 28, 77, 29, 29, 74, 136, 144, 49, 173, 245, 253, 76, 167, 200, 169, 163, 7, 49, 133, 120, 99, 191, 53, 10, 66, 26, 234, 240, 139, 235, 134, 30, 55, 248, 150, 100, 242, 150, 159, 198, 44, 78, 150, 7, 133, 139, 59, 76, 3, 225, 94, 13, 89, 122, 34, 95, 95, 107, 74, 169, 171, 169, 222, 25, 191, 182, 148, 116, 66, 67, 102, 12, 193, 217, 247, 243, 148, 233, 161, 157
|
3, 116, 81, 57, 91, 194, 7, 1, 230, 236, 229, 142, 36, 209, 208, 107, 47, 52, 164, 236, 139, 35, 155, 97, 43, 64, 145, 91, 19, 218, 149, 63, 99, 164, 191, 110, 145, 37, 18, 7, 98, 112, 144, 35, 29, 186, 169, 150, 165, 88, 145, 170, 197, 110, 42, 163, 188, 10, 42, 63, 34, 93, 91, 94, 199, 110, 10, 82, 238, 80, 93, 93, 77, 130, 22, 216, 229, 172, 36, 229, 82, 162, 20, 78, 19, 46, 82, 243, 43, 80, 115, 125, 145, 231, 194, 224, 30, 187, 55, 228, 74, 52, 203, 191, 254, 148, 136, 218, 62, 147, 171, 130, 251, 181, 105, 29, 238, 207, 197, 249, 61, 105, 202, 172, 160, 174, 43, 124, 115, 130, 169, 30, 76, 41, 52, 200, 2, 26, 53, 190, 43, 20, 203, 10, 217, 250, 47, 102, 92, 103, 197, 22, 108, 184, 74, 218, 82, 202, 180, 98, 13, 114, 12, 92, 1, 139, 150, 170, 8, 92, 32, 116, 168, 219, 157, 162, 28, 77, 29, 29, 74, 136, 144, 49, 173, 245, 253, 76, 167, 200, 169, 163, 7, 49, 133, 120, 99, 191, 53, 10, 66, 26, 234, 240, 139, 235, 134, 30, 55, 248, 150, 100, 242, 150, 159, 198, 44, 78, 150, 7, 133, 139, 59, 76, 3, 225, 94, 13, 89, 122, 34, 95, 95, 107, 74, 169, 171, 169, 222, 25, 191, 182, 148, 116, 66, 67, 102, 12, 193, 217, 247, 243, 148, 233, 161, 157
|
||||||
]),
|
]),
|
||||||
data: new Buffer([
|
data: Buffer.from([
|
||||||
10, 16, 27, 128, 228, 220, 147, 176, 53, 105, 175, 171, 32, 213, 35, 236, 203, 60, 18, 171, 2, 8, 0, 18, 166, 2, 48, 130, 1, 34, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0, 3, 130, 1, 15, 0, 48, 130, 1, 10, 2, 130, 1, 1, 0, 181, 113, 138, 108, 208, 103, 166, 102, 37, 36, 204, 250, 228, 165, 44, 64, 176, 210, 205, 141, 241, 55, 200, 110, 98, 68, 85, 199, 254, 19, 86, 204, 63, 250, 167, 38, 59, 249, 146, 228, 73, 171, 63, 18, 96, 104, 191, 137, 186, 244, 255, 90, 16, 119, 195, 52, 177, 213, 254, 187, 174, 84, 174, 173, 12, 236, 53, 234, 3, 209, 82, 37, 78, 111, 214, 135, 76, 195, 9, 242, 134, 188, 153, 84, 139, 231, 51, 146, 177, 60, 12, 25, 158, 91, 215, 152, 7, 0, 84, 35, 36, 230, 227, 67, 198, 72, 50, 110, 37, 209, 98, 193, 65, 93, 173, 199, 4, 198, 102, 99, 148, 144, 224, 217, 114, 53, 144, 245, 251, 114, 211, 20, 82, 163, 123, 75, 16, 192, 106, 213, 128, 2, 11, 200, 203, 84, 41, 199, 224, 155, 171, 217, 64, 109, 116, 188, 151, 183, 173, 52, 205, 164, 93, 13, 251, 65, 182, 160, 154, 185, 239, 33, 184, 84, 159, 105, 101, 173, 194, 251, 123, 84, 92, 66, 61, 180, 45, 104, 162, 224, 214, 233, 64, 220, 165, 2, 104, 116, 150, 2, 234, 203, 112, 21, 124, 23, 48, 66, 30, 63, 30, 36, 246, 135, 203, 218, 115, 22, 189, 39, 39, 125, 205, 65, 222, 220, 77, 18, 84, 121, 161, 153, 125, 25, 139, 137, 170, 239, 150, 106, 119, 168, 216, 140, 113, 121, 26, 53, 118, 110, 53, 192, 244, 252, 145, 85, 2, 3, 1, 0, 1, 26, 17, 80, 45, 50, 53, 54, 44, 80, 45, 51, 56, 52, 44, 80, 45, 53, 50, 49, 34, 24, 65, 69, 83, 45, 50, 53, 54, 44, 65, 69, 83, 45, 49, 50, 56, 44, 66, 108, 111, 119, 102, 105, 115, 104, 42, 13, 83, 72, 65, 50, 53, 54, 44, 83, 72, 65, 53, 49, 50, 10, 16, 220, 83, 240, 105, 6, 203, 78, 83, 210, 115, 6, 106, 98, 82, 1, 161, 18, 171, 2, 8, 0, 18, 166, 2, 48, 130, 1, 34, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0, 3, 130, 1, 15, 0, 48, 130, 1, 10, 2, 130, 1, 1, 0, 185, 234, 19, 191, 164, 33, 65, 94, 87, 42, 74, 83, 224, 25, 142, 44, 26, 7, 92, 242, 189, 42, 170, 197, 178, 92, 45, 240, 107, 141, 128, 59, 122, 252, 48, 140, 4, 85, 85, 203, 3, 197, 8, 127, 120, 98, 44, 169, 135, 196, 70, 137, 117, 180, 177, 134, 170, 35, 165, 88, 105, 30, 114, 138, 11, 96, 68, 99, 18, 149, 223, 166, 105, 12, 176, 77, 48, 214, 22, 236, 17, 154, 213, 209, 158, 169, 202, 5, 100, 210, 83, 90, 201, 38, 205, 246, 231, 106, 63, 86, 222, 143, 157, 173, 62, 4, 85, 232, 20, 188, 6, 209, 186, 132, 192, 117, 146, 181, 233, 26, 0, 240, 138, 206, 91, 170, 114, 137, 217, 132, 139, 242, 144, 213, 103, 101, 190, 146, 188, 250, 188, 134, 255, 70, 125, 78, 65, 136, 239, 190, 206, 139, 155, 140, 163, 233, 170, 247, 205, 87, 209, 19, 29, 173, 10, 147, 43, 28, 90, 46, 6, 197, 217, 186, 66, 68, 126, 76, 64, 184, 8, 170, 23, 79, 243, 223, 119, 133, 118, 50, 226, 44, 246, 176, 10, 161, 219, 83, 54, 68, 248, 5, 14, 177, 114, 54, 63, 11, 71, 136, 142, 56, 151, 123, 230, 61, 80, 15, 180, 42, 49, 220, 148, 99, 231, 20, 230, 220, 85, 207, 187, 37, 210, 137, 171, 125, 71, 14, 53, 100, 91, 83, 209, 50, 132, 165, 253, 25, 161, 5, 97, 164, 163, 83, 95, 53, 2, 3, 1, 0, 1, 26, 17, 80, 45, 50, 53, 54, 44, 80, 45, 51, 56, 52, 44, 80, 45, 53, 50, 49, 34, 15, 65, 69, 83, 45, 50, 53, 54, 44, 65, 69, 83, 45, 49, 50, 56, 42, 13, 83, 72, 65, 50, 53, 54, 44, 83, 72, 65, 53, 49, 50, 4, 97, 54, 203, 112, 136, 34, 231, 162, 19, 154, 131, 27, 105, 26, 121, 238, 120, 25, 203, 66, 232, 53, 198, 20, 19, 96, 119, 218, 90, 64, 170, 3, 132, 116, 1, 87, 116, 232, 165, 161, 198, 117, 167, 60, 145, 1, 253, 108, 50, 150, 117, 8, 140, 133, 48, 30, 236, 36, 84, 186, 22, 144, 87, 101
|
10, 16, 27, 128, 228, 220, 147, 176, 53, 105, 175, 171, 32, 213, 35, 236, 203, 60, 18, 171, 2, 8, 0, 18, 166, 2, 48, 130, 1, 34, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0, 3, 130, 1, 15, 0, 48, 130, 1, 10, 2, 130, 1, 1, 0, 181, 113, 138, 108, 208, 103, 166, 102, 37, 36, 204, 250, 228, 165, 44, 64, 176, 210, 205, 141, 241, 55, 200, 110, 98, 68, 85, 199, 254, 19, 86, 204, 63, 250, 167, 38, 59, 249, 146, 228, 73, 171, 63, 18, 96, 104, 191, 137, 186, 244, 255, 90, 16, 119, 195, 52, 177, 213, 254, 187, 174, 84, 174, 173, 12, 236, 53, 234, 3, 209, 82, 37, 78, 111, 214, 135, 76, 195, 9, 242, 134, 188, 153, 84, 139, 231, 51, 146, 177, 60, 12, 25, 158, 91, 215, 152, 7, 0, 84, 35, 36, 230, 227, 67, 198, 72, 50, 110, 37, 209, 98, 193, 65, 93, 173, 199, 4, 198, 102, 99, 148, 144, 224, 217, 114, 53, 144, 245, 251, 114, 211, 20, 82, 163, 123, 75, 16, 192, 106, 213, 128, 2, 11, 200, 203, 84, 41, 199, 224, 155, 171, 217, 64, 109, 116, 188, 151, 183, 173, 52, 205, 164, 93, 13, 251, 65, 182, 160, 154, 185, 239, 33, 184, 84, 159, 105, 101, 173, 194, 251, 123, 84, 92, 66, 61, 180, 45, 104, 162, 224, 214, 233, 64, 220, 165, 2, 104, 116, 150, 2, 234, 203, 112, 21, 124, 23, 48, 66, 30, 63, 30, 36, 246, 135, 203, 218, 115, 22, 189, 39, 39, 125, 205, 65, 222, 220, 77, 18, 84, 121, 161, 153, 125, 25, 139, 137, 170, 239, 150, 106, 119, 168, 216, 140, 113, 121, 26, 53, 118, 110, 53, 192, 244, 252, 145, 85, 2, 3, 1, 0, 1, 26, 17, 80, 45, 50, 53, 54, 44, 80, 45, 51, 56, 52, 44, 80, 45, 53, 50, 49, 34, 24, 65, 69, 83, 45, 50, 53, 54, 44, 65, 69, 83, 45, 49, 50, 56, 44, 66, 108, 111, 119, 102, 105, 115, 104, 42, 13, 83, 72, 65, 50, 53, 54, 44, 83, 72, 65, 53, 49, 50, 10, 16, 220, 83, 240, 105, 6, 203, 78, 83, 210, 115, 6, 106, 98, 82, 1, 161, 18, 171, 2, 8, 0, 18, 166, 2, 48, 130, 1, 34, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0, 3, 130, 1, 15, 0, 48, 130, 1, 10, 2, 130, 1, 1, 0, 185, 234, 19, 191, 164, 33, 65, 94, 87, 42, 74, 83, 224, 25, 142, 44, 26, 7, 92, 242, 189, 42, 170, 197, 178, 92, 45, 240, 107, 141, 128, 59, 122, 252, 48, 140, 4, 85, 85, 203, 3, 197, 8, 127, 120, 98, 44, 169, 135, 196, 70, 137, 117, 180, 177, 134, 170, 35, 165, 88, 105, 30, 114, 138, 11, 96, 68, 99, 18, 149, 223, 166, 105, 12, 176, 77, 48, 214, 22, 236, 17, 154, 213, 209, 158, 169, 202, 5, 100, 210, 83, 90, 201, 38, 205, 246, 231, 106, 63, 86, 222, 143, 157, 173, 62, 4, 85, 232, 20, 188, 6, 209, 186, 132, 192, 117, 146, 181, 233, 26, 0, 240, 138, 206, 91, 170, 114, 137, 217, 132, 139, 242, 144, 213, 103, 101, 190, 146, 188, 250, 188, 134, 255, 70, 125, 78, 65, 136, 239, 190, 206, 139, 155, 140, 163, 233, 170, 247, 205, 87, 209, 19, 29, 173, 10, 147, 43, 28, 90, 46, 6, 197, 217, 186, 66, 68, 126, 76, 64, 184, 8, 170, 23, 79, 243, 223, 119, 133, 118, 50, 226, 44, 246, 176, 10, 161, 219, 83, 54, 68, 248, 5, 14, 177, 114, 54, 63, 11, 71, 136, 142, 56, 151, 123, 230, 61, 80, 15, 180, 42, 49, 220, 148, 99, 231, 20, 230, 220, 85, 207, 187, 37, 210, 137, 171, 125, 71, 14, 53, 100, 91, 83, 209, 50, 132, 165, 253, 25, 161, 5, 97, 164, 163, 83, 95, 53, 2, 3, 1, 0, 1, 26, 17, 80, 45, 50, 53, 54, 44, 80, 45, 51, 56, 52, 44, 80, 45, 53, 50, 49, 34, 15, 65, 69, 83, 45, 50, 53, 54, 44, 65, 69, 83, 45, 49, 50, 56, 42, 13, 83, 72, 65, 50, 53, 54, 44, 83, 72, 65, 53, 49, 50, 4, 97, 54, 203, 112, 136, 34, 231, 162, 19, 154, 131, 27, 105, 26, 121, 238, 120, 25, 203, 66, 232, 53, 198, 20, 19, 96, 119, 218, 90, 64, 170, 3, 132, 116, 1, 87, 116, 232, 165, 161, 198, 117, 167, 60, 145, 1, 253, 108, 50, 150, 117, 8, 140, 133, 48, 30, 236, 36, 84, 186, 22, 144, 87, 101
|
||||||
]),
|
]),
|
||||||
publicKey: new Buffer([
|
publicKey: Buffer.from([
|
||||||
8, 0, 18, 166, 2, 48, 130, 1, 34, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0, 3, 130, 1, 15, 0, 48, 130, 1, 10, 2, 130, 1, 1, 0, 181, 113, 138, 108, 208, 103, 166, 102, 37, 36, 204, 250, 228, 165, 44, 64, 176, 210, 205, 141, 241, 55, 200, 110, 98, 68, 85, 199, 254, 19, 86, 204, 63, 250, 167, 38, 59, 249, 146, 228, 73, 171, 63, 18, 96, 104, 191, 137, 186, 244, 255, 90, 16, 119, 195, 52, 177, 213, 254, 187, 174, 84, 174, 173, 12, 236, 53, 234, 3, 209, 82, 37, 78, 111, 214, 135, 76, 195, 9, 242, 134, 188, 153, 84, 139, 231, 51, 146, 177, 60, 12, 25, 158, 91, 215, 152, 7, 0, 84, 35, 36, 230, 227, 67, 198, 72, 50, 110, 37, 209, 98, 193, 65, 93, 173, 199, 4, 198, 102, 99, 148, 144, 224, 217, 114, 53, 144, 245, 251, 114, 211, 20, 82, 163, 123, 75, 16, 192, 106, 213, 128, 2, 11, 200, 203, 84, 41, 199, 224, 155, 171, 217, 64, 109, 116, 188, 151, 183, 173, 52, 205, 164, 93, 13, 251, 65, 182, 160, 154, 185, 239, 33, 184, 84, 159, 105, 101, 173, 194, 251, 123, 84, 92, 66, 61, 180, 45, 104, 162, 224, 214, 233, 64, 220, 165, 2, 104, 116, 150, 2, 234, 203, 112, 21, 124, 23, 48, 66, 30, 63, 30, 36, 246, 135, 203, 218, 115, 22, 189, 39, 39, 125, 205, 65, 222, 220, 77, 18, 84, 121, 161, 153, 125, 25, 139, 137, 170, 239, 150, 106, 119, 168, 216, 140, 113, 121, 26, 53, 118, 110, 53, 192, 244, 252, 145, 85, 2, 3, 1, 0, 1
|
8, 0, 18, 166, 2, 48, 130, 1, 34, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0, 3, 130, 1, 15, 0, 48, 130, 1, 10, 2, 130, 1, 1, 0, 181, 113, 138, 108, 208, 103, 166, 102, 37, 36, 204, 250, 228, 165, 44, 64, 176, 210, 205, 141, 241, 55, 200, 110, 98, 68, 85, 199, 254, 19, 86, 204, 63, 250, 167, 38, 59, 249, 146, 228, 73, 171, 63, 18, 96, 104, 191, 137, 186, 244, 255, 90, 16, 119, 195, 52, 177, 213, 254, 187, 174, 84, 174, 173, 12, 236, 53, 234, 3, 209, 82, 37, 78, 111, 214, 135, 76, 195, 9, 242, 134, 188, 153, 84, 139, 231, 51, 146, 177, 60, 12, 25, 158, 91, 215, 152, 7, 0, 84, 35, 36, 230, 227, 67, 198, 72, 50, 110, 37, 209, 98, 193, 65, 93, 173, 199, 4, 198, 102, 99, 148, 144, 224, 217, 114, 53, 144, 245, 251, 114, 211, 20, 82, 163, 123, 75, 16, 192, 106, 213, 128, 2, 11, 200, 203, 84, 41, 199, 224, 155, 171, 217, 64, 109, 116, 188, 151, 183, 173, 52, 205, 164, 93, 13, 251, 65, 182, 160, 154, 185, 239, 33, 184, 84, 159, 105, 101, 173, 194, 251, 123, 84, 92, 66, 61, 180, 45, 104, 162, 224, 214, 233, 64, 220, 165, 2, 104, 116, 150, 2, 234, 203, 112, 21, 124, 23, 48, 66, 30, 63, 30, 36, 246, 135, 203, 218, 115, 22, 189, 39, 39, 125, 205, 65, 222, 220, 77, 18, 84, 121, 161, 153, 125, 25, 139, 137, 170, 239, 150, 106, 119, 168, 216, 140, 113, 121, 26, 53, 118, 110, 53, 192, 244, 252, 145, 85, 2, 3, 1, 0, 1
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
14
test/fixtures/go-stretch-key.js
vendored
14
test/fixtures/go-stretch-key.js
vendored
@@ -3,28 +3,28 @@
|
|||||||
module.exports = [{
|
module.exports = [{
|
||||||
cipher: 'AES-256',
|
cipher: 'AES-256',
|
||||||
hash: 'SHA256',
|
hash: 'SHA256',
|
||||||
secret: new Buffer([
|
secret: Buffer.from([
|
||||||
195, 191, 209, 165, 209, 201, 127, 122, 136, 111, 31, 66, 111, 68, 38, 155, 216, 204, 46, 181, 200, 188, 170, 204, 104, 74, 239, 251, 173, 114, 222, 234
|
195, 191, 209, 165, 209, 201, 127, 122, 136, 111, 31, 66, 111, 68, 38, 155, 216, 204, 46, 181, 200, 188, 170, 204, 104, 74, 239, 251, 173, 114, 222, 234
|
||||||
]),
|
]),
|
||||||
k1: {
|
k1: {
|
||||||
iv: new Buffer([
|
iv: Buffer.from([
|
||||||
208, 132, 203, 169, 253, 52, 40, 83, 161, 91, 17, 71, 33, 136, 67, 96
|
208, 132, 203, 169, 253, 52, 40, 83, 161, 91, 17, 71, 33, 136, 67, 96
|
||||||
]),
|
]),
|
||||||
cipherKey: new Buffer([
|
cipherKey: Buffer.from([
|
||||||
156, 48, 241, 157, 92, 248, 153, 186, 114, 127, 195, 114, 106, 104, 215, 133, 35, 11, 131, 137, 123, 70, 74, 26, 15, 60, 189, 32, 67, 221, 115, 137
|
156, 48, 241, 157, 92, 248, 153, 186, 114, 127, 195, 114, 106, 104, 215, 133, 35, 11, 131, 137, 123, 70, 74, 26, 15, 60, 189, 32, 67, 221, 115, 137
|
||||||
]),
|
]),
|
||||||
macKey: new Buffer([
|
macKey: Buffer.from([
|
||||||
6, 179, 91, 245, 224, 56, 153, 120, 77, 140, 29, 5, 15, 213, 187, 65, 137, 230, 202, 120
|
6, 179, 91, 245, 224, 56, 153, 120, 77, 140, 29, 5, 15, 213, 187, 65, 137, 230, 202, 120
|
||||||
])
|
])
|
||||||
},
|
},
|
||||||
k2: {
|
k2: {
|
||||||
iv: new Buffer([
|
iv: Buffer.from([
|
||||||
236, 17, 34, 141, 90, 106, 197, 56, 197, 184, 157, 135, 91, 88, 112, 19
|
236, 17, 34, 141, 90, 106, 197, 56, 197, 184, 157, 135, 91, 88, 112, 19
|
||||||
]),
|
]),
|
||||||
cipherKey: new Buffer([
|
cipherKey: Buffer.from([
|
||||||
151, 145, 195, 219, 76, 195, 102, 109, 187, 231, 100, 150, 132, 245, 251, 130, 254, 37, 178, 55, 227, 34, 114, 39, 238, 34, 2, 193, 107, 130, 32, 87
|
151, 145, 195, 219, 76, 195, 102, 109, 187, 231, 100, 150, 132, 245, 251, 130, 254, 37, 178, 55, 227, 34, 114, 39, 238, 34, 2, 193, 107, 130, 32, 87
|
||||||
]),
|
]),
|
||||||
macKey: new Buffer([
|
macKey: Buffer.from([
|
||||||
3, 229, 77, 212, 241, 217, 23, 113, 220, 126, 38, 255, 18, 117, 108, 205, 198, 89, 1, 236
|
3, 229, 77, 212, 241, 217, 23, 113, 220, 126, 38, 255, 18, 117, 108, 205, 198, 89, 1, 236
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
8
test/fixtures/secp256k1.js
vendored
Normal file
8
test/fixtures/secp256k1.js
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
// protobuf marshaled key pair generated with libp2p-crypto-secp256k1
|
||||||
|
// and marshaled with libp2p-crypto.marshalPublicKey / marshalPrivateKey
|
||||||
|
pbmPrivateKey: Buffer.from('08021220e0600103010000000100000000000000be1dc82c2e000000e8d6030301000000', 'hex'),
|
||||||
|
pbmPublicKey: Buffer.from('0802122103a9a7272a726fa083abf31ba44037f8347fbc5e5d3113d62a7c6bc26752fd8ee1', 'hex')
|
||||||
|
}
|
46
test/helpers/test-garbage-error-handling.js
Normal file
46
test/helpers/test-garbage-error-handling.js
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
/* eslint-env mocha */
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
const chai = require('chai')
|
||||||
|
const dirtyChai = require('dirty-chai')
|
||||||
|
const expect = chai.expect
|
||||||
|
chai.use(dirtyChai)
|
||||||
|
|
||||||
|
const util = require('util')
|
||||||
|
const garbage = [Buffer.from('00010203040506070809', 'hex'), {}, null, false, undefined, true, 1, 0, Buffer.from(''), 'aGVsbG93b3JsZA==', 'helloworld', '']
|
||||||
|
|
||||||
|
function doTests (fncName, fnc, num, skipBuffersAndStrings) {
|
||||||
|
if (!num) {
|
||||||
|
num = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
garbage.forEach((garbage) => {
|
||||||
|
if (skipBuffersAndStrings && (Buffer.isBuffer(garbage) || (typeof garbage) === 'string')) {
|
||||||
|
// skip this garbage because it's a buffer or a string and we were told do do that
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let args = []
|
||||||
|
for (let i = 0; i < num; i++) {
|
||||||
|
args.push(garbage)
|
||||||
|
}
|
||||||
|
it(fncName + '(' + args.map(garbage => util.inspect(garbage)).join(', ') + ')', cb => {
|
||||||
|
args.push((err, res) => {
|
||||||
|
expect(err).to.exist()
|
||||||
|
expect(res).to.not.exist()
|
||||||
|
cb()
|
||||||
|
})
|
||||||
|
|
||||||
|
fnc.apply(null, args)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = (obj, fncs, num) => {
|
||||||
|
describe('returns error via cb instead of crashing', () => {
|
||||||
|
fncs.forEach(fnc => {
|
||||||
|
doTests(fnc, obj[fnc], num)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports.doTests = doTests
|
@@ -1,24 +0,0 @@
|
|||||||
/* eslint max-nested-callbacks: ["error", 8] */
|
|
||||||
/* eslint-env mocha */
|
|
||||||
'use strict'
|
|
||||||
|
|
||||||
const expect = require('chai').expect
|
|
||||||
const crypto = require('../src')
|
|
||||||
|
|
||||||
const hashes = ['SHA1', 'SHA256', 'SHA512']
|
|
||||||
|
|
||||||
describe('HMAC', () => {
|
|
||||||
hashes.forEach((hash) => {
|
|
||||||
it(`${hash} - sign and verify`, (done) => {
|
|
||||||
crypto.hmac.create(hash, new Buffer('secret'), (err, hmac) => {
|
|
||||||
expect(err).to.not.exist
|
|
||||||
|
|
||||||
hmac.digest(new Buffer('hello world'), (err, sig) => {
|
|
||||||
expect(err).to.not.exist
|
|
||||||
expect(sig).to.have.length(hmac.length)
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
28
test/hmac/hmac.spec.js
Normal file
28
test/hmac/hmac.spec.js
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
/* eslint max-nested-callbacks: ["error", 8] */
|
||||||
|
/* eslint-env mocha */
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
const chai = require('chai')
|
||||||
|
const dirtyChai = require('dirty-chai')
|
||||||
|
const expect = chai.expect
|
||||||
|
chai.use(dirtyChai)
|
||||||
|
|
||||||
|
const crypto = require('../../src')
|
||||||
|
|
||||||
|
const hashes = ['SHA1', 'SHA256', 'SHA512']
|
||||||
|
|
||||||
|
describe('HMAC', () => {
|
||||||
|
hashes.forEach((hash) => {
|
||||||
|
it(`${hash} - sign and verify`, (done) => {
|
||||||
|
crypto.hmac.create(hash, Buffer.from('secret'), (err, hmac) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
|
||||||
|
hmac.digest(Buffer.from('hello world'), (err, sig) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
expect(sig).to.have.length(hmac.length)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
@@ -1,101 +0,0 @@
|
|||||||
/* eslint max-nested-callbacks: ["error", 8] */
|
|
||||||
/* eslint-env mocha */
|
|
||||||
'use strict'
|
|
||||||
|
|
||||||
const expect = require('chai').expect
|
|
||||||
|
|
||||||
const crypto = require('../src')
|
|
||||||
const fixtures = require('./fixtures/go-key-rsa')
|
|
||||||
|
|
||||||
describe('libp2p-crypto', () => {
|
|
||||||
let key
|
|
||||||
before((done) => {
|
|
||||||
crypto.generateKeyPair('RSA', 2048, (err, _key) => {
|
|
||||||
if (err) {
|
|
||||||
return done(err)
|
|
||||||
}
|
|
||||||
key = _key
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('marshalPublicKey and unmarshalPublicKey', () => {
|
|
||||||
const key2 = crypto.unmarshalPublicKey(crypto.marshalPublicKey(key.public))
|
|
||||||
|
|
||||||
expect(key2.equals(key.public)).to.be.eql(true)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('marshalPrivateKey and unmarshalPrivateKey', (done) => {
|
|
||||||
crypto.unmarshalPrivateKey(crypto.marshalPrivateKey(key), (err, key2) => {
|
|
||||||
if (err) {
|
|
||||||
return done(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
expect(key2.equals(key)).to.be.eql(true)
|
|
||||||
expect(key2.public.equals(key.public)).to.be.eql(true)
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
// marshalled keys seem to be slightly different
|
|
||||||
// unsure as to if this is just a difference in encoding
|
|
||||||
// or a bug
|
|
||||||
describe('go interop', () => {
|
|
||||||
it('unmarshals private key', (done) => {
|
|
||||||
crypto.unmarshalPrivateKey(fixtures.private.key, (err, key) => {
|
|
||||||
if (err) {
|
|
||||||
return done(err)
|
|
||||||
}
|
|
||||||
const hash = fixtures.private.hash
|
|
||||||
expect(fixtures.private.key).to.be.eql(key.bytes)
|
|
||||||
|
|
||||||
key.hash((err, digest) => {
|
|
||||||
if (err) {
|
|
||||||
return done(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
expect(digest).to.be.eql(hash)
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('unmarshals public key', (done) => {
|
|
||||||
const key = crypto.unmarshalPublicKey(fixtures.public.key)
|
|
||||||
const hash = fixtures.public.hash
|
|
||||||
|
|
||||||
expect(crypto.marshalPublicKey(key)).to.be.eql(fixtures.public.key)
|
|
||||||
|
|
||||||
key.hash((err, digest) => {
|
|
||||||
if (err) {
|
|
||||||
return done(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
expect(digest).to.be.eql(hash)
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('unmarshal -> marshal, private key', (done) => {
|
|
||||||
crypto.unmarshalPrivateKey(fixtures.private.key, (err, key) => {
|
|
||||||
if (err) {
|
|
||||||
return done(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
const marshalled = crypto.marshalPrivateKey(key)
|
|
||||||
expect(marshalled).to.be.eql(fixtures.private.key)
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('unmarshal -> marshal, public key', () => {
|
|
||||||
const key = crypto.unmarshalPublicKey(fixtures.public.key)
|
|
||||||
const marshalled = crypto.marshalPublicKey(key)
|
|
||||||
expect(
|
|
||||||
fixtures.public.key.equals(marshalled)
|
|
||||||
).to.be.eql(
|
|
||||||
true
|
|
||||||
)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
226
test/keys/ed25519.spec.js
Normal file
226
test/keys/ed25519.spec.js
Normal file
@@ -0,0 +1,226 @@
|
|||||||
|
/* eslint-env mocha */
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
const chai = require('chai')
|
||||||
|
const dirtyChai = require('dirty-chai')
|
||||||
|
const expect = chai.expect
|
||||||
|
chai.use(dirtyChai)
|
||||||
|
|
||||||
|
const crypto = require('../../src')
|
||||||
|
const ed25519 = crypto.keys.supportedKeys.ed25519
|
||||||
|
const fixtures = require('../fixtures/go-key-ed25519')
|
||||||
|
|
||||||
|
const testGarbage = require('../helpers/test-garbage-error-handling')
|
||||||
|
|
||||||
|
describe('ed25519', function () {
|
||||||
|
this.timeout(20 * 1000)
|
||||||
|
let key
|
||||||
|
before((done) => {
|
||||||
|
crypto.keys.generateKeyPair('Ed25519', 512, (err, _key) => {
|
||||||
|
if (err) return done(err)
|
||||||
|
key = _key
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('generates a valid key', (done) => {
|
||||||
|
expect(key).to.be.an.instanceof(ed25519.Ed25519PrivateKey)
|
||||||
|
|
||||||
|
key.hash((err, digest) => {
|
||||||
|
if (err) {
|
||||||
|
return done(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(digest).to.have.length(34)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('generates a valid key from seed', (done) => {
|
||||||
|
var seed = crypto.randomBytes(32)
|
||||||
|
crypto.keys.generateKeyPairFromSeed('Ed25519', seed, 512, (err, seededkey) => {
|
||||||
|
if (err) return done(err)
|
||||||
|
expect(seededkey).to.be.an.instanceof(ed25519.Ed25519PrivateKey)
|
||||||
|
|
||||||
|
seededkey.hash((err, digest) => {
|
||||||
|
if (err) {
|
||||||
|
return done(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(digest).to.have.length(34)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('generates the same key from the same seed', (done) => {
|
||||||
|
var seed = crypto.randomBytes(32)
|
||||||
|
crypto.keys.generateKeyPairFromSeed('Ed25519', seed, 512, (err, seededkey1) => {
|
||||||
|
if (err) return done(err)
|
||||||
|
crypto.keys.generateKeyPairFromSeed('Ed25519', seed, 512, (err, seededkey2) => {
|
||||||
|
if (err) return done(err)
|
||||||
|
expect(seededkey1.equals(seededkey2)).to.eql(true)
|
||||||
|
expect(seededkey1.public.equals(seededkey2.public)).to.eql(true)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('generates different keys for different seeds', (done) => {
|
||||||
|
const seed1 = crypto.randomBytes(32)
|
||||||
|
crypto.keys.generateKeyPairFromSeed('Ed25519', seed1, 512, (err, seededkey1) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
|
||||||
|
const seed2 = crypto.randomBytes(32)
|
||||||
|
crypto.keys.generateKeyPairFromSeed('Ed25519', seed2, 512, (err, seededkey2) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
|
||||||
|
expect(seededkey1.equals(seededkey2)).to.eql(false)
|
||||||
|
expect(seededkey1.public.equals(seededkey2.public))
|
||||||
|
.to.eql(false)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('signs', (done) => {
|
||||||
|
const text = crypto.randomBytes(512)
|
||||||
|
|
||||||
|
key.sign(text, (err, sig) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
|
||||||
|
key.public.verify(text, sig, (err, res) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
expect(res).to.be.eql(true)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('encoding', (done) => {
|
||||||
|
const keyMarshal = key.marshal()
|
||||||
|
ed25519.unmarshalEd25519PrivateKey(keyMarshal, (err, key2) => {
|
||||||
|
if (err) {
|
||||||
|
return done(err)
|
||||||
|
}
|
||||||
|
const keyMarshal2 = key2.marshal()
|
||||||
|
|
||||||
|
expect(keyMarshal).to.eql(keyMarshal2)
|
||||||
|
|
||||||
|
const pk = key.public
|
||||||
|
const pkMarshal = pk.marshal()
|
||||||
|
const pk2 = ed25519.unmarshalEd25519PublicKey(pkMarshal)
|
||||||
|
const pkMarshal2 = pk2.marshal()
|
||||||
|
|
||||||
|
expect(pkMarshal).to.eql(pkMarshal2)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('key id', (done) => {
|
||||||
|
key.id((err, id) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
expect(id).to.exist()
|
||||||
|
expect(id).to.be.a('string')
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('key equals', () => {
|
||||||
|
it('equals itself', () => {
|
||||||
|
expect(
|
||||||
|
key.equals(key)
|
||||||
|
).to.eql(
|
||||||
|
true
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(
|
||||||
|
key.public.equals(key.public)
|
||||||
|
).to.eql(
|
||||||
|
true
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('not equals other key', (done) => {
|
||||||
|
crypto.keys.generateKeyPair('Ed25519', 512, (err, key2) => {
|
||||||
|
if (err) return done(err)
|
||||||
|
|
||||||
|
expect(key.equals(key2)).to.eql(false)
|
||||||
|
expect(key2.equals(key)).to.eql(false)
|
||||||
|
expect(key.public.equals(key2.public)).to.eql(false)
|
||||||
|
expect(key2.public.equals(key.public)).to.eql(false)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('sign and verify', (done) => {
|
||||||
|
const data = Buffer.from('hello world')
|
||||||
|
key.sign(data, (err, sig) => {
|
||||||
|
if (err) {
|
||||||
|
return done(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
key.public.verify(data, sig, (err, valid) => {
|
||||||
|
if (err) {
|
||||||
|
return done(err)
|
||||||
|
}
|
||||||
|
expect(valid).to.eql(true)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('fails to verify for different data', (done) => {
|
||||||
|
const data = Buffer.from('hello world')
|
||||||
|
key.sign(data, (err, sig) => {
|
||||||
|
if (err) {
|
||||||
|
return done(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
key.public.verify(Buffer.from('hello'), sig, (err, valid) => {
|
||||||
|
if (err) {
|
||||||
|
return done(err)
|
||||||
|
}
|
||||||
|
expect(valid).to.be.eql(false)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('returns error via cb instead of crashing', () => {
|
||||||
|
const key = crypto.keys.unmarshalPublicKey(fixtures.verify.publicKey)
|
||||||
|
testGarbage.doTests('key.verify', key.verify.bind(key), 2)
|
||||||
|
testGarbage.doTests('crypto.keys.unmarshalPrivateKey', crypto.keys.unmarshalPrivateKey.bind(crypto.keys))
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('go interop', () => {
|
||||||
|
let privateKey
|
||||||
|
|
||||||
|
before((done) => {
|
||||||
|
crypto.keys.unmarshalPrivateKey(fixtures.verify.privateKey, (err, key) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
privateKey = key
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('verifies with data from go', (done) => {
|
||||||
|
const key = crypto.keys.unmarshalPublicKey(fixtures.verify.publicKey)
|
||||||
|
|
||||||
|
key.verify(fixtures.verify.data, fixtures.verify.signature, (err, ok) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
expect(ok).to.eql(true)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('generates the same signature as go', (done) => {
|
||||||
|
privateKey.sign(fixtures.verify.data, (err, sig) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
expect(sig).to.eql(fixtures.verify.signature)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
73
test/keys/ephemeral-keys.spec.js
Normal file
73
test/keys/ephemeral-keys.spec.js
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
/* eslint max-nested-callbacks: ["error", 8] */
|
||||||
|
/* eslint-env mocha */
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
const chai = require('chai')
|
||||||
|
const dirtyChai = require('dirty-chai')
|
||||||
|
const expect = chai.expect
|
||||||
|
chai.use(dirtyChai)
|
||||||
|
const parallel = require('async/parallel')
|
||||||
|
|
||||||
|
const fixtures = require('../fixtures/go-elliptic-key')
|
||||||
|
const crypto = require('../../src')
|
||||||
|
|
||||||
|
const curves = ['P-256', 'P-384'] // 'P-521' fails in tests :( no clue why
|
||||||
|
const lengths = {
|
||||||
|
'P-256': 65,
|
||||||
|
'P-384': 97,
|
||||||
|
'P-521': 133
|
||||||
|
}
|
||||||
|
const secretLengths = {
|
||||||
|
'P-256': 32,
|
||||||
|
'P-384': 48,
|
||||||
|
'P-521': 66
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('generateEphemeralKeyPair', () => {
|
||||||
|
curves.forEach((curve) => {
|
||||||
|
it(`generate and shared key ${curve}`, (done) => {
|
||||||
|
parallel([
|
||||||
|
(cb) => crypto.keys.generateEphemeralKeyPair(curve, cb),
|
||||||
|
(cb) => crypto.keys.generateEphemeralKeyPair(curve, cb)
|
||||||
|
], (err, keys) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
expect(keys[0].key).to.have.length(lengths[curve])
|
||||||
|
expect(keys[1].key).to.have.length(lengths[curve])
|
||||||
|
|
||||||
|
keys[0].genSharedKey(keys[1].key, (err, shared) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
expect(shared).to.have.length(secretLengths[curve])
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('go interop', () => {
|
||||||
|
it('generates a shared secret', (done) => {
|
||||||
|
const curve = fixtures.curve
|
||||||
|
|
||||||
|
parallel([
|
||||||
|
(cb) => crypto.keys.generateEphemeralKeyPair(curve, cb),
|
||||||
|
(cb) => crypto.keys.generateEphemeralKeyPair(curve, cb)
|
||||||
|
], (err, res) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
const alice = res[0]
|
||||||
|
const bob = res[1]
|
||||||
|
bob.key = fixtures.bob.public
|
||||||
|
|
||||||
|
parallel([
|
||||||
|
(cb) => alice.genSharedKey(bob.key, cb),
|
||||||
|
(cb) => bob.genSharedKey(alice.key, fixtures.bob, cb)
|
||||||
|
], (err, secrets) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
|
||||||
|
expect(secrets[0]).to.eql(secrets[1])
|
||||||
|
expect(secrets[0]).to.have.length(32)
|
||||||
|
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
@@ -2,10 +2,12 @@
|
|||||||
/* eslint-env mocha */
|
/* eslint-env mocha */
|
||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const expect = require('chai').expect
|
const chai = require('chai')
|
||||||
|
const dirtyChai = require('dirty-chai')
|
||||||
const crypto = require('../src')
|
const expect = chai.expect
|
||||||
const fixtures = require('./fixtures/go-stretch-key')
|
chai.use(dirtyChai)
|
||||||
|
const crypto = require('../../src')
|
||||||
|
const fixtures = require('../fixtures/go-stretch-key')
|
||||||
|
|
||||||
describe('keyStretcher', () => {
|
describe('keyStretcher', () => {
|
||||||
describe('generate', () => {
|
describe('generate', () => {
|
||||||
@@ -15,7 +17,7 @@ describe('keyStretcher', () => {
|
|||||||
let secret
|
let secret
|
||||||
|
|
||||||
before((done) => {
|
before((done) => {
|
||||||
crypto.generateEphemeralKeyPair('P-256', (err, _res) => {
|
crypto.keys.generateEphemeralKeyPair('P-256', (err, _res) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
return done(err)
|
return done(err)
|
||||||
}
|
}
|
||||||
@@ -34,13 +36,13 @@ describe('keyStretcher', () => {
|
|||||||
ciphers.forEach((cipher) => {
|
ciphers.forEach((cipher) => {
|
||||||
hashes.forEach((hash) => {
|
hashes.forEach((hash) => {
|
||||||
it(`${cipher} - ${hash}`, (done) => {
|
it(`${cipher} - ${hash}`, (done) => {
|
||||||
crypto.keyStretcher(cipher, hash, secret, (err, keys) => {
|
crypto.keys.keyStretcher(cipher, hash, secret, (err, keys) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
return done(err)
|
return done(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
expect(keys.k1).to.exist
|
expect(keys.k1).to.exist()
|
||||||
expect(keys.k2).to.exist
|
expect(keys.k2).to.exist()
|
||||||
done()
|
done()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -54,7 +56,7 @@ describe('keyStretcher', () => {
|
|||||||
const cipher = test.cipher
|
const cipher = test.cipher
|
||||||
const hash = test.hash
|
const hash = test.hash
|
||||||
const secret = test.secret
|
const secret = test.secret
|
||||||
crypto.keyStretcher(cipher, hash, secret, (err, keys) => {
|
crypto.keys.keyStretcher(cipher, hash, secret, (err, keys) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
return done(err)
|
return done(err)
|
||||||
}
|
}
|
65
test/keys/rsa-crypto-libs.js
Normal file
65
test/keys/rsa-crypto-libs.js
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
/* eslint-env mocha */
|
||||||
|
/* eslint max-nested-callbacks: ["error", 8] */
|
||||||
|
|
||||||
|
const chai = require('chai')
|
||||||
|
const dirtyChai = require('dirty-chai')
|
||||||
|
const expect = chai.expect
|
||||||
|
chai.use(dirtyChai)
|
||||||
|
chai.use(require('chai-string'))
|
||||||
|
|
||||||
|
const LIBS = ['ursa', 'keypair']
|
||||||
|
|
||||||
|
describe('RSA crypto libs', function () {
|
||||||
|
this.timeout(20 * 1000)
|
||||||
|
|
||||||
|
LIBS.forEach(lib => {
|
||||||
|
describe(lib, () => {
|
||||||
|
let crypto
|
||||||
|
let rsa
|
||||||
|
|
||||||
|
before(() => {
|
||||||
|
process.env.LP2P_FORCE_CRYPTO_LIB = lib
|
||||||
|
|
||||||
|
for (const path in require.cache) { // clear module cache
|
||||||
|
if (path.endsWith('.js')) {
|
||||||
|
delete require.cache[path]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
crypto = require('../../src')
|
||||||
|
rsa = crypto.keys.supportedKeys.rsa
|
||||||
|
})
|
||||||
|
|
||||||
|
it('generates a valid key', (done) => {
|
||||||
|
crypto.keys.generateKeyPair('RSA', 512, (err, key) => {
|
||||||
|
if (err) {
|
||||||
|
return done(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(key).to.be.an.instanceof(rsa.RsaPrivateKey)
|
||||||
|
|
||||||
|
key.hash((err, digest) => {
|
||||||
|
if (err) {
|
||||||
|
return done(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(digest).to.have.length(34)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
after(() => {
|
||||||
|
for (const path in require.cache) { // clear module cache
|
||||||
|
if (path.endsWith('.js')) {
|
||||||
|
delete require.cache[path]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delete process.env.LP2P_FORCE_CRYPTO_LIB
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
438
test/keys/rsa.spec.js
Normal file
438
test/keys/rsa.spec.js
Normal file
@@ -0,0 +1,438 @@
|
|||||||
|
/* eslint max-nested-callbacks: ["error", 8] */
|
||||||
|
/* eslint-env mocha */
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
const chai = require('chai')
|
||||||
|
const dirtyChai = require('dirty-chai')
|
||||||
|
const expect = chai.expect
|
||||||
|
chai.use(dirtyChai)
|
||||||
|
chai.use(require('chai-string'))
|
||||||
|
|
||||||
|
const crypto = require('../../src')
|
||||||
|
const rsa = crypto.keys.supportedKeys.rsa
|
||||||
|
const fixtures = require('../fixtures/go-key-rsa')
|
||||||
|
|
||||||
|
const testGarbage = require('../helpers/test-garbage-error-handling')
|
||||||
|
|
||||||
|
describe('RSA', function () {
|
||||||
|
this.timeout(20 * 1000)
|
||||||
|
let key
|
||||||
|
|
||||||
|
before((done) => {
|
||||||
|
crypto.keys.generateKeyPair('RSA', 512, (err, _key) => {
|
||||||
|
if (err) {
|
||||||
|
return done(err)
|
||||||
|
}
|
||||||
|
key = _key
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('generates a valid key', (done) => {
|
||||||
|
expect(key).to.be.an.instanceof(rsa.RsaPrivateKey)
|
||||||
|
|
||||||
|
key.hash((err, digest) => {
|
||||||
|
if (err) {
|
||||||
|
return done(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(digest).to.have.length(34)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('signs', (done) => {
|
||||||
|
const text = key.genSecret()
|
||||||
|
|
||||||
|
key.sign(text, (err, sig) => {
|
||||||
|
if (err) {
|
||||||
|
return done(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
key.public.verify(text, sig, (err, res) => {
|
||||||
|
if (err) {
|
||||||
|
return done(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(res).to.be.eql(true)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('encoding', (done) => {
|
||||||
|
const keyMarshal = key.marshal()
|
||||||
|
rsa.unmarshalRsaPrivateKey(keyMarshal, (err, key2) => {
|
||||||
|
if (err) {
|
||||||
|
return done(err)
|
||||||
|
}
|
||||||
|
const keyMarshal2 = key2.marshal()
|
||||||
|
|
||||||
|
expect(keyMarshal).to.eql(keyMarshal2)
|
||||||
|
|
||||||
|
const pk = key.public
|
||||||
|
const pkMarshal = pk.marshal()
|
||||||
|
const pk2 = rsa.unmarshalRsaPublicKey(pkMarshal)
|
||||||
|
const pkMarshal2 = pk2.marshal()
|
||||||
|
|
||||||
|
expect(pkMarshal).to.eql(pkMarshal2)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('key id', (done) => {
|
||||||
|
key.id((err, id) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
expect(id).to.exist()
|
||||||
|
expect(id).to.be.a('string')
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('key equals', () => {
|
||||||
|
it('equals itself', () => {
|
||||||
|
expect(key.equals(key)).to.eql(true)
|
||||||
|
|
||||||
|
expect(key.public.equals(key.public)).to.eql(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('not equals other key', (done) => {
|
||||||
|
crypto.keys.generateKeyPair('RSA', 512, (err, key2) => {
|
||||||
|
if (err) {
|
||||||
|
return done(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(key.equals(key2)).to.eql(false)
|
||||||
|
expect(key2.equals(key)).to.eql(false)
|
||||||
|
expect(key.public.equals(key2.public)).to.eql(false)
|
||||||
|
expect(key2.public.equals(key.public)).to.eql(false)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('sign and verify', (done) => {
|
||||||
|
const data = Buffer.from('hello world')
|
||||||
|
key.sign(data, (err, sig) => {
|
||||||
|
if (err) {
|
||||||
|
return done(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
key.public.verify(data, sig, (err, valid) => {
|
||||||
|
if (err) {
|
||||||
|
return done(err)
|
||||||
|
}
|
||||||
|
expect(valid).to.be.eql(true)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('fails to verify for different data', (done) => {
|
||||||
|
const data = Buffer.from('hello world')
|
||||||
|
key.sign(data, (err, sig) => {
|
||||||
|
if (err) {
|
||||||
|
return done(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
key.public.verify(Buffer.from('hello'), sig, (err, valid) => {
|
||||||
|
if (err) {
|
||||||
|
return done(err)
|
||||||
|
}
|
||||||
|
expect(valid).to.be.eql(false)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('export and import', () => {
|
||||||
|
it('password protected PKCS #8', (done) => {
|
||||||
|
key.export('pkcs-8', 'my secret', (err, pem) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
expect(pem).to.startsWith('-----BEGIN ENCRYPTED PRIVATE KEY-----')
|
||||||
|
crypto.keys.import(pem, 'my secret', (err, clone) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
expect(clone).to.exist()
|
||||||
|
expect(key.equals(clone)).to.eql(true)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('defaults to PKCS #8', (done) => {
|
||||||
|
key.export('another secret', (err, pem) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
expect(pem).to.startsWith('-----BEGIN ENCRYPTED PRIVATE KEY-----')
|
||||||
|
crypto.keys.import(pem, 'another secret', (err, clone) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
expect(clone).to.exist()
|
||||||
|
expect(key.equals(clone)).to.eql(true)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('needs correct password', (done) => {
|
||||||
|
key.export('another secret', (err, pem) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
crypto.keys.import(pem, 'not the secret', (err, clone) => {
|
||||||
|
expect(err).to.exist()
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('returns error via cb instead of crashing', () => {
|
||||||
|
const key = crypto.keys.unmarshalPublicKey(fixtures.verify.publicKey)
|
||||||
|
testGarbage.doTests('key.verify', key.verify.bind(key), 2, true)
|
||||||
|
testGarbage.doTests('crypto.keys.unmarshalPrivateKey', crypto.keys.unmarshalPrivateKey.bind(crypto.keys))
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('go interop', () => {
|
||||||
|
it('verifies with data from go', (done) => {
|
||||||
|
const key = crypto.keys.unmarshalPublicKey(fixtures.verify.publicKey)
|
||||||
|
|
||||||
|
key.verify(fixtures.verify.data, fixtures.verify.signature, (err, ok) => {
|
||||||
|
if (err) throw err
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
expect(ok).to.equal(true)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('openssl interop', () => {
|
||||||
|
it('can read a private key', (done) => {
|
||||||
|
/*
|
||||||
|
* Generated with
|
||||||
|
* openssl genpkey -algorithm RSA
|
||||||
|
* -pkeyopt rsa_keygen_bits:3072
|
||||||
|
* -pkeyopt rsa_keygen_pubexp:65537
|
||||||
|
*/
|
||||||
|
const pem = `-----BEGIN PRIVATE KEY-----
|
||||||
|
MIIG/wIBADANBgkqhkiG9w0BAQEFAASCBukwggblAgEAAoIBgQDp0Whyqa8KmdvK
|
||||||
|
0MsQGJEBzDAEHAZc0C6cr0rkb6Xwo+yB5kjZBRDORk0UXtYGE1pYt4JhUTmMzcWO
|
||||||
|
v2xTIsdbVMQlNtput2U8kIqS1cSTkX5HxOJtCiIzntMzuR/bGPSOexkyFQ8nCUqb
|
||||||
|
ROS7cln/ixprra2KMAKldCApN3ue2jo/JI1gyoS8sekhOASAa0ufMPpC+f70sc75
|
||||||
|
Y53VLnGBNM43iM/2lsK+GI2a13d6rRy86CEM/ygnh/EDlyNDxo+SQmy6GmSv/lmR
|
||||||
|
xgWQE2dIfK504KIxFTOphPAQAr9AsmcNnCQLhbz7YTsBz8WcytHGQ0Z5pnBQJ9AV
|
||||||
|
CX9E6DFHetvs0CNLVw1iEO06QStzHulmNEI/3P8I1TIxViuESJxSu3pSNwG1bSJZ
|
||||||
|
+Qee24vvlz/slBzK5gZWHvdm46v7vl5z7SA+whncEtjrswd8vkJk9fI/YTUbgOC0
|
||||||
|
HWMdc2t/LTZDZ+LUSZ/b2n5trvdJSsOKTjEfuf0wICC08pUUk8MCAwEAAQKCAYEA
|
||||||
|
ywve+DQCneIezHGk5cVvp2/6ApeTruXalJZlIxsRr3eq2uNwP4X2oirKpPX2RjBo
|
||||||
|
NMKnpnsyzuOiu+Pf3hJFrTpfWzHXXm5Eq+OZcwnQO5YNY6XGO4qhSNKT9ka9Mzbo
|
||||||
|
qRKdPrCrB+s5rryVJXKYVSInP3sDSQ2IPsYpZ6GW6Mv56PuFCpjTzElzejV7M0n5
|
||||||
|
0bRmn+MZVMVUR54KYiaCywFgUzmr3yfs1cfcsKqMRywt2J58lRy/chTLZ6LILQMv
|
||||||
|
4V01neVJiRkTmUfIWvc1ENIFM9QJlky9AvA5ASvwTTRz8yOnxoOXE/y4OVyOePjT
|
||||||
|
cz9eumu9N5dPuUIMmsYlXmRNaeGZPD9bIgKY5zOlfhlfZSuOLNH6EHBNr6JAgfwL
|
||||||
|
pdP43sbg2SSNKpBZ0iSMvpyTpbigbe3OyhnFH/TyhcC2Wdf62S9/FRsvjlRPbakW
|
||||||
|
YhKAA2kmJoydcUDO5ccEga8b7NxCdhRiczbiU2cj70pMIuOhDlGAznyxsYbtyxaB
|
||||||
|
AoHBAPy6Cbt6y1AmuId/HYfvms6i8B+/frD1CKyn+sUDkPf81xSHV7RcNrJi1S1c
|
||||||
|
V55I0y96HulsR+GmcAW1DF3qivWkdsd/b4mVkizd/zJm3/Dm8p8QOnNTtdWvYoEB
|
||||||
|
VzfAhBGaR/xflSLxZh2WE8ZHQ3IcRCXV9ZFgJ7PMeTprBJXzl0lTptvrHyo9QK1v
|
||||||
|
obLrL/KuXWS0ql1uSnJr1vtDI5uW8WU4GDENeU5b/CJHpKpjVxlGg+7pmLknxlBl
|
||||||
|
oBnZnQKBwQDs2Ky29qZ69qnPWowKceMJ53Z6uoUeSffRZ7xuBjowpkylasEROjuL
|
||||||
|
nyAihIYB7fd7R74CnRVYLI+O2qXfNKJ8HN+TgcWv8LudkRcnZDSvoyPEJAPyZGfr
|
||||||
|
olRCXD3caqtarlZO7vXSAl09C6HcL2KZ8FuPIEsuO0Aw25nESMg9eVMaIC6s2eSU
|
||||||
|
NUt6xfZw1JC0c+f0LrGuFSjxT2Dr5WKND9ageI6afuauMuosjrrOMl2g0dMcSnVz
|
||||||
|
KrtYa7Wi1N8CgcBFnuJreUplDCWtfgEen40f+5b2yAQYr4fyOFxGxdK73jVJ/HbW
|
||||||
|
wsh2n+9mDZg9jIZQ/+1gFGpA6V7W06dSf/hD70ihcKPDXSbloUpaEikC7jxMQWY4
|
||||||
|
uwjOkwAp1bq3Kxu21a+bAKHO/H1LDTrpVlxoJQ1I9wYtRDXrvBpxU2XyASbeFmNT
|
||||||
|
FhSByFn27Ve4OD3/NrWXtoVwM5/ioX6ZvUcj55McdTWE3ddbFNACiYX9QlyOI/TY
|
||||||
|
bhWafDCPmU9fj6kCgcEAjyQEfi9jPj2FM0RODqH1zS6OdG31tfCOTYicYQJyeKSI
|
||||||
|
/hAezwKaqi9phHMDancfcupQ89Nr6vZDbNrIFLYC3W+1z7hGeabMPNZLYAs3rE60
|
||||||
|
dv4tRHlaNRbORazp1iTBmvRyRRI2js3O++3jzOb2eILDUyT5St+UU/LkY7R5EG4a
|
||||||
|
w1df3idx9gCftXufDWHqcqT6MqFl0QgIzo5izS68+PPxitpRlR3M3Mr4rCU20Rev
|
||||||
|
blphdF+rzAavYyj1hYuRAoHBANmxwbq+QqsJ19SmeGMvfhXj+T7fNZQFh2F0xwb2
|
||||||
|
rMlf4Ejsnx97KpCLUkoydqAs2q0Ws9Nkx2VEVx5KfUD7fWhgbpdnEPnQkfeXv9sD
|
||||||
|
vZTuAoqInN1+vj1TME6EKR/6D4OtQygSNpecv23EuqEvyXWqRVsRt9Qd2B0H4k7h
|
||||||
|
gnjREs10u7zyqBIZH7KYVgyh27WxLr859ap8cKAH6Fb+UOPtZo3sUeeume60aebn
|
||||||
|
4pMwXeXP+LO8NIfRXV8mgrm86g==
|
||||||
|
-----END PRIVATE KEY-----
|
||||||
|
`
|
||||||
|
crypto.keys.import(pem, '', (err, key) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
expect(key).to.exist()
|
||||||
|
key.id((err, id) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
expect(id).to.equal('QmfWu2Xp8DZzCkZZzoPB9rcrq4R4RZid6AWE6kmrUAzuHy')
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// AssertionError: expected 'this only supports pkcs5PBES2' to not exist
|
||||||
|
it.skip('can read a private encrypted key (v1)', (done) => {
|
||||||
|
/*
|
||||||
|
* Generated with
|
||||||
|
* openssl genpkey -algorithm RSA
|
||||||
|
* -pkeyopt rsa_keygen_bits:1024
|
||||||
|
* -pkeyopt rsa_keygen_pubexp:65537
|
||||||
|
* -out foo.pem
|
||||||
|
* openssl pkcs8 -in foo.pem -topk8 -passout pass:mypassword
|
||||||
|
*/
|
||||||
|
const pem = `-----BEGIN ENCRYPTED PRIVATE KEY-----
|
||||||
|
MIICoTAbBgkqhkiG9w0BBQMwDgQI2563Jugj/KkCAggABIICgPxHkKtUUE8EWevq
|
||||||
|
eX9nTjqpbsv0QoXQMhegfxDELJLU8tj6V0bWNt7QDdfQ1n6FRgnNvNGick6gyqHH
|
||||||
|
yH9qC2oXwkDFP7OrHp2NEZd7DHQLLc+L4KJ/0dzsiZ1U9no7XzQMUay9Bc918ADE
|
||||||
|
pN2/EqigWkaG4gNjkAeKWr6+BNRevDXlSvls7YDboNcTiACi5zJkthivB9g3vT1m
|
||||||
|
gPdN6Gf/mmqtBTDHeqj5QsmXYqeCyo5b26JgYsziABVZDHph4ekPUsTvudRpE9Ex
|
||||||
|
baXwdYEAZxVpSbTvQ3A5qysjSZeM9ttfRTSSwL391q7dViz4+aujpk0Vj7piH+1B
|
||||||
|
CkfO8/XudRdRlnOe+KjMidktKCsMGCIOW92IlfMvIQ/Zn1GTYj9bRXONFNJ2WPND
|
||||||
|
UmCKnL7cmworwg/weRorrGKBWIGspU+tDASOPSvIGKo6Hoxm4CN1TpDRY7DAGlgm
|
||||||
|
Y3TEbMYfpXyzkPjvAhJDt03D3J9PrTO6uM5d7YUaaTmJ2TQFQVF2Lc3Uz8lDJLs0
|
||||||
|
ZYtfQ/4H+YY2RrX7ua7t6ArUcYXZtv0J4lRYWjwV8fGPUVc0d8xLJU0Yjf4BD7K8
|
||||||
|
rsavHo9b5YvBUX7SgUyxAEembEOe3SjQ+gPu2U5wovcjUuC9eItEEsXGrx30BQ0E
|
||||||
|
8BtK2+hp0eMkW5/BYckJkH+Yl8ypbzRGRRIZzLgeI4JveSx/mNhewfgTr+ORPThZ
|
||||||
|
mBdkD5r+ixWF174naw53L8U9wF8kiK7pIE1N9TR4USEeovLwX6Ni/2MMDZedOfof
|
||||||
|
2f77eUdLsK19/5/lcgAAYaXauXWhy2d2r3SayFrC9woy0lh2VLKRMBjcx1oWb7dp
|
||||||
|
0uxzo5Y=
|
||||||
|
-----END ENCRYPTED PRIVATE KEY-----
|
||||||
|
`
|
||||||
|
crypto.keys.import(pem, 'mypassword', (err, key) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
expect(key).to.exist()
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('can read a private encrypted key (v2 aes-128-cbc)', (done) => {
|
||||||
|
/*
|
||||||
|
* Generated with
|
||||||
|
* openssl genpkey -algorithm RSA
|
||||||
|
* -pkeyopt rsa_keygen_bits:1024
|
||||||
|
* -pkeyopt rsa_keygen_pubexp:65537
|
||||||
|
* -out foo.pem
|
||||||
|
* openssl pkcs8 -in foo.pem -topk8 -v2 aes-128-cbc -passout pass:mypassword
|
||||||
|
*/
|
||||||
|
const pem = `-----BEGIN ENCRYPTED PRIVATE KEY-----
|
||||||
|
MIICzzBJBgkqhkiG9w0BBQ0wPDAbBgkqhkiG9w0BBQwwDgQIP5QK2RfqUl4CAggA
|
||||||
|
MB0GCWCGSAFlAwQBAgQQj3OyM9gnW2dd/eRHkxjGrgSCAoCpM5GZB0v27cxzZsGc
|
||||||
|
O4/xqgwB0c/bSJ6QogtYU2KVoc7ZNQ5q9jtzn3I4ONvneOkpm9arzYz0FWnJi2C3
|
||||||
|
BPiF0D1NkfvjvMLv56bwiG2A1oBECacyAb2pXYeJY7SdtYKvcbgs3jx65uCm6TF2
|
||||||
|
BylteH+n1ewTQN9DLfASp1n81Ajq9lQGaK03SN2MUtcAPp7N9gnxJrlmDGeqlPRs
|
||||||
|
KpQYRcot+kE6Ew8a5jAr7mAxwpqvr3SM4dMvADZmRQsM4Uc/9+YMUdI52DG87EWc
|
||||||
|
0OUB+fnQ8jw4DZgOE9KKM5/QTWc3aEw/dzXr/YJsrv01oLazhqVHnEMG0Nfr0+DP
|
||||||
|
q+qac1AsCsOb71VxaRlRZcVEkEfAq3gidSPD93qmlDrCnmLYTilcLanXUepda7ez
|
||||||
|
qhjkHtpwBLN5xRZxOn3oUuLGjk8VRwfmFX+RIMYCyihjdmbEDYpNUVkQVYFGi/F/
|
||||||
|
1hxOyl9yhGdL0hb9pKHH10GGIgoqo4jSTLlb4ennihGMHCjehAjLdx/GKJkOWShy
|
||||||
|
V9hj8rAuYnRNb+tUW7ChXm1nLq14x9x1tX0ciVVn3ap/NoMkbFTr8M3pJ4bQlpAn
|
||||||
|
wCT2erYqwQtgSpOJcrFeph9TjIrNRVE7Zlmr7vayJrB/8/oPssVdhf82TXkna4fB
|
||||||
|
PcmO0YWLa117rfdeNM/Duy0ThSdTl39Qd+4FxqRZiHjbt+l0iSa/nOjTv1TZ/QqF
|
||||||
|
wqrO6EtcM45fbFJ1Y79o2ptC2D6MB4HKJq9WCt064/8zQCVx3XPbb3X8Z5o/6koy
|
||||||
|
ePGbz+UtSb9xczvqpRCOiFLh2MG1dUgWuHazjOtUcVWvilKnkjCMzZ9s1qG0sUDj
|
||||||
|
nPyn
|
||||||
|
-----END ENCRYPTED PRIVATE KEY-----
|
||||||
|
`
|
||||||
|
crypto.keys.import(pem, 'mypassword', (err, key) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
expect(key).to.exist()
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('can read a private encrypted key (v2 aes-256-cbc)', (done) => {
|
||||||
|
/*
|
||||||
|
* Generated with
|
||||||
|
* openssl genpkey -algorithm RSA
|
||||||
|
* -pkeyopt rsa_keygen_bits:1024
|
||||||
|
* -pkeyopt rsa_keygen_pubexp:65537
|
||||||
|
* -out foo.pem
|
||||||
|
* openssl pkcs8 -in foo.pem -topk8 -v2 aes-256-cbc -passout pass:mypassword
|
||||||
|
*/
|
||||||
|
const pem = `-----BEGIN ENCRYPTED PRIVATE KEY-----
|
||||||
|
MIICzzBJBgkqhkiG9w0BBQ0wPDAbBgkqhkiG9w0BBQwwDgQIhuL894loRucCAggA
|
||||||
|
MB0GCWCGSAFlAwQBKgQQEoEtsjW3iC9/u0uGvkxX7wSCAoAsX3l6JoR2OGbT8CkY
|
||||||
|
YT3RQFqquOgItYOHw6E3tir2YrmxEAo99nxoL8pdto37KSC32eAGnfv5R1zmHHSx
|
||||||
|
0M3/y2AWiCBTX95EEzdtGC1hK3PBa/qpp/xEmcrsjYN6NXxMAkhC0hMP/HdvqMAg
|
||||||
|
ee7upvaYJsJcl8QLFNayAWr8b8cZA/RBhGEIRl59Eyj6nNtxDt3bCrfe06o1CPCV
|
||||||
|
50/fRZEwFOi/C6GYvPN6MrPZO3ALBWgopLT2yQqycTKtfxYWIdOsMBkAjKf2D6Pk
|
||||||
|
u2mqBsaP4b71jIIeT4euSJLsoJV+O39s8YHXtW8GtOqp7V5kIlnm90lZ9wzeLTZ7
|
||||||
|
HJsD/jEdYto5J3YWm2wwEDccraffJSm7UDtJBvQdIx832kxeFCcGQjW38Zl1qqkg
|
||||||
|
iTH1PLTypxj2ZuviS2EkXVFb/kVU6leWwOt6fqWFC58UvJKeCk/6veazz3PDnTWM
|
||||||
|
92ClUqFd+CZn9VT4CIaJaAc6v5NLpPp+T9sRX9AtequPm7FyTeevY9bElfyk9gW9
|
||||||
|
JDKgKxs6DGWDa16RL5vzwtU+G3o6w6IU+mEwa6/c+hN+pRFs/KBNLLSP9OHBx7BJ
|
||||||
|
X/32Ft+VFhJaK+lQ+f+hve7od/bgKnz4c/Vtp7Dh51DgWgCpBgb8p0vqu02vTnxD
|
||||||
|
BXtDv3h75l5PhvdWfVIzpMWRYFvPR+vJi066FjAz2sjYc0NMLSYtZWyWoIInjhoX
|
||||||
|
Dp5CQujCtw/ZSSlwde1DKEWAW4SeDZAOQNvuz0rU3eosNUJxEmh3aSrcrRtDpw+Y
|
||||||
|
mBUuWAZMpz7njBi7h+JDfmSW/GAaMwrVFC2gef5375R0TejAh+COAjItyoeYEvv8
|
||||||
|
DQd8
|
||||||
|
-----END ENCRYPTED PRIVATE KEY-----
|
||||||
|
`
|
||||||
|
crypto.keys.import(pem, 'mypassword', (err, key) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
expect(key).to.exist()
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('can read a private encrypted key (v2 des)', (done) => {
|
||||||
|
/*
|
||||||
|
* Generated with
|
||||||
|
* openssl genpkey -algorithm RSA
|
||||||
|
* -pkeyopt rsa_keygen_bits:1024
|
||||||
|
* -pkeyopt rsa_keygen_pubexp:65537
|
||||||
|
* -out foo.pem
|
||||||
|
* openssl pkcs8 -in foo.pem -topk8 -v2 des -passout pass:mypassword
|
||||||
|
*/
|
||||||
|
const pem = `-----BEGIN ENCRYPTED PRIVATE KEY-----
|
||||||
|
MIICwzA9BgkqhkiG9w0BBQ0wMDAbBgkqhkiG9w0BBQwwDgQI0lXp62ozXvwCAggA
|
||||||
|
MBEGBSsOAwIHBAiR3Id5vH0u4wSCAoDQQYOrrkPFPIa0S5fQGXnJw1F/66g92Gs1
|
||||||
|
TkGydn4ouabWb++Vbi2chee1oyZsN2l8YNzDi0Gb2PfjsGpg2aJk0a3/efgA0u6T
|
||||||
|
leEH1dA/7Hr9NVspgHkaXpHt3X6wdbznLYJeAelfj7sDXpOkULGWCkCst0Txb6bi
|
||||||
|
Oxv4c0yYykiuUrp+2xvHbF9c2PrcDb58u/OBZcCg3QB1gTugQKM+ZIBRhcTEFLrm
|
||||||
|
8gWbzBfwYiUm6aJce4zoafP0NSlEOBbpbr73A08Q1IK6pISwltOUhhTvspSZnK41
|
||||||
|
y2CHt5Drnpl1pfOw9Q0svO3VrUP+omxP1SFP17ZfaRGw2uHd08HJZs438x5dIQoH
|
||||||
|
QgjlZ8A5rcT3FjnytSh3fln2ZxAGuObghuzmOEL/+8fkGER9QVjmQlsL6OMfB4j4
|
||||||
|
ZAkLf74uaTdegF3SqDQaGUwWgk7LyualmUXWTBoeP9kRIsRQLGzAEmd6duBPypED
|
||||||
|
HhKXP/ZFA1kVp3x1fzJ2llMFB3m1JBwy4PiohqrIJoR+YvKUvzVQtbOjxtCEAj87
|
||||||
|
JFnlQj0wjTd6lfNn+okewMNjKINZx+08ui7XANNU/l18lHIIz3ssXJSmqMW+hRZ9
|
||||||
|
9oB2tntLrnRMhkVZDVHadq7eMFOPu0rkekuaZm9CO2vu4V7Qa2h+gOoeczYza0H7
|
||||||
|
A+qCKbprxyL8SKI5vug2hE+mfC1leXVRtUYm1DnE+oet99bFd0fN20NwTw0rOeRg
|
||||||
|
0Z+/ZpQNizrXxfd3sU7zaJypWCxZ6TD/U/AKBtcb2gqmUjObZhbfbWq6jU2Ye//w
|
||||||
|
EBqQkwAUXR1tNekF8CWLOrfC/wbLRxVRkayb8bQUfdgukLpz0bgw
|
||||||
|
-----END ENCRYPTED PRIVATE KEY-----
|
||||||
|
`
|
||||||
|
crypto.keys.import(pem, 'mypassword', (err, key) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
expect(key).to.exist()
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('can read a private encrypted key (v2 des3)', (done) => {
|
||||||
|
/*
|
||||||
|
* Generated with
|
||||||
|
* openssl genpkey -algorithm RSA
|
||||||
|
* -pkeyopt rsa_keygen_bits:1024
|
||||||
|
* -pkeyopt rsa_keygen_pubexp:65537
|
||||||
|
* -out foo.pem
|
||||||
|
* openssl pkcs8 -in foo.pem -topk8 -v2 des3 -passout pass:mypassword
|
||||||
|
*/
|
||||||
|
const pem = `-----BEGIN ENCRYPTED PRIVATE KEY-----
|
||||||
|
MIICxjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQISznrfHd+D58CAggA
|
||||||
|
MBQGCCqGSIb3DQMHBAhx0DnnUvDiHASCAoCceplm+Cmwlgvn4hNsv6e4c/S1iA7w
|
||||||
|
2hU7Jt8JgRCIMWjP2FthXOAFLa2fD4g3qncYXcDAFBXNyoh25OgOwstO14YkxhDi
|
||||||
|
wG4TeppGUt9IlyyCol6Z4WhQs1TGm5OcD5xDta+zBXsBnlgmKLD5ZXPEYB+3v/Dg
|
||||||
|
SvM4sQz6NgkVHN52hchERsnknwSOghiK9mIBH0RZU5LgzlDy2VoBCiEPVdZ7m4F2
|
||||||
|
dft5e82zFS58vwDeNN/0r7fC54TyJf/8k3q94+4Hp0mseZ67LR39cvnEKuDuFROm
|
||||||
|
kLPLekWt5R2NGdunSQlA79BkrNB1ADruO8hQOOHMO9Y3/gNPWLKk+qrfHcUni+w3
|
||||||
|
Ofq+rdfakHRb8D6PUmsp3wQj6fSOwOyq3S50VwP4P02gKcZ1om1RvEzTbVMyL3sh
|
||||||
|
hZcVB3vViu3DO2/56wo29lPVTpj9bSYjw/CO5jNpPBab0B/Gv7JAR0z4Q8gn6OPy
|
||||||
|
qf+ddyW4Kcb6QUtMrYepghDthOiS3YJV/zCNdL3gTtVs5Ku9QwQ8FeM0/5oJZPlC
|
||||||
|
TxGuOFEJnYRWqIdByCP8mp/qXS5alSR4uoYQSd7vZG4vkhkPNSAwux/qK1IWfqiW
|
||||||
|
3XlZzrbD//9IzFVqGRs4nRIFq85ULK0zAR57HEKIwGyn2brEJzrxpV6xsHBp+m4w
|
||||||
|
6r0+PtwuWA0NauTCUzJ1biUdH8t0TgBL6YLaMjlrfU7JstH3TpcZzhJzsjfy0+zV
|
||||||
|
NT2TO3kSzXpQ5M2VjOoHPm2fqxD/js+ThDB3QLi4+C7HqakfiTY1lYzXl9/vayt6
|
||||||
|
DUD29r9pYL9ErB9tYko2rat54EY7k7Ts6S5jf+8G7Zz234We1APhvqaG
|
||||||
|
-----END ENCRYPTED PRIVATE KEY-----
|
||||||
|
`
|
||||||
|
crypto.keys.import(pem, 'mypassword', (err, key) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
expect(key).to.exist()
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
99
test/keys/secp256k1.spec.js
Normal file
99
test/keys/secp256k1.spec.js
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
/* eslint-env mocha */
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
const chai = require('chai')
|
||||||
|
const dirtyChai = require('dirty-chai')
|
||||||
|
const expect = chai.expect
|
||||||
|
chai.use(dirtyChai)
|
||||||
|
const fixtures = require('../fixtures/secp256k1')
|
||||||
|
const crypto = require('../../src')
|
||||||
|
|
||||||
|
const mockPublicKey = {
|
||||||
|
bytes: fixtures.pbmPublicKey
|
||||||
|
}
|
||||||
|
|
||||||
|
const mockPrivateKey = {
|
||||||
|
bytes: fixtures.pbmPrivateKey,
|
||||||
|
public: mockPublicKey
|
||||||
|
}
|
||||||
|
|
||||||
|
const mockSecp256k1Module = {
|
||||||
|
generateKeyPair (bits, callback) {
|
||||||
|
callback(null, mockPrivateKey)
|
||||||
|
},
|
||||||
|
|
||||||
|
unmarshalSecp256k1PrivateKey (buf, callback) {
|
||||||
|
callback(null, mockPrivateKey)
|
||||||
|
},
|
||||||
|
|
||||||
|
unmarshalSecp256k1PublicKey (buf) {
|
||||||
|
return mockPublicKey
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('without libp2p-crypto-secp256k1 module present', () => {
|
||||||
|
crypto.keys.supportedKeys.secp256k1 = undefined
|
||||||
|
|
||||||
|
it('fails to generate a secp256k1 key', (done) => {
|
||||||
|
crypto.keys.generateKeyPair('secp256k1', 256, (err, key) => {
|
||||||
|
expect(err).to.exist()
|
||||||
|
expect(key).to.not.exist()
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('fails to unmarshal a secp256k1 private key', (done) => {
|
||||||
|
crypto.keys.unmarshalPrivateKey(fixtures.pbmPrivateKey, (err, key) => {
|
||||||
|
expect(err).to.exist()
|
||||||
|
expect(key).to.not.exist()
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('fails to unmarshal a secp256k1 public key', () => {
|
||||||
|
expect(() => {
|
||||||
|
crypto.keys.unmarshalPublicKey(fixtures.pbmPublicKey)
|
||||||
|
}).to.throw(Error)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('with libp2p-crypto-secp256k1 module present', () => {
|
||||||
|
let key
|
||||||
|
|
||||||
|
before((done) => {
|
||||||
|
crypto.keys.supportedKeys.secp256k1 = mockSecp256k1Module
|
||||||
|
crypto.keys.generateKeyPair('secp256k1', 256, (err, _key) => {
|
||||||
|
if (err) return done(err)
|
||||||
|
key = _key
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
after((done) => {
|
||||||
|
delete crypto.keys.secp256k1
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('generates a valid key', (done) => {
|
||||||
|
expect(key).to.exist()
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('protobuf encoding', (done) => {
|
||||||
|
const keyMarshal = crypto.keys.marshalPrivateKey(key)
|
||||||
|
crypto.keys.unmarshalPrivateKey(keyMarshal, (err, key2) => {
|
||||||
|
if (err) return done(err)
|
||||||
|
const keyMarshal2 = crypto.keys.marshalPrivateKey(key2)
|
||||||
|
|
||||||
|
expect(keyMarshal).to.eql(keyMarshal2)
|
||||||
|
|
||||||
|
const pk = key.public
|
||||||
|
const pkMarshal = crypto.keys.marshalPublicKey(pk)
|
||||||
|
const pk2 = crypto.keys.unmarshalPublicKey(pkMarshal)
|
||||||
|
const pkMarshal2 = crypto.keys.marshalPublicKey(pk2)
|
||||||
|
|
||||||
|
expect(pkMarshal).to.eql(pkMarshal2)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
3
test/node.js
Normal file
3
test/node.js
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
require('./keys/rsa-crypto-libs')
|
177
test/rsa.spec.js
177
test/rsa.spec.js
@@ -1,177 +0,0 @@
|
|||||||
/* eslint-env mocha */
|
|
||||||
'use strict'
|
|
||||||
|
|
||||||
const expect = require('chai').expect
|
|
||||||
|
|
||||||
const crypto = require('../src')
|
|
||||||
const rsa = crypto.keys.rsa
|
|
||||||
const fixtures = require('./fixtures/go-key-rsa')
|
|
||||||
|
|
||||||
describe('RSA', () => {
|
|
||||||
let key
|
|
||||||
before((done) => {
|
|
||||||
crypto.generateKeyPair('RSA', 2048, (err, _key) => {
|
|
||||||
if (err) return done(err)
|
|
||||||
key = _key
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('generates a valid key', (done) => {
|
|
||||||
expect(
|
|
||||||
key
|
|
||||||
).to.be.an.instanceof(
|
|
||||||
rsa.RsaPrivateKey
|
|
||||||
)
|
|
||||||
|
|
||||||
key.hash((err, digest) => {
|
|
||||||
if (err) {
|
|
||||||
return done(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
expect(digest).to.have.length(34)
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('signs', (done) => {
|
|
||||||
const text = key.genSecret()
|
|
||||||
|
|
||||||
key.sign(text, (err, sig) => {
|
|
||||||
if (err) {
|
|
||||||
return done(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
key.public.verify(text, sig, (err, res) => {
|
|
||||||
if (err) {
|
|
||||||
return done(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
expect(res).to.be.eql(true)
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('encoding', (done) => {
|
|
||||||
const keyMarshal = key.marshal()
|
|
||||||
rsa.unmarshalRsaPrivateKey(keyMarshal, (err, key2) => {
|
|
||||||
if (err) {
|
|
||||||
return done(err)
|
|
||||||
}
|
|
||||||
const keyMarshal2 = key2.marshal()
|
|
||||||
|
|
||||||
expect(
|
|
||||||
keyMarshal
|
|
||||||
).to.be.eql(
|
|
||||||
keyMarshal2
|
|
||||||
)
|
|
||||||
|
|
||||||
const pk = key.public
|
|
||||||
const pkMarshal = pk.marshal()
|
|
||||||
const pk2 = rsa.unmarshalRsaPublicKey(pkMarshal)
|
|
||||||
const pkMarshal2 = pk2.marshal()
|
|
||||||
|
|
||||||
expect(
|
|
||||||
pkMarshal
|
|
||||||
).to.be.eql(
|
|
||||||
pkMarshal2
|
|
||||||
)
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('key equals', () => {
|
|
||||||
it('equals itself', () => {
|
|
||||||
expect(
|
|
||||||
key.equals(key)
|
|
||||||
).to.be.eql(
|
|
||||||
true
|
|
||||||
)
|
|
||||||
|
|
||||||
expect(
|
|
||||||
key.public.equals(key.public)
|
|
||||||
).to.be.eql(
|
|
||||||
true
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('not equals other key', (done) => {
|
|
||||||
crypto.generateKeyPair('RSA', 2048, (err, key2) => {
|
|
||||||
if (err) return done(err)
|
|
||||||
|
|
||||||
expect(
|
|
||||||
key.equals(key2)
|
|
||||||
).to.be.eql(
|
|
||||||
false
|
|
||||||
)
|
|
||||||
|
|
||||||
expect(
|
|
||||||
key2.equals(key)
|
|
||||||
).to.be.eql(
|
|
||||||
false
|
|
||||||
)
|
|
||||||
|
|
||||||
expect(
|
|
||||||
key.public.equals(key2.public)
|
|
||||||
).to.be.eql(
|
|
||||||
false
|
|
||||||
)
|
|
||||||
|
|
||||||
expect(
|
|
||||||
key2.public.equals(key.public)
|
|
||||||
).to.be.eql(
|
|
||||||
false
|
|
||||||
)
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('sign and verify', (done) => {
|
|
||||||
const data = new Buffer('hello world')
|
|
||||||
key.sign(data, (err, sig) => {
|
|
||||||
if (err) {
|
|
||||||
return done(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
key.public.verify(data, sig, (err, valid) => {
|
|
||||||
if (err) {
|
|
||||||
return done(err)
|
|
||||||
}
|
|
||||||
expect(valid).to.be.eql(true)
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('fails to verify for different data', (done) => {
|
|
||||||
const data = new Buffer('hello world')
|
|
||||||
key.sign(data, (err, sig) => {
|
|
||||||
if (err) {
|
|
||||||
return done(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
key.public.verify(new Buffer('hello'), sig, (err, valid) => {
|
|
||||||
if (err) {
|
|
||||||
return done(err)
|
|
||||||
}
|
|
||||||
expect(valid).to.be.eql(false)
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('go interop', () => {
|
|
||||||
it('verifies with data from go', (done) => {
|
|
||||||
const key = crypto.unmarshalPublicKey(fixtures.verify.publicKey)
|
|
||||||
|
|
||||||
key.verify(fixtures.verify.data, fixtures.verify.signature, (err, ok) => {
|
|
||||||
if (err) throw err
|
|
||||||
expect(err).to.not.exist
|
|
||||||
expect(ok).to.be.eql(true)
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
31
test/util.spec.js
Normal file
31
test/util.spec.js
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
/* eslint max-nested-callbacks: ["error", 8] */
|
||||||
|
/* eslint-env mocha */
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
const chai = require('chai')
|
||||||
|
const dirtyChai = require('dirty-chai')
|
||||||
|
const expect = chai.expect
|
||||||
|
chai.use(dirtyChai)
|
||||||
|
|
||||||
|
const util = require('../src/util')
|
||||||
|
const BN = require('bn.js')
|
||||||
|
|
||||||
|
describe('Util', () => {
|
||||||
|
let bn
|
||||||
|
|
||||||
|
before((done) => {
|
||||||
|
bn = new BN('dead', 16)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('toBase64', (done) => {
|
||||||
|
expect(util.toBase64(bn)).to.eql('3q0')
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('toBase64 zero padding', (done) => {
|
||||||
|
let bnpad = new BN('ff', 16)
|
||||||
|
expect(util.toBase64(bnpad, 2)).to.eql('AP8')
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
Reference in New Issue
Block a user