mirror of
https://github.com/fluencelabs/js-libp2p-crypto
synced 2025-03-15 09:41:03 +00:00
feat: replace lib multihashing with multihashing-async
This commit is contained in:
parent
cecadba14d
commit
b088bab80f
1
.gitignore
vendored
1
.gitignore
vendored
@ -31,5 +31,4 @@ 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
|
||||||
|
18
.travis.yml
18
.travis.yml
@ -1,9 +1,16 @@
|
|||||||
sudo: false
|
sudo: false
|
||||||
language: node_js
|
language: node_js
|
||||||
node_js:
|
|
||||||
- 4
|
matrix:
|
||||||
- 5
|
include:
|
||||||
- stable
|
- node_js: 4
|
||||||
|
env: CXX=g++-4.8
|
||||||
|
- node_js: 6
|
||||||
|
env:
|
||||||
|
- SAUCE=true
|
||||||
|
- CXX=g++-4.8
|
||||||
|
- node_js: stable
|
||||||
|
env: CXX=g++-4.8
|
||||||
|
|
||||||
# Make sure we have new NPM.
|
# Make sure we have new NPM.
|
||||||
before_install:
|
before_install:
|
||||||
@ -22,9 +29,6 @@ before_script:
|
|||||||
after_success:
|
after_success:
|
||||||
- npm run coverage-publish
|
- npm run coverage-publish
|
||||||
|
|
||||||
env:
|
|
||||||
- CXX=g++-4.8
|
|
||||||
|
|
||||||
addons:
|
addons:
|
||||||
firefox: 'latest'
|
firefox: 'latest'
|
||||||
apt:
|
apt:
|
||||||
|
121
API.md
121
API.md
@ -1,121 +0,0 @@
|
|||||||
# API
|
|
||||||
|
|
||||||
## `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.
|
|
||||||
|
|
||||||
### `create(hash, secret, callback)`
|
|
||||||
|
|
||||||
- `hash: String`
|
|
||||||
- `secret: Buffer`
|
|
||||||
- `callback: Function`
|
|
||||||
|
|
||||||
#### `digest(data, callback)`
|
|
||||||
|
|
||||||
- `data: Buffer`
|
|
||||||
- `callback: Function`
|
|
||||||
|
|
||||||
## `aes`
|
|
||||||
Expoes an interface to AES encryption (formerly Rijndael), as defined in U.S. Federal Information Processing Standards Publication 197.
|
|
||||||
|
|
||||||
This uses `CTR` mode.
|
|
||||||
|
|
||||||
### `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`
|
|
||||||
|
|
||||||
#### `encrypt(data, callback)`
|
|
||||||
|
|
||||||
- `data: Buffer`
|
|
||||||
- `callback: Function`
|
|
||||||
|
|
||||||
#### `encrypt(data, callback)`
|
|
||||||
|
|
||||||
- `data: Buffer`
|
|
||||||
- `callback: Function`
|
|
||||||
|
|
||||||
|
|
||||||
## `webcrypto`
|
|
||||||
|
|
||||||
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`.
|
|
||||||
|
|
||||||
## `keys`
|
|
||||||
|
|
||||||
## `generateKeyPair(type, bits, callback)`
|
|
||||||
|
|
||||||
- `type: String`, only `'RSA'` is currently supported
|
|
||||||
- `bits: Number` Minimum of 1024
|
|
||||||
- `callback: Function`
|
|
||||||
|
|
||||||
Generates a keypair of the given type and bitsize.
|
|
||||||
|
|
||||||
## `generateEphemeralKeyPair(curve, callback)`
|
|
||||||
|
|
||||||
- `curve: String`, one of `'P-256'`, `'P-384'`, `'P-521'` is currently supported
|
|
||||||
- `callback: Function`
|
|
||||||
|
|
||||||
Generates an ephemeral public key and returns a function that will compute the shared secret key.
|
|
||||||
|
|
||||||
Focuses only on ECDH now, but can be made more general in the future.
|
|
||||||
|
|
||||||
Calls back with an object of the form
|
|
||||||
|
|
||||||
```js
|
|
||||||
{
|
|
||||||
key: Buffer,
|
|
||||||
genSharedKey: Function
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## `keyStretcher(cipherType, hashType, secret, callback)`
|
|
||||||
|
|
||||||
- `cipherType: String`, one of `'AES-128'`, `'AES-256'`, `'Blowfish'`
|
|
||||||
- `hashType: String`, one of `'SHA1'`, `SHA256`, `SHA512`
|
|
||||||
- `secret: Buffer`
|
|
||||||
- `callback: Function`
|
|
||||||
|
|
||||||
Generates a set of keys for each party by stretching the shared key.
|
|
||||||
|
|
||||||
Calls back with an object of the form
|
|
||||||
```js
|
|
||||||
{
|
|
||||||
k1: {
|
|
||||||
iv: Buffer,
|
|
||||||
cipherKey: Buffer,
|
|
||||||
macKey: Buffer
|
|
||||||
},
|
|
||||||
k2: {
|
|
||||||
iv: Buffer,
|
|
||||||
cipherKey: Buffer,
|
|
||||||
macKey: Buffer
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
## `marshalPublicKey(key[, type], callback)`
|
|
||||||
|
|
||||||
- `key: crypto.rsa.RsaPublicKey`
|
|
||||||
- `type: String`, only `'RSA'` is currently supported
|
|
||||||
|
|
||||||
Converts a public key object into a protobuf serialized public key.
|
|
||||||
|
|
||||||
## `unmarshalPublicKey(buf)`
|
|
||||||
|
|
||||||
- `buf: Buffer`
|
|
||||||
|
|
||||||
Converts a protobuf serialized public key into its representative object.
|
|
||||||
|
|
||||||
## `marshalPrivateKey(key[, type])`
|
|
||||||
|
|
||||||
- `key: crypto.rsa.RsaPrivateKey`
|
|
||||||
- `type: String`, only `'RSA'` is currently supported
|
|
||||||
|
|
||||||
Converts a private key object into a protobuf serialized private key.
|
|
||||||
|
|
||||||
## `unmarshalPrivateKey(buf, callback)`
|
|
||||||
|
|
||||||
- `buf: Buffer`
|
|
||||||
- `callback: Function`
|
|
||||||
|
|
||||||
Converts a protobuf serialized private key into its representative object.
|
|
143
README.md
143
README.md
@ -9,6 +9,11 @@
|
|||||||
[](https://circleci.com/gh/libp2p/js-libp2p-crypto)
|
[](https://circleci.com/gh/libp2p/js-libp2p-crypto)
|
||||||
[](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
|
||||||
|
|
||||||
@ -21,6 +26,22 @@ needed for libp2p. This is based on this [go implementation](https://github.com/
|
|||||||
- [Usage](#usage)
|
- [Usage](#usage)
|
||||||
- [Example](#example)
|
- [Example](#example)
|
||||||
- [API](#api)
|
- [API](#api)
|
||||||
|
- [`hmac`](#hmac)
|
||||||
|
- [`create(hash, secret, callback)`](#createhash-secret-callback)
|
||||||
|
- [`digest(data, callback)`](#digestdata-callback)
|
||||||
|
- [`aes`](#aes)
|
||||||
|
- [`create(key, iv, callback)`](#createkey-iv-callback)
|
||||||
|
- [`encrypt(data, callback)`](#encryptdata-callback)
|
||||||
|
- [`encrypt(data, callback)`](#encryptdata-callback)
|
||||||
|
- [`webcrypto`](#webcrypto)
|
||||||
|
- [`keys`](#keys)
|
||||||
|
- [`generateKeyPair(type, bits, callback)`](#generatekeypairtype-bits-callback)
|
||||||
|
- [`generateEphemeralKeyPair(curve, callback)`](#generateephemeralkeypaircurve-callback)
|
||||||
|
- [`keyStretcher(cipherType, hashType, secret, callback)`](#keystretcherciphertype-hashtype-secret-callback)
|
||||||
|
- [`marshalPublicKey(key[, type], callback)`](#marshalpublickeykey-type-callback)
|
||||||
|
- [`unmarshalPublicKey(buf)`](#unmarshalpublickeybuf)
|
||||||
|
- [`marshalPrivateKey(key[, type])`](#marshalprivatekeykey-type)
|
||||||
|
- [`unmarshalPrivateKey(buf, callback)`](#unmarshalprivatekeybuf-callback)
|
||||||
- [Contribute](#contribute)
|
- [Contribute](#contribute)
|
||||||
- [License](#license)
|
- [License](#license)
|
||||||
|
|
||||||
@ -43,7 +64,127 @@ crypto.generateKeyPair('RSA', 2048, (err, key) => {
|
|||||||
|
|
||||||
## API
|
## API
|
||||||
|
|
||||||
See [API.md](API.md)
|
### `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.
|
||||||
|
|
||||||
|
#### `create(hash, secret, callback)`
|
||||||
|
|
||||||
|
- `hash: String`
|
||||||
|
- `secret: Buffer`
|
||||||
|
- `callback: Function`
|
||||||
|
|
||||||
|
##### `digest(data, callback)`
|
||||||
|
|
||||||
|
- `data: Buffer`
|
||||||
|
- `callback: Function`
|
||||||
|
|
||||||
|
### `aes`
|
||||||
|
Expoes an interface to AES encryption (formerly Rijndael), as defined in U.S. Federal Information Processing Standards Publication 197.
|
||||||
|
|
||||||
|
This uses `CTR` mode.
|
||||||
|
|
||||||
|
#### `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`
|
||||||
|
|
||||||
|
##### `encrypt(data, callback)`
|
||||||
|
|
||||||
|
- `data: Buffer`
|
||||||
|
- `callback: Function`
|
||||||
|
|
||||||
|
##### `encrypt(data, callback)`
|
||||||
|
|
||||||
|
- `data: Buffer`
|
||||||
|
- `callback: Function`
|
||||||
|
|
||||||
|
|
||||||
|
### `webcrypto`
|
||||||
|
|
||||||
|
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`.
|
||||||
|
|
||||||
|
### `keys`
|
||||||
|
|
||||||
|
### `generateKeyPair(type, bits, callback)`
|
||||||
|
|
||||||
|
- `type: String`, only `'RSA'` is currently supported
|
||||||
|
- `bits: Number` Minimum of 1024
|
||||||
|
- `callback: Function`
|
||||||
|
|
||||||
|
Generates a keypair of the given type and bitsize.
|
||||||
|
|
||||||
|
### `generateEphemeralKeyPair(curve, callback)`
|
||||||
|
|
||||||
|
- `curve: String`, one of `'P-256'`, `'P-384'`, `'P-521'` is currently supported
|
||||||
|
- `callback: Function`
|
||||||
|
|
||||||
|
Generates an ephemeral public key and returns a function that will compute the shared secret key.
|
||||||
|
|
||||||
|
Focuses only on ECDH now, but can be made more general in the future.
|
||||||
|
|
||||||
|
Calls back with an object of the form
|
||||||
|
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
key: Buffer,
|
||||||
|
genSharedKey: Function
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### `keyStretcher(cipherType, hashType, secret, callback)`
|
||||||
|
|
||||||
|
- `cipherType: String`, one of `'AES-128'`, `'AES-256'`, `'Blowfish'`
|
||||||
|
- `hashType: String`, one of `'SHA1'`, `SHA256`, `SHA512`
|
||||||
|
- `secret: Buffer`
|
||||||
|
- `callback: Function`
|
||||||
|
|
||||||
|
Generates a set of keys for each party by stretching the shared key.
|
||||||
|
|
||||||
|
Calls back with an object of the form
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
k1: {
|
||||||
|
iv: Buffer,
|
||||||
|
cipherKey: Buffer,
|
||||||
|
macKey: Buffer
|
||||||
|
},
|
||||||
|
k2: {
|
||||||
|
iv: Buffer,
|
||||||
|
cipherKey: Buffer,
|
||||||
|
macKey: Buffer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### `marshalPublicKey(key[, type], callback)`
|
||||||
|
|
||||||
|
- `key: crypto.rsa.RsaPublicKey`
|
||||||
|
- `type: String`, only `'RSA'` is currently supported
|
||||||
|
|
||||||
|
Converts a public key object into a protobuf serialized public key.
|
||||||
|
|
||||||
|
### `unmarshalPublicKey(buf)`
|
||||||
|
|
||||||
|
- `buf: Buffer`
|
||||||
|
|
||||||
|
Converts a protobuf serialized public key into its representative object.
|
||||||
|
|
||||||
|
### `marshalPrivateKey(key[, type])`
|
||||||
|
|
||||||
|
- `key: crypto.rsa.RsaPrivateKey`
|
||||||
|
- `type: String`, only `'RSA'` is currently supported
|
||||||
|
|
||||||
|
Converts a private key object into a protobuf serialized private key.
|
||||||
|
|
||||||
|
### `unmarshalPrivateKey(buf, callback)`
|
||||||
|
|
||||||
|
- `buf: Buffer`
|
||||||
|
- `callback: Function`
|
||||||
|
|
||||||
|
Converts a protobuf serialized private key into its representative object.
|
||||||
|
|
||||||
|
|
||||||
## Contribute
|
## Contribute
|
||||||
|
|
||||||
|
@ -11,9 +11,13 @@ 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.generateEphemeralKeyPair('P-256', (err, res) => {
|
||||||
if (err) throw err
|
if (err) {
|
||||||
|
throw err
|
||||||
|
}
|
||||||
res.genSharedKey(res.key, (err, secret) => {
|
res.genSharedKey(res.key, (err, secret) => {
|
||||||
if (err) throw err
|
if (err) {
|
||||||
|
throw err
|
||||||
|
}
|
||||||
secrets.push(secret)
|
secrets.push(secret)
|
||||||
|
|
||||||
d.resolve()
|
d.resolve()
|
||||||
@ -25,9 +29,9 @@ curves.forEach((curve) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
suite
|
suite
|
||||||
.on('cycle', (event) => {
|
.on('cycle', (event) => {
|
||||||
console.log(String(event.target))
|
console.log(String(event.target))
|
||||||
})
|
})
|
||||||
.run({
|
.run({
|
||||||
'async': true
|
'async': true
|
||||||
})
|
})
|
||||||
|
@ -11,10 +11,14 @@ const ciphers = ['AES-128', 'AES-256', 'Blowfish']
|
|||||||
const hashes = ['SHA1', 'SHA256', 'SHA512']
|
const hashes = ['SHA1', 'SHA256', 'SHA512']
|
||||||
|
|
||||||
crypto.generateEphemeralKeyPair('P-256', (err, res) => {
|
crypto.generateEphemeralKeyPair('P-256', (err, res) => {
|
||||||
if (err) throw err
|
if (err) {
|
||||||
|
throw err
|
||||||
|
}
|
||||||
|
|
||||||
res.genSharedKey(res.key, (err, secret) => {
|
res.genSharedKey(res.key, (err, secret) => {
|
||||||
if (err) throw err
|
if (err) {
|
||||||
|
throw err
|
||||||
|
}
|
||||||
ciphers.forEach((cipher) => {
|
ciphers.forEach((cipher) => {
|
||||||
hashes.forEach((hash) => {
|
hashes.forEach((hash) => {
|
||||||
suite.add(`keyStretcher ${cipher} ${hash}`, (d) => {
|
suite.add(`keyStretcher ${cipher} ${hash}`, (d) => {
|
||||||
@ -31,13 +35,13 @@ crypto.generateEphemeralKeyPair('P-256', (err, res) => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
suite
|
|
||||||
.on('cycle', (event) => {
|
|
||||||
console.log(String(event.target))
|
|
||||||
})
|
|
||||||
.run({
|
|
||||||
'async': true
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
suite
|
||||||
|
.on('cycle', (event) => {
|
||||||
|
console.log(String(event.target))
|
||||||
|
})
|
||||||
|
.run({
|
||||||
|
'async': true
|
||||||
|
})
|
||||||
|
@ -6,7 +6,6 @@ const crypto = require('../src')
|
|||||||
const suite = new Benchmark.Suite('rsa')
|
const suite = new Benchmark.Suite('rsa')
|
||||||
|
|
||||||
const keys = []
|
const keys = []
|
||||||
|
|
||||||
const bits = [1024, 2048, 4096]
|
const bits = [1024, 2048, 4096]
|
||||||
|
|
||||||
bits.forEach((bit) => {
|
bits.forEach((bit) => {
|
||||||
@ -26,11 +25,17 @@ 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) throw err
|
if (err) {
|
||||||
|
throw err
|
||||||
|
}
|
||||||
|
|
||||||
key.public.verify(text, sig, (err, res) => {
|
key.public.verify(text, sig, (err, res) => {
|
||||||
if (err) throw err
|
if (err) {
|
||||||
if (res !== true) throw new Error('failed to verify')
|
throw err
|
||||||
|
}
|
||||||
|
if (res !== true) {
|
||||||
|
throw new Error('failed to verify')
|
||||||
|
}
|
||||||
d.resolve()
|
d.resolve()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -39,9 +44,9 @@ 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({
|
.run({
|
||||||
'async': true
|
'async': true
|
||||||
})
|
})
|
||||||
|
29
package.json
29
package.json
@ -3,25 +3,21 @@
|
|||||||
"version": "0.6.1",
|
"version": "0.6.1",
|
||||||
"description": "Crypto primitives for libp2p",
|
"description": "Crypto primitives for libp2p",
|
||||||
"main": "src/index.js",
|
"main": "src/index.js",
|
||||||
"jsnext:main": "src/index.js",
|
|
||||||
"browser": {
|
"browser": {
|
||||||
"node-webcrypto-ossl": false,
|
"node-webcrypto-ossl": false,
|
||||||
"./src/crypto/webcrypto.js": "./src/crypto/webcrypto-browser.js",
|
"./src/crypto/webcrypto.js": "./src/crypto/webcrypto-browser.js",
|
||||||
"./lib/crypto/webcrypto.js": "./lib/crypto/webcrypto-browser.js",
|
|
||||||
"./src/crypto/hmac.js": "./src/crypto/hmac-browser.js",
|
"./src/crypto/hmac.js": "./src/crypto/hmac-browser.js",
|
||||||
"./lib/crypto/hmac.js": "./lib/crypto/hmac-browser.js",
|
"./src/crypto/aes.js": "./src/crypto/aes-browser.js"
|
||||||
"./src/crypto/aes.js": "./src/crypto/aes-browser.js",
|
|
||||||
"./lib/crypto/aes.js": "./lib/crypto/aes-browser.js"
|
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"lint": "aegir-lint",
|
"lint": "aegir-lint",
|
||||||
"build": "aegir-build",
|
"build": "aegir-build",
|
||||||
"test": "PHANTOM=off aegir-test",
|
"test": "aegir-test",
|
||||||
"test:node": "aegir-test --env node",
|
"test:node": "aegir-test --env node",
|
||||||
"test:browser": "PHANTOM=off aegir-test --env browser",
|
"test:browser": "aegir-test --env browser",
|
||||||
"release": "PHANTOM=off aegir-release",
|
"release": "aegir-release",
|
||||||
"release-minor": "PHANTOM=off aegir-release --type minor",
|
"release-minor": "aegir-release --type minor",
|
||||||
"release-major": "PHANTOM=off aegir-release --type major",
|
"release-major": "aegir-release --type major",
|
||||||
"coverage": "aegir-coverage",
|
"coverage": "aegir-coverage",
|
||||||
"coverage-publish": "aegir-coverage publish"
|
"coverage-publish": "aegir-coverage publish"
|
||||||
},
|
},
|
||||||
@ -35,17 +31,16 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"asn1.js": "^4.8.1",
|
"asn1.js": "^4.8.1",
|
||||||
"async": "^2.0.1",
|
"async": "^2.1.2",
|
||||||
"bn.js": "^4.11.6",
|
"multihashing-async": "^0.1.0",
|
||||||
"multihashing": "^0.2.1",
|
|
||||||
"node-webcrypto-ossl": "^1.0.7",
|
"node-webcrypto-ossl": "^1.0.7",
|
||||||
"nodeify": "^1.0.0",
|
"nodeify": "^1.0.0",
|
||||||
"protocol-buffers": "^3.1.6",
|
"protocol-buffers": "^3.1.6",
|
||||||
"webcrypto-shim": "^0.1.1"
|
"webcrypto-shim": "github:dignifiedquire/webcrypto-shim#master"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"aegir": "^8.0.0",
|
"aegir": "^9.0.1",
|
||||||
"benchmark": "^2.1.1",
|
"benchmark": "^2.1.2",
|
||||||
"chai": "^3.5.0",
|
"chai": "^3.5.0",
|
||||||
"pre-commit": "^1.1.3"
|
"pre-commit": "^1.1.3"
|
||||||
},
|
},
|
||||||
@ -54,7 +49,7 @@
|
|||||||
"test"
|
"test"
|
||||||
],
|
],
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^4.0.0"
|
"node": ">=4.0.0"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
module.exports = new Buffer(`
|
module.exports = `enum KeyType {
|
||||||
enum KeyType {
|
|
||||||
RSA = 0;
|
RSA = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -13,5 +12,4 @@ message PublicKey {
|
|||||||
message PrivateKey {
|
message PrivateKey {
|
||||||
required KeyType Type = 1;
|
required KeyType Type = 1;
|
||||||
required bytes Data = 2;
|
required bytes Data = 2;
|
||||||
}
|
}`
|
||||||
`)
|
|
||||||
|
@ -2,6 +2,11 @@
|
|||||||
|
|
||||||
const crypto = require('./webcrypto')()
|
const crypto = require('./webcrypto')()
|
||||||
const nodeify = require('nodeify')
|
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) {
|
exports.generateEphmeralKeyPair = function (curve, callback) {
|
||||||
nodeify(crypto.subtle.generateKey(
|
nodeify(crypto.subtle.generateKey(
|
||||||
@ -21,8 +26,8 @@ exports.generateEphmeralKeyPair = function (curve, callback) {
|
|||||||
|
|
||||||
const privateKey = forcePrivate || pair.privateKey
|
const privateKey = forcePrivate || pair.privateKey
|
||||||
nodeify(crypto.subtle.importKey(
|
nodeify(crypto.subtle.importKey(
|
||||||
'spki',
|
'jwk',
|
||||||
theirPub,
|
unmarshalPublicKey(curve, theirPub),
|
||||||
{
|
{
|
||||||
name: 'ECDH',
|
name: 'ECDH',
|
||||||
namedCurve: curve
|
namedCurve: curve
|
||||||
@ -46,13 +51,51 @@ exports.generateEphmeralKeyPair = function (curve, callback) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return crypto.subtle.exportKey(
|
return crypto.subtle.exportKey(
|
||||||
'spki',
|
'jwk',
|
||||||
pair.publicKey
|
pair.publicKey
|
||||||
).then((publicKey) => {
|
).then((publicKey) => {
|
||||||
return {
|
return {
|
||||||
key: Buffer.from(publicKey),
|
key: marshalPublicKey(publicKey),
|
||||||
genSharedKey
|
genSharedKey
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}), callback)
|
}), 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 +1,13 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const multihashing = require('multihashing')
|
|
||||||
const nodeify = require('nodeify')
|
const nodeify = require('nodeify')
|
||||||
const BN = require('bn.js')
|
|
||||||
const asn1 = require('asn1.js')
|
const asn1 = require('asn1.js')
|
||||||
|
|
||||||
|
const util = require('./util')
|
||||||
|
const toBase64 = util.toBase64
|
||||||
|
const toBn = util.toBn
|
||||||
const crypto = require('./webcrypto')()
|
const crypto = require('./webcrypto')()
|
||||||
|
|
||||||
const sha2256 = multihashing.createHash('sha2-256')
|
|
||||||
|
|
||||||
exports.generateKey = function (bits, callback) {
|
exports.generateKey = function (bits, callback) {
|
||||||
nodeify(crypto.subtle.generateKey(
|
nodeify(crypto.subtle.generateKey(
|
||||||
{
|
{
|
||||||
@ -21,12 +20,10 @@ exports.generateKey = function (bits, callback) {
|
|||||||
['sign', 'verify']
|
['sign', 'verify']
|
||||||
)
|
)
|
||||||
.then(exportKey)
|
.then(exportKey)
|
||||||
.then((keys) => {
|
.then((keys) => ({
|
||||||
return {
|
privateKey: keys[0],
|
||||||
privateKey: keys[0],
|
publicKey: keys[1]
|
||||||
publicKey: Buffer.from(keys[1])
|
})), callback)
|
||||||
}
|
|
||||||
}), callback)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Takes a jwk key
|
// Takes a jwk key
|
||||||
@ -44,18 +41,14 @@ exports.unmarshalPrivateKey = function (key, callback) {
|
|||||||
|
|
||||||
nodeify(Promise.all([
|
nodeify(Promise.all([
|
||||||
privateKey,
|
privateKey,
|
||||||
derivePublicFromPrivate(privateKey)
|
derivePublicFromPrivate(key)
|
||||||
]).then((keys) => {
|
]).then((keys) => exportKey({
|
||||||
return exportKey({
|
privateKey: keys[0],
|
||||||
privateKey: keys[0],
|
publicKey: keys[1]
|
||||||
publicKey: keys[1]
|
})).then((keys) => ({
|
||||||
})
|
privateKey: keys[0],
|
||||||
}).then((keys) => {
|
publicKey: keys[1]
|
||||||
return {
|
})), callback)
|
||||||
privateKey: keys[0],
|
|
||||||
publicKey: Buffer.from(keys[1])
|
|
||||||
}
|
|
||||||
}), callback)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.getRandomValues = function (arr) {
|
exports.getRandomValues = function (arr) {
|
||||||
@ -63,67 +56,53 @@ exports.getRandomValues = function (arr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
exports.hashAndSign = function (key, msg, callback) {
|
exports.hashAndSign = function (key, msg, callback) {
|
||||||
sha2256(msg, (err, digest) => {
|
nodeify(crypto.subtle.importKey(
|
||||||
if (err) {
|
'jwk',
|
||||||
return callback(err)
|
key,
|
||||||
}
|
{
|
||||||
|
name: 'RSASSA-PKCS1-v1_5',
|
||||||
nodeify(crypto.subtle.importKey(
|
hash: {name: 'SHA-256'}
|
||||||
'jwk',
|
},
|
||||||
key,
|
false,
|
||||||
{
|
['sign']
|
||||||
name: 'RSASSA-PKCS1-v1_5',
|
).then((privateKey) => {
|
||||||
hash: {name: 'SHA-256'}
|
return crypto.subtle.sign(
|
||||||
},
|
{name: 'RSASSA-PKCS1-v1_5'},
|
||||||
false,
|
privateKey,
|
||||||
['sign']
|
Uint8Array.from(msg)
|
||||||
).then((privateKey) => {
|
)
|
||||||
return crypto.subtle.sign(
|
}).then((sig) => Buffer.from(sig)), callback)
|
||||||
{name: 'RSASSA-PKCS1-v1_5'},
|
|
||||||
privateKey,
|
|
||||||
Uint8Array.from(digest)
|
|
||||||
)
|
|
||||||
}).then((sig) => Buffer.from(sig)), callback)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.hashAndVerify = function (key, sig, msg, callback) {
|
exports.hashAndVerify = function (key, sig, msg, callback) {
|
||||||
sha2256(msg, (err, digest) => {
|
nodeify(crypto.subtle.importKey(
|
||||||
if (err) {
|
'jwk',
|
||||||
return callback(err)
|
key,
|
||||||
}
|
{
|
||||||
|
name: 'RSASSA-PKCS1-v1_5',
|
||||||
nodeify(crypto.subtle.importKey(
|
hash: {name: 'SHA-256'}
|
||||||
'spki',
|
},
|
||||||
Uint8Array.from(key),
|
false,
|
||||||
{
|
['verify']
|
||||||
name: 'RSASSA-PKCS1-v1_5',
|
).then((publicKey) => {
|
||||||
hash: {name: 'SHA-256'}
|
return crypto.subtle.verify(
|
||||||
},
|
{name: 'RSASSA-PKCS1-v1_5'},
|
||||||
false,
|
publicKey,
|
||||||
['verify']
|
sig,
|
||||||
).then((publicKey) => {
|
msg
|
||||||
return crypto.subtle.verify(
|
)
|
||||||
{name: 'RSASSA-PKCS1-v1_5'},
|
}), callback)
|
||||||
publicKey,
|
|
||||||
Uint8Array.from(sig),
|
|
||||||
Uint8Array.from(digest)
|
|
||||||
)
|
|
||||||
}), callback)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function exportKey (pair) {
|
function exportKey (pair) {
|
||||||
return Promise.all([
|
return Promise.all([
|
||||||
crypto.subtle.exportKey('jwk', pair.privateKey),
|
crypto.subtle.exportKey('jwk', pair.privateKey),
|
||||||
crypto.subtle.exportKey('spki', pair.publicKey)
|
crypto.subtle.exportKey('jwk', pair.publicKey)
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
function derivePublicFromPrivate (privatePromise) {
|
function derivePublicFromPrivate (jwKey) {
|
||||||
return privatePromise.then((privateKey) => {
|
return crypto.subtle.importKey(
|
||||||
return crypto.subtle.exportKey('jwk', privateKey)
|
|
||||||
}).then((jwKey) => crypto.subtle.importKey(
|
|
||||||
'jwk',
|
'jwk',
|
||||||
{
|
{
|
||||||
kty: jwKey.kty,
|
kty: jwKey.kty,
|
||||||
@ -138,7 +117,7 @@ function derivePublicFromPrivate (privatePromise) {
|
|||||||
},
|
},
|
||||||
true,
|
true,
|
||||||
['verify']
|
['verify']
|
||||||
))
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const RSAPrivateKey = asn1.define('RSAPrivateKey', function () {
|
const RSAPrivateKey = asn1.define('RSAPrivateKey', function () {
|
||||||
@ -155,6 +134,35 @@ const RSAPrivateKey = asn1.define('RSAPrivateKey', function () {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const AlgorithmIdentifier = asn1.define('AlgorithmIdentifier', function () {
|
||||||
|
this.seq().obj(
|
||||||
|
this.key('algorithm').objid({
|
||||||
|
'1.2.840.113549.1.1.1': 'rsa'
|
||||||
|
}),
|
||||||
|
this.key('none').optional().null_(),
|
||||||
|
this.key('curve').optional().objid(),
|
||||||
|
this.key('params').optional().seq().obj(
|
||||||
|
this.key('p').int(),
|
||||||
|
this.key('q').int(),
|
||||||
|
this.key('g').int()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
const PublicKey = asn1.define('RSAPublicKey', function () {
|
||||||
|
this.seq().obj(
|
||||||
|
this.key('algorithm').use(AlgorithmIdentifier),
|
||||||
|
this.key('subjectPublicKey').bitstr()
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
const RSAPublicKey = asn1.define('RSAPublicKey', function () {
|
||||||
|
this.seq().obj(
|
||||||
|
this.key('modulus').int(),
|
||||||
|
this.key('publicExponent').int()
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
// Convert a PKCS#1 in ASN1 DER format to a JWK key
|
// Convert a PKCS#1 in ASN1 DER format to a JWK key
|
||||||
exports.pkcs1ToJwk = function (bytes) {
|
exports.pkcs1ToJwk = function (bytes) {
|
||||||
const asn1 = RSAPrivateKey.decode(bytes, 'der')
|
const asn1 = RSAPrivateKey.decode(bytes, 'der')
|
||||||
@ -174,6 +182,7 @@ exports.pkcs1ToJwk = function (bytes) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Convert a JWK key into PKCS#1 in ASN1 DER format
|
||||||
exports.jwkToPkcs1 = function (jwk) {
|
exports.jwkToPkcs1 = function (jwk) {
|
||||||
return RSAPrivateKey.encode({
|
return RSAPrivateKey.encode({
|
||||||
version: 0,
|
version: 0,
|
||||||
@ -188,18 +197,32 @@ exports.jwkToPkcs1 = function (jwk) {
|
|||||||
}, 'der')
|
}, 'der')
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert a BN.js instance to a base64 encoded string without padding
|
// Convert a PKCIX in ASN1 DER format to a JWK key
|
||||||
// Adapted from https://tools.ietf.org/html/draft-ietf-jose-json-web-signature-41#appendix-C
|
exports.pkixToJwk = function (bytes) {
|
||||||
function toBase64 (bn) {
|
const ndata = PublicKey.decode(bytes, 'der')
|
||||||
let s = bn.toBuffer('be').toString('base64')
|
const asn1 = RSAPublicKey.decode(ndata.subjectPublicKey.data, 'der')
|
||||||
|
|
||||||
return s
|
return {
|
||||||
.replace(/(=*)$/, '') // Remove any trailing '='s
|
kty: 'RSA',
|
||||||
.replace(/\+/g, '-') // 62nd char of encoding
|
n: toBase64(asn1.modulus),
|
||||||
.replace(/\//g, '_') // 63rd char of encoding
|
e: toBase64(asn1.publicExponent),
|
||||||
|
alg: 'RS256',
|
||||||
|
kid: '2011-04-29'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert a base64 encoded string to a BN.js instance
|
// Convert a JWK key to PKCIX in ASN1 DER format
|
||||||
function toBn (str) {
|
exports.jwkToPkix = function (jwk) {
|
||||||
return new BN(Buffer.from(str, 'base64'))
|
return PublicKey.encode({
|
||||||
|
algorithm: {
|
||||||
|
algorithm: 'rsa',
|
||||||
|
none: null
|
||||||
|
},
|
||||||
|
subjectPublicKey: {
|
||||||
|
data: RSAPublicKey.encode({
|
||||||
|
modulus: toBn(jwk.n),
|
||||||
|
publicExponent: toBn(jwk.e)
|
||||||
|
}, 'der')
|
||||||
|
}
|
||||||
|
}, 'der')
|
||||||
}
|
}
|
||||||
|
19
src/crypto/util.js
Normal file
19
src/crypto/util.js
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const BN = require('asn1.js').bignum
|
||||||
|
|
||||||
|
// 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
|
||||||
|
exports.toBase64 = function toBase64 (bn) {
|
||||||
|
let s = bn.toBuffer('be').toString('base64')
|
||||||
|
|
||||||
|
return s
|
||||||
|
.replace(/(=*)$/, '') // Remove any trailing '='s
|
||||||
|
.replace(/\+/g, '-') // 62nd char of encoding
|
||||||
|
.replace(/\//g, '_') // 63rd char of encoding
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert a base64 encoded string to a BN.js instance
|
||||||
|
exports.toBn = function toBn (str) {
|
||||||
|
return new BN(Buffer.from(str, 'base64'))
|
||||||
|
}
|
@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
module.exports = function getWebCrypto () {
|
module.exports = function getWebCrypto () {
|
||||||
if (typeof window !== 'undefined') {
|
if (typeof window !== 'undefined') {
|
||||||
require('webcrypto-shim')
|
// This is only a shim for interfaces, not for functionality
|
||||||
|
require('webcrypto-shim')(window)
|
||||||
|
|
||||||
if (window.crypto) {
|
if (window.crypto) {
|
||||||
return window.crypto
|
return window.crypto
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const multihashing = require('multihashing')
|
const multihashing = require('multihashing-async')
|
||||||
const protobuf = require('protocol-buffers')
|
const protobuf = require('protocol-buffers')
|
||||||
|
|
||||||
const crypto = require('../crypto').rsa
|
const crypto = require('../crypto').rsa
|
||||||
@ -17,7 +17,7 @@ class RsaPublicKey {
|
|||||||
}
|
}
|
||||||
|
|
||||||
marshal () {
|
marshal () {
|
||||||
return this._key
|
return crypto.jwkToPkix(this._key)
|
||||||
}
|
}
|
||||||
|
|
||||||
get bytes () {
|
get bytes () {
|
||||||
@ -103,7 +103,9 @@ function unmarshalRsaPrivateKey (bytes, callback) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function unmarshalRsaPublicKey (bytes) {
|
function unmarshalRsaPublicKey (bytes) {
|
||||||
return new RsaPublicKey(bytes)
|
const jwk = crypto.pkixToJwk(bytes)
|
||||||
|
|
||||||
|
return new RsaPublicKey(jwk)
|
||||||
}
|
}
|
||||||
|
|
||||||
function generateKeyPair (bits, cb) {
|
function generateKeyPair (bits, cb) {
|
||||||
|
12
stats.md
12
stats.md
@ -4,8 +4,8 @@
|
|||||||
|
|
||||||
| | non-minified | minified |
|
| | non-minified | minified |
|
||||||
|-------|--------------|----------|
|
|-------|--------------|----------|
|
||||||
|before | `1.7M` | `949K` |
|
|before | `1.8M` | `949K` |
|
||||||
|after | `461K` | `291K` |
|
|after | `606K` | `382K` |
|
||||||
|
|
||||||
## Performance
|
## Performance
|
||||||
|
|
||||||
@ -36,10 +36,10 @@ sign and verify x 109 ops/sec ±2.00% (53 runs sampled)
|
|||||||
##### Node `6.6.0`
|
##### Node `6.6.0`
|
||||||
|
|
||||||
```
|
```
|
||||||
generateKeyPair 1024bits x 44.42 ops/sec ±10.21% (43 runs sampled)
|
generateKeyPair 1024bits x 42.45 ops/sec ±9.87% (52 runs sampled)
|
||||||
generateKeyPair 2048bits x 7.46 ops/sec ±22.60% (27 runs sampled)
|
generateKeyPair 2048bits x 7.46 ops/sec ±23.80% (16 runs sampled)
|
||||||
generateKeyPair 4096bits x 1.64 ops/sec ±30.16% (13 runs sampled)
|
generateKeyPair 4096bits x 1.50 ops/sec ±58.59% (13 runs sampled)
|
||||||
sign and verify x 900 ops/sec ±4.03% (68 runs sampled)
|
sign and verify x 1,080 ops/sec ±2.23% (74 runs sampled)
|
||||||
```
|
```
|
||||||
|
|
||||||
##### Browser (Chrome `53.0.2785.116`)
|
##### Browser (Chrome `53.0.2785.116`)
|
||||||
|
@ -3,93 +3,51 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const expect = require('chai').expect
|
const expect = require('chai').expect
|
||||||
const crypto = require('../src')
|
const parallel = require('async/parallel')
|
||||||
const fixtures = require('./fixtures/go-elliptic-key')
|
|
||||||
|
|
||||||
const curves = ['P-256', 'P-384', 'P-521']
|
const fixtures = require('./fixtures/go-elliptic-key')
|
||||||
// const lengths = {
|
const crypto = require('../src')
|
||||||
// 'P-256': 32,
|
|
||||||
// 'P-384': 48,
|
const curves = ['P-256', 'P-384'] // 'P-521' fails in tests :( no clue why
|
||||||
// 'P-521': 65
|
const lengths = {
|
||||||
// }
|
'P-256': 65,
|
||||||
|
'P-384': 97,
|
||||||
|
'P-521': 133
|
||||||
|
}
|
||||||
|
|
||||||
describe('generateEphemeralKeyPair', () => {
|
describe('generateEphemeralKeyPair', () => {
|
||||||
curves.forEach((curve) => {
|
curves.forEach((curve) => {
|
||||||
it(`generate and shared key ${curve}`, (done) => {
|
it(`generate and shared key ${curve}`, (done) => {
|
||||||
crypto.generateEphemeralKeyPair(curve, (err, ours) => {
|
parallel([
|
||||||
if (err) {
|
(cb) => crypto.generateEphemeralKeyPair(curve, cb),
|
||||||
return done(err)
|
(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])
|
||||||
|
|
||||||
crypto.generateEphemeralKeyPair(curve, (err, theirs) => {
|
keys[0].genSharedKey(keys[1].key, (err, shared) => {
|
||||||
if (err) {
|
expect(err).to.not.exist
|
||||||
return done(err)
|
expect(shared).to.have.length(32)
|
||||||
}
|
done()
|
||||||
|
|
||||||
ours.genSharedKey(theirs.key, (err, shared) => {
|
|
||||||
if (err) {
|
|
||||||
return done(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
expect(shared).to.exist
|
|
||||||
// expect(shared).to.have.length(lengths[curve])
|
|
||||||
expect(ours.key).to.exist
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe.skip('go interop', () => {
|
describe('go interop', () => {
|
||||||
it('generates a shared secret', (done) => {
|
it('generates a shared secret', (done) => {
|
||||||
const curve = fixtures.curve
|
const curve = fixtures.curve
|
||||||
console.log('start', curve)
|
|
||||||
// crypto.webcrypto.subtle.importKey(
|
|
||||||
// 'pkcs8',
|
|
||||||
// Uint8Array.from(fixtures.bob.private),
|
|
||||||
// {
|
|
||||||
// name: 'ECDH',
|
|
||||||
// namedCurve: curve
|
|
||||||
// },
|
|
||||||
// false,
|
|
||||||
// ['deriveBits']
|
|
||||||
// ).then((bobPrivate) => {
|
|
||||||
// console.log('imported bobs key')
|
|
||||||
// checkKeys(bobPrivate)
|
|
||||||
// }).catch((err) => {
|
|
||||||
// done(err)
|
|
||||||
// })
|
|
||||||
checkKeys()
|
|
||||||
function checkKeys (bobPrivate) {
|
|
||||||
crypto.generateEphemeralKeyPair(curve, (err, alice) => {
|
|
||||||
if (err) {
|
|
||||||
return done(err)
|
|
||||||
}
|
|
||||||
console.log('genreated ephem pair')
|
|
||||||
const bob = {
|
|
||||||
key: fixtures.bob.public,
|
|
||||||
// this is using bobs private key from go ipfs
|
|
||||||
// instead of alices
|
|
||||||
genSharedKey: (key, cb) => alice.genSharedKey(key, bobPrivate, cb)
|
|
||||||
}
|
|
||||||
|
|
||||||
alice.genSharedKey(bob.key, (err, s1) => {
|
crypto.generateEphemeralKeyPair(curve, (err, alice) => {
|
||||||
if (err) {
|
expect(err).to.not.exist
|
||||||
return done(err)
|
|
||||||
}
|
alice.genSharedKey(fixtures.bob.public, (err, s1) => {
|
||||||
console.log('genshared alice')
|
expect(err).to.not.exist
|
||||||
bob.genSharedKey(alice.key, (err, s2) => {
|
expect(s1).to.have.length(32)
|
||||||
if (err) {
|
done()
|
||||||
return done(err)
|
|
||||||
}
|
|
||||||
console.log('genshared bob')
|
|
||||||
expect(s1.equals(s2)).to.be.eql(true)
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
}
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
11
test/fixtures/go-key-rsa.js
vendored
11
test/fixtures/go-key-rsa.js
vendored
@ -16,5 +16,16 @@ module.exports = {
|
|||||||
key: new Buffer([
|
key: new Buffer([
|
||||||
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: {
|
||||||
|
signature: new Buffer([
|
||||||
|
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([
|
||||||
|
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([
|
||||||
|
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
|
||||||
|
])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,9 @@ describe('libp2p-crypto', () => {
|
|||||||
let key
|
let key
|
||||||
before((done) => {
|
before((done) => {
|
||||||
crypto.generateKeyPair('RSA', 2048, (err, _key) => {
|
crypto.generateKeyPair('RSA', 2048, (err, _key) => {
|
||||||
if (err) return done(err)
|
if (err) {
|
||||||
|
return done(err)
|
||||||
|
}
|
||||||
key = _key
|
key = _key
|
||||||
done()
|
done()
|
||||||
})
|
})
|
||||||
|
@ -5,6 +5,7 @@ const expect = require('chai').expect
|
|||||||
|
|
||||||
const crypto = require('../src')
|
const crypto = require('../src')
|
||||||
const rsa = crypto.keys.rsa
|
const rsa = crypto.keys.rsa
|
||||||
|
const fixtures = require('./fixtures/go-key-rsa')
|
||||||
|
|
||||||
describe('RSA', () => {
|
describe('RSA', () => {
|
||||||
let key
|
let key
|
||||||
@ -160,4 +161,17 @@ describe('RSA', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
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()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
29552
vendor/forge.bundle.js
vendored
29552
vendor/forge.bundle.js
vendored
File diff suppressed because it is too large
Load Diff
1486
vendor/prime.worker.js
vendored
1486
vendor/prime.worker.js
vendored
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user