mirror of
https://github.com/fluencelabs/js-libp2p-crypto
synced 2025-07-20 22:42:16 +00:00
Compare commits
38 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 |
1
.eslintignore
Normal file
1
.eslintignore
Normal file
@@ -0,0 +1 @@
|
|||||||
|
src/keys/keys.proto.js
|
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,3 +1,4 @@
|
|||||||
|
docs
|
||||||
package-lock.json
|
package-lock.json
|
||||||
yarn.lock
|
yarn.lock
|
||||||
|
|
||||||
@@ -43,3 +44,4 @@ test/test-data/go-ipfs-repo/LOG.old
|
|||||||
|
|
||||||
# while testing npm5
|
# while testing npm5
|
||||||
package-lock.json
|
package-lock.json
|
||||||
|
yarn.lock
|
||||||
|
@@ -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.
|
||||||
sudo: false
|
sudo: false
|
||||||
language: node_js
|
language: node_js
|
||||||
|
|
||||||
@@ -14,7 +15,6 @@ script:
|
|||||||
- npm run lint
|
- npm run lint
|
||||||
- npm run test
|
- npm run test
|
||||||
- npm run coverage
|
- npm run coverage
|
||||||
- make test
|
|
||||||
|
|
||||||
before_script:
|
before_script:
|
||||||
- export DISPLAY=:99.0
|
- export DISPLAY=:99.0
|
||||||
|
91
CHANGELOG.md
91
CHANGELOG.md
@@ -1,3 +1,94 @@
|
|||||||
|
<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>
|
<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)
|
# [0.10.0](https://github.com/libp2p/js-libp2p-crypto/compare/v0.9.4...v0.10.0) (2017-09-03)
|
||||||
|
|
||||||
|
88
README.md
88
README.md
@@ -16,6 +16,10 @@
|
|||||||
|
|
||||||
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).
|
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).
|
||||||
|
|
||||||
|
## Lead Maintainer
|
||||||
|
|
||||||
|
[Friedel Ziegelmayer](https://github.com/dignifiedquire/)
|
||||||
|
|
||||||
## Table of Contents
|
## Table of Contents
|
||||||
|
|
||||||
- [Install](#install)
|
- [Install](#install)
|
||||||
@@ -35,6 +39,7 @@ This repo contains the JavaScript implementation of the crypto primitives needed
|
|||||||
- [`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)
|
- [`webcrypto`](#webcrypto)
|
||||||
- [Contribute](#contribute)
|
- [Contribute](#contribute)
|
||||||
- [License](#license)
|
- [License](#license)
|
||||||
@@ -69,8 +74,51 @@ This uses `CTR` mode.
|
|||||||
- `data: Buffer`
|
- `data: Buffer`
|
||||||
- `callback: Function`
|
- `callback: Function`
|
||||||
|
|
||||||
```
|
```js
|
||||||
TODO: Example of using aes
|
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`
|
### `crypto.hmac`
|
||||||
@@ -90,8 +138,20 @@ Exposes an interface to the Keyed-Hash Message Authentication Code (HMAC) as def
|
|||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
```
|
```js
|
||||||
TODO: Example of using hmac
|
var crypto = require('libp2p-crypto')
|
||||||
|
|
||||||
|
let hash = 'SHA1' // 'SHA256' || 'SHA512'
|
||||||
|
|
||||||
|
crypto.hmac.create(hash, Buffer.from('secret'), (err, hmac) => {
|
||||||
|
if (!err) {
|
||||||
|
hmac.digest(Buffer.from('hello world'), (err, sig) => {
|
||||||
|
if (!err) {
|
||||||
|
console.log(sig)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
### `crypto.keys`
|
### `crypto.keys`
|
||||||
@@ -183,12 +243,30 @@ Converts a private key object into a protobuf serialized private key.
|
|||||||
|
|
||||||
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)`
|
### `crypto.randomBytes(number)`
|
||||||
|
|
||||||
- `number: Number`
|
- `number: Number`
|
||||||
|
|
||||||
Generates a Buffer with length `number` populated by random bytes.
|
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
|
||||||
|
|
||||||
Feel free to join in. All welcome. Open an [issue](https://github.com/libp2p/js-libp2p-crypto/issues)!
|
Feel free to join in. All welcome. Open an [issue](https://github.com/libp2p/js-libp2p-crypto/issues)!
|
||||||
@@ -199,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
|
@@ -22,5 +22,6 @@ curves.forEach((curve) => {
|
|||||||
}, { defer: true })
|
}, { defer: true })
|
||||||
})
|
})
|
||||||
|
|
||||||
suite.on('cycle', (event) => console.log(String(event.target)))
|
suite
|
||||||
.run({async: true})
|
.on('cycle', (event) => console.log(String(event.target)))
|
||||||
|
.run({async: true})
|
||||||
|
@@ -22,8 +22,9 @@ async.waterfall([
|
|||||||
setup(cipher, hash, secret)
|
setup(cipher, hash, secret)
|
||||||
}))
|
}))
|
||||||
|
|
||||||
suite.on('cycle', (event) => console.log(String(event.target)))
|
suite
|
||||||
.run({async: true})
|
.on('cycle', (event) => console.log(String(event.target)))
|
||||||
|
.run({async: true})
|
||||||
})
|
})
|
||||||
|
|
||||||
function setup (cipher, hash, secret) {
|
function setup (cipher, hash, secret) {
|
||||||
|
@@ -37,5 +37,6 @@ suite.add('sign and verify', (d) => {
|
|||||||
defer: true
|
defer: true
|
||||||
})
|
})
|
||||||
|
|
||||||
suite.on('cycle', (event) => console.log(String(event.target)))
|
suite
|
||||||
.run({async: true})
|
.on('cycle', (event) => console.log(String(event.target)))
|
||||||
|
.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
|
||||||
|
54
package.json
54
package.json
@@ -1,8 +1,9 @@
|
|||||||
{
|
{
|
||||||
"name": "libp2p-crypto",
|
"name": "libp2p-crypto",
|
||||||
"version": "0.10.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": {
|
||||||
"./src/hmac/index.js": "./src/hmac/index-browser.js",
|
"./src/hmac/index.js": "./src/hmac/index-browser.js",
|
||||||
"./src/keys/ecdh.js": "./src/keys/ecdh-browser.js",
|
"./src/keys/ecdh.js": "./src/keys/ecdh-browser.js",
|
||||||
@@ -10,16 +11,16 @@
|
|||||||
"./src/keys/rsa.js": "./src/keys/rsa-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,33 +28,30 @@
|
|||||||
"crypto",
|
"crypto",
|
||||||
"rsa"
|
"rsa"
|
||||||
],
|
],
|
||||||
"author": "Friedel Ziegelmayer <dignifiedquire@gmail.com>",
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"asn1.js": "^4.9.1",
|
"asn1.js": "^5.0.1",
|
||||||
"async": "^2.5.0",
|
"async": "^2.6.1",
|
||||||
"browserify-aes": "^1.0.6",
|
"browserify-aes": "^1.2.0",
|
||||||
|
"bs58": "^4.0.1",
|
||||||
"keypair": "^1.0.1",
|
"keypair": "^1.0.1",
|
||||||
"libp2p-crypto-secp256k1": "~0.2.2",
|
"libp2p-crypto-secp256k1": "~0.2.2",
|
||||||
"multihashing-async": "~0.4.6",
|
"multihashing-async": "~0.5.1",
|
||||||
|
"node-forge": "~0.7.6",
|
||||||
"pem-jwk": "^1.5.1",
|
"pem-jwk": "^1.5.1",
|
||||||
"protocol-buffers": "^3.2.1",
|
"protons": "^1.0.1",
|
||||||
"rsa-pem-to-jwk": "^1.1.3",
|
"rsa-pem-to-jwk": "^1.1.3",
|
||||||
"safe-buffer": "^5.1.1",
|
|
||||||
"tweetnacl": "^1.0.0",
|
"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": "^11.0.2",
|
"aegir": "^15.2.0",
|
||||||
"benchmark": "^2.1.4",
|
"benchmark": "^2.1.4",
|
||||||
"chai": "^4.1.2",
|
"chai": "^4.1.2",
|
||||||
"dirty-chai": "^2.0.1",
|
"chai-string": "^1.5.0",
|
||||||
"pre-commit": "^1.2.2"
|
"dirty-chai": "^2.0.1"
|
||||||
},
|
},
|
||||||
"pre-commit": [
|
|
||||||
"lint",
|
|
||||||
"test"
|
|
||||||
],
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.0.0",
|
"node": ">=6.0.0",
|
||||||
"npm": ">=3.0.0"
|
"npm": ">=3.0.0"
|
||||||
@@ -72,10 +70,14 @@
|
|||||||
"Friedel Ziegelmayer <dignifiedquire@gmail.com>",
|
"Friedel Ziegelmayer <dignifiedquire@gmail.com>",
|
||||||
"Greenkeeper <support@greenkeeper.io>",
|
"Greenkeeper <support@greenkeeper.io>",
|
||||||
"Jack Kleeman <jackkleeman@gmail.com>",
|
"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>",
|
||||||
|
"Richard Schneider <makaretu@gmail.com>",
|
||||||
"Tom Swindell <t.swindell@rubyx.co.uk>",
|
"Tom Swindell <t.swindell@rubyx.co.uk>",
|
||||||
|
"Victor Bjelkholm <victorbjelkholm@gmail.com>",
|
||||||
"Yusef Napora <yusef@napora.org>",
|
"Yusef Napora <yusef@napora.org>",
|
||||||
"greenkeeper[bot] <greenkeeper[bot]@users.noreply.github.com>",
|
"greenkeeper[bot] <greenkeeper[bot]@users.noreply.github.com>",
|
||||||
"nikuda <nikuda@gmail.com>"
|
"nikuda <nikuda@gmail.com>"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
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,7 +1,6 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const nodeify = require('../nodeify')
|
const nodeify = require('../nodeify')
|
||||||
const Buffer = require('safe-buffer').Buffer
|
|
||||||
|
|
||||||
const crypto = require('../webcrypto.js')()
|
const crypto = require('../webcrypto.js')()
|
||||||
const lengths = require('./lengths')
|
const lengths = require('./lengths')
|
||||||
|
@@ -10,3 +10,4 @@ exports.aes = aes
|
|||||||
exports.hmac = hmac
|
exports.hmac = hmac
|
||||||
exports.keys = keys
|
exports.keys = keys
|
||||||
exports.randomBytes = require('./random-bytes')
|
exports.randomBytes = require('./random-bytes')
|
||||||
|
exports.pbkdf2 = require('./pbkdf2')
|
||||||
|
@@ -3,7 +3,6 @@
|
|||||||
const webcrypto = require('../webcrypto.js')()
|
const webcrypto = require('../webcrypto.js')()
|
||||||
const nodeify = require('../nodeify')
|
const nodeify = require('../nodeify')
|
||||||
const BN = require('asn1.js').bignum
|
const BN = require('asn1.js').bignum
|
||||||
const Buffer = require('safe-buffer').Buffer
|
|
||||||
|
|
||||||
const util = require('../util')
|
const util = require('../util')
|
||||||
const toBase64 = util.toBase64
|
const toBase64 = util.toBase64
|
||||||
|
@@ -1,8 +1,8 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const multihashing = require('multihashing-async')
|
const multihashing = require('multihashing-async')
|
||||||
const protobuf = require('protocol-buffers')
|
const protobuf = require('protons')
|
||||||
const Buffer = require('safe-buffer').Buffer
|
const bs58 = require('bs58')
|
||||||
|
|
||||||
const crypto = require('./ed25519')
|
const crypto = require('./ed25519')
|
||||||
const pbm = protobuf(require('./keys.proto'))
|
const pbm = protobuf(require('./keys.proto'))
|
||||||
@@ -78,6 +78,25 @@ class Ed25519PrivateKey {
|
|||||||
ensure(callback)
|
ensure(callback)
|
||||||
multihashing(this.bytes, 'sha2-256', 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) {
|
function unmarshalEd25519PrivateKey (bytes, callback) {
|
||||||
|
@@ -2,36 +2,33 @@
|
|||||||
|
|
||||||
const nacl = require('tweetnacl')
|
const nacl = require('tweetnacl')
|
||||||
const setImmediate = require('async/setImmediate')
|
const setImmediate = require('async/setImmediate')
|
||||||
const Buffer = require('safe-buffer').Buffer
|
|
||||||
|
|
||||||
exports.publicKeyLength = nacl.sign.publicKeyLength
|
exports.publicKeyLength = nacl.sign.publicKeyLength
|
||||||
exports.privateKeyLength = nacl.sign.secretKeyLength
|
exports.privateKeyLength = nacl.sign.secretKeyLength
|
||||||
|
|
||||||
exports.generateKey = function (callback) {
|
exports.generateKey = function (callback) {
|
||||||
const done = (err, res) => setImmediate(() => {
|
setImmediate(() => {
|
||||||
callback(err, res)
|
let result
|
||||||
|
try {
|
||||||
|
result = nacl.sign.keyPair()
|
||||||
|
} catch (err) {
|
||||||
|
return callback(err)
|
||||||
|
}
|
||||||
|
callback(null, result)
|
||||||
})
|
})
|
||||||
|
|
||||||
let keys
|
|
||||||
try {
|
|
||||||
keys = nacl.sign.keyPair()
|
|
||||||
} catch (err) {
|
|
||||||
return done(err)
|
|
||||||
}
|
|
||||||
done(null, keys)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// seed should be a 32 byte uint8array
|
// seed should be a 32 byte uint8array
|
||||||
exports.generateKeyFromSeed = function (seed, callback) {
|
exports.generateKeyFromSeed = function (seed, callback) {
|
||||||
const done = (err, res) => setImmediate(() => callback(err, res))
|
setImmediate(() => {
|
||||||
|
let result
|
||||||
let keys
|
try {
|
||||||
try {
|
result = nacl.sign.keyPair.fromSeed(seed)
|
||||||
keys = nacl.sign.keyPair.fromSeed(seed)
|
} catch (err) {
|
||||||
} catch (err) {
|
return callback(err)
|
||||||
return done(err)
|
}
|
||||||
}
|
callback(null, result)
|
||||||
done(null, keys)
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.hashAndSign = function (key, msg, callback) {
|
exports.hashAndSign = function (key, msg, callback) {
|
||||||
@@ -42,6 +39,13 @@ exports.hashAndSign = function (key, msg, callback) {
|
|||||||
|
|
||||||
exports.hashAndVerify = function (key, sig, msg, callback) {
|
exports.hashAndVerify = function (key, sig, msg, callback) {
|
||||||
setImmediate(() => {
|
setImmediate(() => {
|
||||||
callback(null, nacl.sign.detached.verify(msg, sig, key))
|
let result
|
||||||
|
try {
|
||||||
|
result = nacl.sign.detached.verify(msg, sig, key)
|
||||||
|
} catch (err) {
|
||||||
|
return callback(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
callback(null, result)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,8 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const protobuf = require('protocol-buffers')
|
const protobuf = require('protons')
|
||||||
const keysPBM = protobuf(require('./keys.proto'))
|
const keysPBM = protobuf(require('./keys.proto'))
|
||||||
|
const forge = require('node-forge')
|
||||||
|
|
||||||
exports = module.exports
|
exports = module.exports
|
||||||
|
|
||||||
@@ -50,15 +51,16 @@ exports.generateKeyPairFromSeed = (type, seed, bits, cb) => {
|
|||||||
// representative object
|
// representative object
|
||||||
exports.unmarshalPublicKey = (buf) => {
|
exports.unmarshalPublicKey = (buf) => {
|
||||||
const decoded = keysPBM.PublicKey.decode(buf)
|
const decoded = keysPBM.PublicKey.decode(buf)
|
||||||
|
const data = decoded.Data
|
||||||
|
|
||||||
switch (decoded.Type) {
|
switch (decoded.Type) {
|
||||||
case keysPBM.KeyType.RSA:
|
case keysPBM.KeyType.RSA:
|
||||||
return supportedKeys.rsa.unmarshalRsaPublicKey(decoded.Data)
|
return supportedKeys.rsa.unmarshalRsaPublicKey(data)
|
||||||
case keysPBM.KeyType.Ed25519:
|
case keysPBM.KeyType.Ed25519:
|
||||||
return supportedKeys.ed25519.unmarshalEd25519PublicKey(decoded.Data)
|
return supportedKeys.ed25519.unmarshalEd25519PublicKey(data)
|
||||||
case keysPBM.KeyType.Secp256k1:
|
case keysPBM.KeyType.Secp256k1:
|
||||||
if (supportedKeys.secp256k1) {
|
if (supportedKeys.secp256k1) {
|
||||||
return supportedKeys.secp256k1.unmarshalSecp256k1PublicKey(decoded.Data)
|
return supportedKeys.secp256k1.unmarshalSecp256k1PublicKey(data)
|
||||||
} else {
|
} else {
|
||||||
throw new Error('secp256k1 support requires libp2p-crypto-secp256k1 package')
|
throw new Error('secp256k1 support requires libp2p-crypto-secp256k1 package')
|
||||||
}
|
}
|
||||||
@@ -80,16 +82,23 @@ exports.marshalPublicKey = (key, type) => {
|
|||||||
// Converts a protobuf serialized private key into its
|
// Converts a protobuf serialized private key into its
|
||||||
// representative object
|
// representative object
|
||||||
exports.unmarshalPrivateKey = (buf, callback) => {
|
exports.unmarshalPrivateKey = (buf, callback) => {
|
||||||
const decoded = keysPBM.PrivateKey.decode(buf)
|
let decoded
|
||||||
|
try {
|
||||||
|
decoded = keysPBM.PrivateKey.decode(buf)
|
||||||
|
} catch (err) {
|
||||||
|
return callback(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = decoded.Data
|
||||||
|
|
||||||
switch (decoded.Type) {
|
switch (decoded.Type) {
|
||||||
case keysPBM.KeyType.RSA:
|
case keysPBM.KeyType.RSA:
|
||||||
return supportedKeys.rsa.unmarshalRsaPrivateKey(decoded.Data, callback)
|
return supportedKeys.rsa.unmarshalRsaPrivateKey(data, callback)
|
||||||
case keysPBM.KeyType.Ed25519:
|
case keysPBM.KeyType.Ed25519:
|
||||||
return supportedKeys.ed25519.unmarshalEd25519PrivateKey(decoded.Data, callback)
|
return supportedKeys.ed25519.unmarshalEd25519PrivateKey(data, callback)
|
||||||
case keysPBM.KeyType.Secp256k1:
|
case keysPBM.KeyType.Secp256k1:
|
||||||
if (supportedKeys.secp256k1) {
|
if (supportedKeys.secp256k1) {
|
||||||
return supportedKeys.secp256k1.unmarshalSecp256k1PrivateKey(decoded.Data, callback)
|
return supportedKeys.secp256k1.unmarshalSecp256k1PrivateKey(data, callback)
|
||||||
} else {
|
} else {
|
||||||
return callback(new Error('secp256k1 support requires libp2p-crypto-secp256k1 package'))
|
return callback(new Error('secp256k1 support requires libp2p-crypto-secp256k1 package'))
|
||||||
}
|
}
|
||||||
@@ -107,3 +116,17 @@ exports.marshalPrivateKey = (key, type) => {
|
|||||||
|
|
||||||
return key.bytes
|
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,6 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const whilst = require('async/whilst')
|
const whilst = require('async/whilst')
|
||||||
const Buffer = require('safe-buffer').Buffer
|
|
||||||
const hmac = require('../hmac')
|
const hmac = require('../hmac')
|
||||||
|
|
||||||
const cipherMap = {
|
const cipherMap = {
|
||||||
|
@@ -5,13 +5,11 @@ module.exports = `enum KeyType {
|
|||||||
Ed25519 = 1;
|
Ed25519 = 1;
|
||||||
Secp256k1 = 2;
|
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;
|
||||||
}`
|
}`
|
@@ -1,7 +1,6 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const nodeify = require('../nodeify')
|
const nodeify = require('../nodeify')
|
||||||
const Buffer = require('safe-buffer').Buffer
|
|
||||||
|
|
||||||
const webcrypto = require('../webcrypto.js')()
|
const webcrypto = require('../webcrypto.js')()
|
||||||
|
|
||||||
@@ -18,11 +17,11 @@ exports.generateKey = function (bits, callback) {
|
|||||||
true,
|
true,
|
||||||
['sign', 'verify']
|
['sign', 'verify']
|
||||||
)
|
)
|
||||||
.then(exportKey)
|
.then(exportKey)
|
||||||
.then((keys) => ({
|
.then((keys) => ({
|
||||||
privateKey: keys[0],
|
privateKey: keys[0],
|
||||||
publicKey: keys[1]
|
publicKey: keys[1]
|
||||||
})), callback)
|
})), callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Takes a jwk key
|
// Takes a jwk key
|
||||||
@@ -106,9 +105,7 @@ function derivePublicFromPrivate (jwKey) {
|
|||||||
{
|
{
|
||||||
kty: jwKey.kty,
|
kty: jwKey.kty,
|
||||||
n: jwKey.n,
|
n: jwKey.n,
|
||||||
e: jwKey.e,
|
e: jwKey.e
|
||||||
alg: jwKey.alg,
|
|
||||||
kid: jwKey.kid
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'RSASSA-PKCS1-v1_5',
|
name: 'RSASSA-PKCS1-v1_5',
|
||||||
|
@@ -1,10 +1,13 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const multihashing = require('multihashing-async')
|
const multihashing = require('multihashing-async')
|
||||||
const protobuf = require('protocol-buffers')
|
const protobuf = require('protons')
|
||||||
|
const bs58 = require('bs58')
|
||||||
|
|
||||||
const crypto = require('./rsa')
|
const crypto = require('./rsa')
|
||||||
const pbm = protobuf(require('./keys.proto'))
|
const pbm = protobuf(require('./keys.proto'))
|
||||||
|
const forge = require('node-forge')
|
||||||
|
const setImmediate = require('async/setImmediate')
|
||||||
|
|
||||||
class RsaPublicKey {
|
class RsaPublicKey {
|
||||||
constructor (key) {
|
constructor (key) {
|
||||||
@@ -89,10 +92,74 @@ class RsaPrivateKey {
|
|||||||
ensure(callback)
|
ensure(callback)
|
||||||
multihashing(this.bytes, 'sha2-256', 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) {
|
function unmarshalRsaPrivateKey (bytes, callback) {
|
||||||
const jwk = crypto.utils.pkcs1ToJwk(bytes)
|
const jwk = crypto.utils.pkcs1ToJwk(bytes)
|
||||||
|
|
||||||
crypto.unmarshalPrivateKey(jwk, (err, keys) => {
|
crypto.unmarshalPrivateKey(jwk, (err, keys) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
return callback(err)
|
return callback(err)
|
||||||
@@ -108,18 +175,28 @@ function unmarshalRsaPublicKey (bytes) {
|
|||||||
return new RsaPublicKey(jwk)
|
return new RsaPublicKey(jwk)
|
||||||
}
|
}
|
||||||
|
|
||||||
function generateKeyPair (bits, cb) {
|
function fromJwk (jwk, callback) {
|
||||||
crypto.generateKey(bits, (err, keys) => {
|
crypto.unmarshalPrivateKey(jwk, (err, keys) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
return cb(err)
|
return callback(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
cb(null, new RsaPrivateKey(keys.privateKey, keys.publicKey))
|
callback(null, new RsaPrivateKey(keys.privateKey, keys.publicKey))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function ensure (cb) {
|
function generateKeyPair (bits, callback) {
|
||||||
if (typeof cb !== 'function') {
|
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')
|
throw new Error('callback is required')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -129,5 +206,6 @@ module.exports = {
|
|||||||
RsaPrivateKey,
|
RsaPrivateKey,
|
||||||
unmarshalRsaPublicKey,
|
unmarshalRsaPublicKey,
|
||||||
unmarshalRsaPrivateKey,
|
unmarshalRsaPrivateKey,
|
||||||
generateKeyPair
|
generateKeyPair,
|
||||||
|
fromJwk
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,27 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const crypto = require('crypto')
|
const crypto = require('crypto')
|
||||||
const keypair = require('keypair')
|
let keypair
|
||||||
|
try {
|
||||||
|
if (process.env.LP2P_FORCE_CRYPTO_LIB === 'keypair') {
|
||||||
|
throw new Error('Force keypair usage')
|
||||||
|
}
|
||||||
|
|
||||||
|
const ursa = require('ursa-optional') // throws if not compiled
|
||||||
|
keypair = ({bits}) => {
|
||||||
|
const key = ursa.generatePrivateKey(bits)
|
||||||
|
return {
|
||||||
|
private: key.toPrivatePem(),
|
||||||
|
public: key.toPublicPem()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
if (process.env.LP2P_FORCE_CRYPTO_LIB === 'ursa') {
|
||||||
|
throw e
|
||||||
|
}
|
||||||
|
|
||||||
|
keypair = require('keypair')
|
||||||
|
}
|
||||||
const setImmediate = require('async/setImmediate')
|
const setImmediate = require('async/setImmediate')
|
||||||
const pemToJwk = require('pem-jwk').pem2jwk
|
const pemToJwk = require('pem-jwk').pem2jwk
|
||||||
const jwkToPem = require('pem-jwk').jwk2pem
|
const jwkToPem = require('pem-jwk').jwk2pem
|
||||||
@@ -9,30 +29,36 @@ const jwkToPem = require('pem-jwk').jwk2pem
|
|||||||
exports.utils = require('./rsa-utils')
|
exports.utils = require('./rsa-utils')
|
||||||
|
|
||||||
exports.generateKey = function (bits, callback) {
|
exports.generateKey = function (bits, callback) {
|
||||||
const done = (err, res) => setImmediate(() => callback(err, res))
|
setImmediate(() => {
|
||||||
|
let result
|
||||||
|
try {
|
||||||
|
const key = keypair({ bits: bits })
|
||||||
|
result = {
|
||||||
|
privateKey: pemToJwk(key.private),
|
||||||
|
publicKey: pemToJwk(key.public)
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
return callback(err)
|
||||||
|
}
|
||||||
|
|
||||||
let key
|
callback(null, result)
|
||||||
try {
|
|
||||||
key = keypair({ bits: bits })
|
|
||||||
} catch (err) {
|
|
||||||
return done(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
done(null, {
|
|
||||||
privateKey: pemToJwk(key.private),
|
|
||||||
publicKey: pemToJwk(key.public)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Takes a jwk key
|
// Takes a jwk key
|
||||||
exports.unmarshalPrivateKey = function (key, callback) {
|
exports.unmarshalPrivateKey = function (key, callback) {
|
||||||
callback(null, {
|
setImmediate(() => {
|
||||||
privateKey: key,
|
if (!key) {
|
||||||
publicKey: {
|
return callback(new Error('Key is invalid'))
|
||||||
kty: key.kty,
|
|
||||||
n: key.n,
|
|
||||||
e: key.e
|
|
||||||
}
|
}
|
||||||
|
callback(null, {
|
||||||
|
privateKey: key,
|
||||||
|
publicKey: {
|
||||||
|
kty: key.kty,
|
||||||
|
n: key.n,
|
||||||
|
e: key.e
|
||||||
|
}
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,16 +67,33 @@ exports.getRandomValues = function (arr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
exports.hashAndSign = function (key, msg, callback) {
|
exports.hashAndSign = function (key, msg, callback) {
|
||||||
const sign = crypto.createSign('RSA-SHA256')
|
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))
|
||||||
|
}
|
||||||
|
|
||||||
sign.update(msg)
|
callback(null, result)
|
||||||
setImmediate(() => callback(null, sign.sign(jwkToPem(key))))
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.hashAndVerify = function (key, sig, msg, callback) {
|
exports.hashAndVerify = function (key, sig, msg, callback) {
|
||||||
const verify = crypto.createVerify('RSA-SHA256')
|
setImmediate(() => {
|
||||||
|
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))
|
||||||
|
}
|
||||||
|
|
||||||
verify.update(msg)
|
callback(null, result)
|
||||||
|
})
|
||||||
setImmediate(() => callback(null, verify.verify(jwkToPem(key), sig)))
|
|
||||||
}
|
}
|
||||||
|
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
|
@@ -1,7 +1,6 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const BN = require('asn1.js').bignum
|
const BN = require('asn1.js').bignum
|
||||||
const Buffer = require('safe-buffer').Buffer
|
|
||||||
|
|
||||||
// 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
|
||||||
@@ -11,8 +10,8 @@ exports.toBase64 = function toBase64 (bn, len) {
|
|||||||
|
|
||||||
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
|
||||||
|
@@ -7,7 +7,6 @@ const dirtyChai = require('dirty-chai')
|
|||||||
const expect = chai.expect
|
const expect = chai.expect
|
||||||
chai.use(dirtyChai)
|
chai.use(dirtyChai)
|
||||||
const series = require('async/series')
|
const series = require('async/series')
|
||||||
const Buffer = require('safe-buffer').Buffer
|
|
||||||
|
|
||||||
const crypto = require('../../src')
|
const crypto = require('../../src')
|
||||||
const fixtures = require('./../fixtures/aes')
|
const fixtures = require('./../fixtures/aes')
|
||||||
|
@@ -9,10 +9,11 @@ chai.use(dirtyChai)
|
|||||||
const crypto = require('../src')
|
const crypto = require('../src')
|
||||||
const fixtures = require('./fixtures/go-key-rsa')
|
const fixtures = require('./fixtures/go-key-rsa')
|
||||||
|
|
||||||
describe('libp2p-crypto', () => {
|
describe('libp2p-crypto', function () {
|
||||||
|
this.timeout(20 * 1000)
|
||||||
let key
|
let key
|
||||||
before((done) => {
|
before((done) => {
|
||||||
crypto.keys.generateKeyPair('RSA', 2048, (err, _key) => {
|
crypto.keys.generateKeyPair('RSA', 512, (err, _key) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
return done(err)
|
return done(err)
|
||||||
}
|
}
|
||||||
@@ -106,6 +107,32 @@ describe('libp2p-crypto', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
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', () => {
|
describe('randomBytes', () => {
|
||||||
it('throws with no number passed', () => {
|
it('throws with no number passed', () => {
|
||||||
expect(() => {
|
expect(() => {
|
||||||
|
2
test/fixtures/go-elliptic-key.js
vendored
2
test/fixtures/go-elliptic-key.js
vendored
@@ -1,7 +1,5 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const Buffer = require('safe-buffer').Buffer
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
curve: 'P-256',
|
curve: 'P-256',
|
||||||
bob: {
|
bob: {
|
||||||
|
2
test/fixtures/go-key-ed25519.js
vendored
2
test/fixtures/go-key-ed25519.js
vendored
@@ -1,7 +1,5 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const Buffer = require('safe-buffer').Buffer
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
// These were generated in a gore (https://github.com/motemen/gore) repl session:
|
// These were generated in a gore (https://github.com/motemen/gore) repl session:
|
||||||
//
|
//
|
||||||
|
2
test/fixtures/go-key-rsa.js
vendored
2
test/fixtures/go-key-rsa.js
vendored
@@ -1,7 +1,5 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const Buffer = require('safe-buffer').Buffer
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
private: {
|
private: {
|
||||||
hash: Buffer.from([
|
hash: Buffer.from([
|
||||||
|
2
test/fixtures/go-stretch-key.js
vendored
2
test/fixtures/go-stretch-key.js
vendored
@@ -1,7 +1,5 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const Buffer = require('safe-buffer').Buffer
|
|
||||||
|
|
||||||
module.exports = [{
|
module.exports = [{
|
||||||
cipher: 'AES-256',
|
cipher: 'AES-256',
|
||||||
hash: 'SHA256',
|
hash: 'SHA256',
|
||||||
|
3
test/fixtures/secp256k1.js
vendored
3
test/fixtures/secp256k1.js
vendored
@@ -1,9 +1,6 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const Buffer = require('safe-buffer').Buffer
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
|
||||||
// protobuf marshaled key pair generated with libp2p-crypto-secp256k1
|
// protobuf marshaled key pair generated with libp2p-crypto-secp256k1
|
||||||
// and marshaled with libp2p-crypto.marshalPublicKey / marshalPrivateKey
|
// and marshaled with libp2p-crypto.marshalPublicKey / marshalPrivateKey
|
||||||
pbmPrivateKey: Buffer.from('08021220e0600103010000000100000000000000be1dc82c2e000000e8d6030301000000', 'hex'),
|
pbmPrivateKey: Buffer.from('08021220e0600103010000000100000000000000be1dc82c2e000000e8d6030301000000', '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
|
@@ -2,7 +2,6 @@
|
|||||||
/* eslint-env mocha */
|
/* eslint-env mocha */
|
||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const Buffer = require('safe-buffer').Buffer
|
|
||||||
const chai = require('chai')
|
const chai = require('chai')
|
||||||
const dirtyChai = require('dirty-chai')
|
const dirtyChai = require('dirty-chai')
|
||||||
const expect = chai.expect
|
const expect = chai.expect
|
||||||
|
@@ -5,13 +5,15 @@ const chai = require('chai')
|
|||||||
const dirtyChai = require('dirty-chai')
|
const dirtyChai = require('dirty-chai')
|
||||||
const expect = chai.expect
|
const expect = chai.expect
|
||||||
chai.use(dirtyChai)
|
chai.use(dirtyChai)
|
||||||
const Buffer = require('safe-buffer').Buffer
|
|
||||||
|
|
||||||
const crypto = require('../../src')
|
const crypto = require('../../src')
|
||||||
const ed25519 = crypto.keys.supportedKeys.ed25519
|
const ed25519 = crypto.keys.supportedKeys.ed25519
|
||||||
const fixtures = require('../fixtures/go-key-ed25519')
|
const fixtures = require('../fixtures/go-key-ed25519')
|
||||||
|
|
||||||
describe('ed25519', () => {
|
const testGarbage = require('../helpers/test-garbage-error-handling')
|
||||||
|
|
||||||
|
describe('ed25519', function () {
|
||||||
|
this.timeout(20 * 1000)
|
||||||
let key
|
let key
|
||||||
before((done) => {
|
before((done) => {
|
||||||
crypto.keys.generateKeyPair('Ed25519', 512, (err, _key) => {
|
crypto.keys.generateKeyPair('Ed25519', 512, (err, _key) => {
|
||||||
@@ -115,6 +117,15 @@ describe('ed25519', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
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', () => {
|
describe('key equals', () => {
|
||||||
it('equals itself', () => {
|
it('equals itself', () => {
|
||||||
expect(
|
expect(
|
||||||
@@ -177,6 +188,12 @@ describe('ed25519', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
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', () => {
|
describe('go interop', () => {
|
||||||
let privateKey
|
let privateKey
|
||||||
|
|
||||||
|
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
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
@@ -1,3 +1,4 @@
|
|||||||
|
/* eslint max-nested-callbacks: ["error", 8] */
|
||||||
/* eslint-env mocha */
|
/* eslint-env mocha */
|
||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
@@ -5,17 +6,20 @@ const chai = require('chai')
|
|||||||
const dirtyChai = require('dirty-chai')
|
const dirtyChai = require('dirty-chai')
|
||||||
const expect = chai.expect
|
const expect = chai.expect
|
||||||
chai.use(dirtyChai)
|
chai.use(dirtyChai)
|
||||||
const Buffer = require('safe-buffer').Buffer
|
chai.use(require('chai-string'))
|
||||||
|
|
||||||
const crypto = require('../../src')
|
const crypto = require('../../src')
|
||||||
const rsa = crypto.keys.supportedKeys.rsa
|
const rsa = crypto.keys.supportedKeys.rsa
|
||||||
const fixtures = require('../fixtures/go-key-rsa')
|
const fixtures = require('../fixtures/go-key-rsa')
|
||||||
|
|
||||||
describe('RSA', () => {
|
const testGarbage = require('../helpers/test-garbage-error-handling')
|
||||||
|
|
||||||
|
describe('RSA', function () {
|
||||||
|
this.timeout(20 * 1000)
|
||||||
let key
|
let key
|
||||||
|
|
||||||
before((done) => {
|
before((done) => {
|
||||||
crypto.keys.generateKeyPair('RSA', 2048, (err, _key) => {
|
crypto.keys.generateKeyPair('RSA', 512, (err, _key) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
return done(err)
|
return done(err)
|
||||||
}
|
}
|
||||||
@@ -76,6 +80,15 @@ describe('RSA', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
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', () => {
|
describe('key equals', () => {
|
||||||
it('equals itself', () => {
|
it('equals itself', () => {
|
||||||
expect(key.equals(key)).to.eql(true)
|
expect(key.equals(key)).to.eql(true)
|
||||||
@@ -84,7 +97,7 @@ describe('RSA', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('not equals other key', (done) => {
|
it('not equals other key', (done) => {
|
||||||
crypto.keys.generateKeyPair('RSA', 2048, (err, key2) => {
|
crypto.keys.generateKeyPair('RSA', 512, (err, key2) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
return done(err)
|
return done(err)
|
||||||
}
|
}
|
||||||
@@ -132,6 +145,50 @@ describe('RSA', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
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', () => {
|
describe('go interop', () => {
|
||||||
it('verifies with data from go', (done) => {
|
it('verifies with data from go', (done) => {
|
||||||
const key = crypto.keys.unmarshalPublicKey(fixtures.verify.publicKey)
|
const key = crypto.keys.unmarshalPublicKey(fixtures.verify.publicKey)
|
||||||
@@ -144,4 +201,238 @@ describe('RSA', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
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()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@@ -32,7 +32,7 @@ const mockSecp256k1Module = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
describe('without libp2p-crypto-secp256k1 module present', () => {
|
describe('without libp2p-crypto-secp256k1 module present', () => {
|
||||||
crypto.keys.supportedKeys['secp256k1'] = undefined
|
crypto.keys.supportedKeys.secp256k1 = undefined
|
||||||
|
|
||||||
it('fails to generate a secp256k1 key', (done) => {
|
it('fails to generate a secp256k1 key', (done) => {
|
||||||
crypto.keys.generateKeyPair('secp256k1', 256, (err, key) => {
|
crypto.keys.generateKeyPair('secp256k1', 256, (err, key) => {
|
||||||
@@ -61,7 +61,7 @@ describe('with libp2p-crypto-secp256k1 module present', () => {
|
|||||||
let key
|
let key
|
||||||
|
|
||||||
before((done) => {
|
before((done) => {
|
||||||
crypto.keys.supportedKeys['secp256k1'] = mockSecp256k1Module
|
crypto.keys.supportedKeys.secp256k1 = mockSecp256k1Module
|
||||||
crypto.keys.generateKeyPair('secp256k1', 256, (err, _key) => {
|
crypto.keys.generateKeyPair('secp256k1', 256, (err, _key) => {
|
||||||
if (err) return done(err)
|
if (err) return done(err)
|
||||||
key = _key
|
key = _key
|
||||||
@@ -70,7 +70,7 @@ describe('with libp2p-crypto-secp256k1 module present', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
after((done) => {
|
after((done) => {
|
||||||
delete crypto.keys['secp256k1']
|
delete crypto.keys.secp256k1
|
||||||
done()
|
done()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
3
test/node.js
Normal file
3
test/node.js
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
require('./keys/rsa-crypto-libs')
|
Reference in New Issue
Block a user