mirror of
https://github.com/fluencelabs/js-libp2p-crypto
synced 2025-07-16 07:42:08 +00:00
Compare commits
35 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
567d68c855 | ||
|
af782c5906 | ||
|
f0593c9e6d | ||
|
8d8294dc3f | ||
|
df23d634c5 | ||
|
88e1bcf75f | ||
|
c54ea206f0 | ||
|
857d2bd902 | ||
|
200110cb9d | ||
|
9e5778694c | ||
|
87e8f1c86f | ||
|
df75980a88 | ||
|
934390acd3 | ||
|
8b80b46667 | ||
|
e8efad546f | ||
|
e8cbf13d85 | ||
|
c7e0409c1c | ||
|
f4c00893ad | ||
|
b05e77f375 | ||
|
ad478454d8 | ||
|
8c69ffb20f | ||
|
e689a402a3 | ||
|
4bd032a6ae | ||
|
50c61ba46e | ||
|
3a90f70350 | ||
|
743c69524c | ||
|
1a347fa04c | ||
|
71339e08e7 | ||
|
0ab2c2d2d6 | ||
|
cdcca5f828 | ||
|
2c0dc706b7 | ||
|
21d4c8b74e | ||
|
285b6ca392 | ||
|
7d96dd3243 | ||
|
b3421284f9 |
34
.npmignore
34
.npmignore
@@ -1,34 +0,0 @@
|
||||
**/node_modules/
|
||||
**/*.log
|
||||
test/repo-tests*
|
||||
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
|
||||
coverage
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
|
||||
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
build
|
||||
|
||||
# Dependency directory
|
||||
# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
|
||||
node_modules
|
||||
|
||||
test
|
27
.travis.yml
27
.travis.yml
@@ -1,27 +0,0 @@
|
||||
sudo: false
|
||||
language: node_js
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- node_js: 6
|
||||
env: CXX=g++-4.8
|
||||
- node_js: 8
|
||||
env: CXX=g++-4.8
|
||||
# - node_js: stable
|
||||
# env: CXX=g++-4.8
|
||||
|
||||
script:
|
||||
- npm run lint
|
||||
- npm run test
|
||||
|
||||
before_script:
|
||||
- export DISPLAY=:99.0
|
||||
- sh -e /etc/init.d/xvfb start
|
||||
|
||||
addons:
|
||||
firefox: 'latest'
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- g++-4.8
|
81
CHANGELOG.md
81
CHANGELOG.md
@@ -1,3 +1,84 @@
|
||||
<a name="0.16.0"></a>
|
||||
# [0.16.0](https://github.com/libp2p/js-libp2p-crypto/compare/v0.15.0...v0.16.0) (2019-01-08)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* clean up, bundle size reduction ([8d8294d](https://github.com/libp2p/js-libp2p-crypto/commit/8d8294d))
|
||||
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* getRandomValues method exported from src/keys/rsa-browser.js and src/keys/rsa.js signature has changed from accepting an array to a number for random byte length
|
||||
|
||||
|
||||
|
||||
<a name="0.15.0"></a>
|
||||
# [0.15.0](https://github.com/libp2p/js-libp2p-crypto/compare/v0.14.1...v0.15.0) (2019-01-03)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* nextTick instead of setImmediate, and fix sync in async ([#136](https://github.com/libp2p/js-libp2p-crypto/issues/136)) ([c54ea20](https://github.com/libp2p/js-libp2p-crypto/commit/c54ea20))
|
||||
|
||||
|
||||
|
||||
<a name="0.14.1"></a>
|
||||
## [0.14.1](https://github.com/libp2p/js-libp2p-crypto/compare/v0.14.0...v0.14.1) (2018-11-05)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* dont setimmediate when its not needed ([9e57786](https://github.com/libp2p/js-libp2p-crypto/commit/9e57786))
|
||||
|
||||
|
||||
|
||||
<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)
|
||||
|
||||
|
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).
|
||||
|
||||
## Lead Maintainer
|
||||
|
||||
[Friedel Ziegelmayer](https://github.com/dignifiedquire/)
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Install](#install)
|
||||
@@ -35,6 +39,7 @@ This repo contains the JavaScript implementation of the crypto primitives needed
|
||||
- [`unmarshalPublicKey(buf)`](#unmarshalpublickeybuf)
|
||||
- [`marshalPrivateKey(key[, type])`](#marshalprivatekeykey-type)
|
||||
- [`unmarshalPrivateKey(buf, callback)`](#unmarshalprivatekeybuf-callback)
|
||||
- [`import(pem, password, callback)`](#importpem-password-callback)
|
||||
- [`webcrypto`](#webcrypto)
|
||||
- [Contribute](#contribute)
|
||||
- [License](#license)
|
||||
@@ -69,8 +74,51 @@ This uses `CTR` mode.
|
||||
- `data: Buffer`
|
||||
- `callback: Function`
|
||||
|
||||
```
|
||||
TODO: Example of using aes
|
||||
```js
|
||||
var crypto = require('libp2p-crypto')
|
||||
|
||||
// Setting up Key and IV
|
||||
|
||||
// A 16 bytes array, 128 Bits, AES-128 is chosen
|
||||
var key128 = Buffer.from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15])
|
||||
|
||||
// A 16 bytes array, 128 Bits,
|
||||
var IV = Buffer.from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15])
|
||||
|
||||
async function main () {
|
||||
let decryptedMessage = 'Hello, world!'
|
||||
let encryptedMessage
|
||||
|
||||
// Encrypting
|
||||
await crypto.aes.create(key128, IV, (err, cipher) => {
|
||||
if (!err) {
|
||||
cipher.encrypt(Buffer.from(decryptedMessage), (err, encryptedBuffer) => {
|
||||
if (!err) {
|
||||
console.log(encryptedBuffer)
|
||||
// prints: <Buffer 42 f1 67 d9 2e 42 d0 32 9e b1 f8 3c>
|
||||
encryptedMessage = encryptedBuffer
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
// Decrypting
|
||||
await crypto.aes.create(key128, IV, (err, cipher) => {
|
||||
if (!err) {
|
||||
cipher.decrypt(encryptedMessage, (err, decryptedBuffer) => {
|
||||
if (!err) {
|
||||
console.log(decryptedBuffer)
|
||||
// prints: <Buffer 42 f1 67 d9 2e 42 d0 32 9e b1 f8 3c>
|
||||
|
||||
console.log(decryptedBuffer.toString('utf-8'))
|
||||
// prints: Hello, world!
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
main()
|
||||
|
||||
```
|
||||
|
||||
### `crypto.hmac`
|
||||
@@ -90,8 +138,20 @@ Exposes an interface to the Keyed-Hash Message Authentication Code (HMAC) as def
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
TODO: Example of using hmac
|
||||
```js
|
||||
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`
|
||||
@@ -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.
|
||||
|
||||
### `crypto.keys.import(pem, password, callback)`
|
||||
|
||||
- `pem: string`
|
||||
- `password: string`
|
||||
- `callback: Function`
|
||||
|
||||
Converts a PEM password protected private key into its representative object.
|
||||
|
||||
### `crypto.randomBytes(number)`
|
||||
|
||||
- `number: Number`
|
||||
|
||||
Generates a Buffer with length `number` populated by random bytes.
|
||||
|
||||
### `crypto.pbkdf2(password, salt, iterations, keySize, hash)`
|
||||
|
||||
- `password: String`
|
||||
- `salt: String`
|
||||
- `iterations: Number`
|
||||
- `keySize: Number` in bytes
|
||||
- `hash: String` the hashing algorithm ('sha1', 'sha2-512', ...)
|
||||
|
||||
Computes the Password Based Key Derivation Function 2; returning a new password.
|
||||
|
||||
## Contribute
|
||||
|
||||
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
|
||||
|
||||
[MIT](LICENSE)
|
||||
[MIT](./LICENSE)
|
||||
|
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-console */
|
||||
'use strict'
|
||||
|
||||
const Benchmark = require('benchmark')
|
||||
@@ -24,4 +25,4 @@ curves.forEach((curve) => {
|
||||
|
||||
suite
|
||||
.on('cycle', (event) => console.log(String(event.target)))
|
||||
.run({async: true})
|
||||
.run({ async: true })
|
||||
|
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-console */
|
||||
'use strict'
|
||||
|
||||
const Benchmark = require('benchmark')
|
||||
@@ -24,7 +25,7 @@ async.waterfall([
|
||||
|
||||
suite
|
||||
.on('cycle', (event) => console.log(String(event.target)))
|
||||
.run({async: true})
|
||||
.run({ async: true })
|
||||
})
|
||||
|
||||
function setup (cipher, hash, secret) {
|
||||
|
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-console */
|
||||
'use strict'
|
||||
|
||||
const Benchmark = require('benchmark')
|
||||
@@ -39,4 +40,4 @@ suite.add('sign and verify', (d) => {
|
||||
|
||||
suite
|
||||
.on('cycle', (event) => console.log(String(event.target)))
|
||||
.run({async: true})
|
||||
.run({ async: true })
|
||||
|
2
ci/Jenkinsfile
vendored
Normal file
2
ci/Jenkinsfile
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
// Warning: This file is automatically synced from https://github.com/ipfs/ci-sync so if you want to change it, please change it there and ask someone to sync all repositories.
|
||||
javascript()
|
18
circle.yml
18
circle.yml
@@ -1,18 +0,0 @@
|
||||
machine:
|
||||
node:
|
||||
version: stable
|
||||
|
||||
post:
|
||||
test:
|
||||
- npm run coverage -- --upload
|
||||
|
||||
dependencies:
|
||||
pre:
|
||||
- google-chrome --version
|
||||
- curl -L -o google-chrome.deb https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
|
||||
- sudo dpkg -i google-chrome.deb || true
|
||||
- sudo apt-get update
|
||||
- sudo apt-get install -f
|
||||
- sudo apt-get install --only-upgrade lsb-base
|
||||
- sudo dpkg -i google-chrome.deb
|
||||
- google-chrome --version
|
52
package.json
52
package.json
@@ -1,14 +1,19 @@
|
||||
{
|
||||
"name": "libp2p-crypto",
|
||||
"version": "0.10.4",
|
||||
"version": "0.16.0",
|
||||
"description": "Crypto primitives for libp2p",
|
||||
"main": "src/index.js",
|
||||
"leadMaintainer": "Friedel Ziegelmayer <dignifiedquire@gmail.com>",
|
||||
"browser": {
|
||||
"./src/hmac/index.js": "./src/hmac/index-browser.js",
|
||||
"./src/keys/ecdh.js": "./src/keys/ecdh-browser.js",
|
||||
"./src/aes/ciphers.js": "./src/aes/ciphers-browser.js",
|
||||
"./src/keys/rsa.js": "./src/keys/rsa-browser.js"
|
||||
},
|
||||
"files": [
|
||||
"src",
|
||||
"dist"
|
||||
],
|
||||
"scripts": {
|
||||
"lint": "aegir lint",
|
||||
"build": "aegir build",
|
||||
@@ -19,7 +24,8 @@
|
||||
"release": "aegir release",
|
||||
"release-minor": "aegir release --type minor",
|
||||
"release-major": "aegir release --type major",
|
||||
"coverage": "aegir coverage --ignore src/keys/keys.proto.js"
|
||||
"coverage": "aegir coverage --ignore src/keys/keys.proto.js",
|
||||
"size": "bundlesize -f dist/index.min.js -s 139kB"
|
||||
},
|
||||
"keywords": [
|
||||
"IPFS",
|
||||
@@ -27,35 +33,34 @@
|
||||
"crypto",
|
||||
"rsa"
|
||||
],
|
||||
"author": "Friedel Ziegelmayer <dignifiedquire@gmail.com>",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"asn1.js": "^5.0.0",
|
||||
"async": "^2.6.0",
|
||||
"browserify-aes": "^1.1.1",
|
||||
"asn1.js": "^5.0.1",
|
||||
"async": "^2.6.1",
|
||||
"browserify-aes": "^1.2.0",
|
||||
"bs58": "^4.0.1",
|
||||
"iso-random-stream": "^1.1.0",
|
||||
"keypair": "^1.0.1",
|
||||
"libp2p-crypto-secp256k1": "~0.2.2",
|
||||
"multihashing-async": "~0.4.7",
|
||||
"pem-jwk": "^1.5.1",
|
||||
"protons": "^1.0.0",
|
||||
"libp2p-crypto-secp256k1": "~0.2.3",
|
||||
"multihashing-async": "~0.5.1",
|
||||
"node-forge": "~0.7.6",
|
||||
"pem-jwk": "^2.0.0",
|
||||
"protons": "^1.0.1",
|
||||
"rsa-pem-to-jwk": "^1.1.3",
|
||||
"tweetnacl": "^1.0.0",
|
||||
"webcrypto-shim": "github:dignifiedquire/webcrypto-shim#master"
|
||||
"ursa-optional": "~0.9.10"
|
||||
},
|
||||
"devDependencies": {
|
||||
"aegir": "^12.2.0",
|
||||
"aegir": "^18.0.3",
|
||||
"benchmark": "^2.1.4",
|
||||
"chai": "^4.1.2",
|
||||
"dirty-chai": "^2.0.1",
|
||||
"pre-commit": "^1.2.2"
|
||||
"bundlesize": "~0.17.0",
|
||||
"chai": "^4.2.0",
|
||||
"chai-string": "^1.5.0",
|
||||
"dirty-chai": "^2.0.1"
|
||||
},
|
||||
"pre-commit": [
|
||||
"lint",
|
||||
"test"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=6.0.0",
|
||||
"npm": ">=3.0.0"
|
||||
"node": ">=10.0.0",
|
||||
"npm": ">=6.0.0"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -70,10 +75,15 @@
|
||||
"Dmitriy Ryajov <dryajov@gmail.com>",
|
||||
"Friedel Ziegelmayer <dignifiedquire@gmail.com>",
|
||||
"Greenkeeper <support@greenkeeper.io>",
|
||||
"Hugo Dias <hugomrdias@gmail.com>",
|
||||
"Jack Kleeman <jackkleeman@gmail.com>",
|
||||
"Jacob Heun <jacobheun@gmail.com>",
|
||||
"Joao Santos <jrmsantos15@gmail.com>",
|
||||
"Maciej Krüger <mkg20001@gmail.com>",
|
||||
"Richard Littauer <richard.littauer@gmail.com>",
|
||||
"Richard Schneider <makaretu@gmail.com>",
|
||||
"Tom Swindell <t.swindell@rubyx.co.uk>",
|
||||
"Victor Bjelkholm <victorbjelkholm@gmail.com>",
|
||||
"Yusef Napora <yusef@napora.org>",
|
||||
"greenkeeper[bot] <greenkeeper[bot]@users.noreply.github.com>",
|
||||
"nikuda <nikuda@gmail.com>"
|
||||
|
@@ -1,10 +1,10 @@
|
||||
'use strict'
|
||||
|
||||
const asm = require('asmcrypto.js')
|
||||
const setImmediate = require('async/setImmediate')
|
||||
const nextTick = require('async/nextTick')
|
||||
|
||||
exports.create = function (key, iv, callback) {
|
||||
const done = (err, res) => setImmediate(() => callback(err, res))
|
||||
const done = (err, res) => nextTick(() => callback(err, res))
|
||||
|
||||
if (key.length !== 16 && key.length !== 32) {
|
||||
return done(new Error('Invalid key length'))
|
||||
@@ -21,7 +21,7 @@ exports.create = function (key, iv, callback) {
|
||||
|
||||
const res = {
|
||||
encrypt (data, cb) {
|
||||
const done = (err, res) => setImmediate(() => cb(err, res))
|
||||
const done = (err, res) => nextTick(() => cb(err, res))
|
||||
|
||||
let res
|
||||
try {
|
||||
@@ -36,7 +36,7 @@ exports.create = function (key, iv, callback) {
|
||||
},
|
||||
|
||||
decrypt (data, cb) {
|
||||
const done = (err, res) => setImmediate(() => cb(err, res))
|
||||
const done = (err, res) => nextTick(() => cb(err, res))
|
||||
|
||||
let res
|
||||
try {
|
||||
|
@@ -2,7 +2,7 @@
|
||||
|
||||
const nodeify = require('../nodeify')
|
||||
|
||||
const crypto = require('../webcrypto.js')()
|
||||
const crypto = require('../webcrypto')
|
||||
const lengths = require('./lengths')
|
||||
|
||||
const hashTypes = {
|
||||
@@ -12,7 +12,7 @@ const hashTypes = {
|
||||
}
|
||||
|
||||
const sign = (key, data, cb) => {
|
||||
nodeify(crypto.subtle.sign({name: 'HMAC'}, key, data)
|
||||
nodeify(crypto.subtle.sign({ name: 'HMAC' }, key, data)
|
||||
.then((raw) => Buffer.from(raw)), cb)
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ exports.create = function (hashType, secret, callback) {
|
||||
secret,
|
||||
{
|
||||
name: 'HMAC',
|
||||
hash: {name: hash}
|
||||
hash: { name: hash }
|
||||
},
|
||||
false,
|
||||
['sign']
|
||||
|
@@ -2,6 +2,7 @@
|
||||
|
||||
const crypto = require('crypto')
|
||||
const lengths = require('./lengths')
|
||||
const nextTick = require('async/nextTick')
|
||||
|
||||
exports.create = function (hash, secret, callback) {
|
||||
const res = {
|
||||
@@ -10,7 +11,7 @@ exports.create = function (hash, secret, callback) {
|
||||
|
||||
hmac.update(data)
|
||||
|
||||
setImmediate(() => {
|
||||
nextTick(() => {
|
||||
cb(null, hmac.digest())
|
||||
})
|
||||
},
|
||||
|
@@ -10,3 +10,4 @@ exports.aes = aes
|
||||
exports.hmac = hmac
|
||||
exports.keys = keys
|
||||
exports.randomBytes = require('./random-bytes')
|
||||
exports.pbkdf2 = require('./pbkdf2')
|
||||
|
@@ -1,6 +1,6 @@
|
||||
'use strict'
|
||||
|
||||
const webcrypto = require('../webcrypto.js')()
|
||||
const webcrypto = require('../webcrypto')
|
||||
const nodeify = require('../nodeify')
|
||||
const BN = require('asn1.js').bignum
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
'use strict'
|
||||
|
||||
const crypto = require('crypto')
|
||||
const setImmediate = require('async/setImmediate')
|
||||
const nextTick = require('async/nextTick')
|
||||
|
||||
const curves = {
|
||||
'P-256': 'prime256v1',
|
||||
@@ -16,7 +16,7 @@ exports.generateEphmeralKeyPair = function (curve, callback) {
|
||||
const ecdh = crypto.createECDH(curves[curve])
|
||||
ecdh.generateKeys()
|
||||
|
||||
setImmediate(() => callback(null, {
|
||||
nextTick(() => callback(null, {
|
||||
key: ecdh.getPublicKey(),
|
||||
genSharedKey (theirPub, forcePrivate, cb) {
|
||||
if (typeof forcePrivate === 'function') {
|
||||
@@ -35,7 +35,7 @@ exports.generateEphmeralKeyPair = function (curve, callback) {
|
||||
return cb(err)
|
||||
}
|
||||
|
||||
setImmediate(() => cb(null, secret))
|
||||
nextTick(() => cb(null, secret))
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
@@ -2,6 +2,7 @@
|
||||
|
||||
const multihashing = require('multihashing-async')
|
||||
const protobuf = require('protons')
|
||||
const bs58 = require('bs58')
|
||||
|
||||
const crypto = require('./ed25519')
|
||||
const pbm = protobuf(require('./keys.proto'))
|
||||
@@ -77,6 +78,25 @@ class Ed25519PrivateKey {
|
||||
ensure(callback)
|
||||
multihashing(this.bytes, 'sha2-256', callback)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the ID of the key.
|
||||
*
|
||||
* The key id is the base58 encoding of the SHA-256 multihash of its public key.
|
||||
* The public key is a protobuf encoding containing a type and the DER encoding
|
||||
* of the PKCS SubjectPublicKeyInfo.
|
||||
*
|
||||
* @param {function(Error, id)} callback
|
||||
* @returns {undefined}
|
||||
*/
|
||||
id (callback) {
|
||||
this.public.hash((err, hash) => {
|
||||
if (err) {
|
||||
return callback(err)
|
||||
}
|
||||
callback(null, bs58.encode(hash))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function unmarshalEd25519PrivateKey (bytes, callback) {
|
||||
|
@@ -1,13 +1,13 @@
|
||||
'use strict'
|
||||
|
||||
const nacl = require('tweetnacl')
|
||||
const setImmediate = require('async/setImmediate')
|
||||
const nextTick = require('async/nextTick')
|
||||
|
||||
exports.publicKeyLength = nacl.sign.publicKeyLength
|
||||
exports.privateKeyLength = nacl.sign.secretKeyLength
|
||||
|
||||
exports.generateKey = function (callback) {
|
||||
setImmediate(() => {
|
||||
nextTick(() => {
|
||||
let result
|
||||
try {
|
||||
result = nacl.sign.keyPair()
|
||||
@@ -20,7 +20,7 @@ exports.generateKey = function (callback) {
|
||||
|
||||
// seed should be a 32 byte uint8array
|
||||
exports.generateKeyFromSeed = function (seed, callback) {
|
||||
setImmediate(() => {
|
||||
nextTick(() => {
|
||||
let result
|
||||
try {
|
||||
result = nacl.sign.keyPair.fromSeed(seed)
|
||||
@@ -32,13 +32,13 @@ exports.generateKeyFromSeed = function (seed, callback) {
|
||||
}
|
||||
|
||||
exports.hashAndSign = function (key, msg, callback) {
|
||||
setImmediate(() => {
|
||||
nextTick(() => {
|
||||
callback(null, Buffer.from(nacl.sign.detached(msg, key)))
|
||||
})
|
||||
}
|
||||
|
||||
exports.hashAndVerify = function (key, sig, msg, callback) {
|
||||
setImmediate(() => {
|
||||
nextTick(() => {
|
||||
let result
|
||||
try {
|
||||
result = nacl.sign.detached.verify(msg, sig, key)
|
||||
|
@@ -2,6 +2,10 @@
|
||||
|
||||
const protobuf = require('protons')
|
||||
const keysPBM = protobuf(require('./keys.proto'))
|
||||
require('node-forge/lib/asn1')
|
||||
require('node-forge/lib/rsa')
|
||||
require('node-forge/lib/pbe')
|
||||
const forge = require('node-forge/lib/forge')
|
||||
|
||||
exports = module.exports
|
||||
|
||||
@@ -115,3 +119,17 @@ exports.marshalPrivateKey = (key, type) => {
|
||||
|
||||
return key.bytes
|
||||
}
|
||||
|
||||
exports.import = (pem, password, callback) => {
|
||||
try {
|
||||
const key = forge.pki.decryptRsaPrivateKey(pem, password)
|
||||
if (key === null) {
|
||||
throw new Error('Cannot read the key, most likely the password is wrong or not a RSA key')
|
||||
}
|
||||
let der = forge.asn1.toDer(forge.pki.privateKeyToAsn1(key))
|
||||
der = Buffer.from(der.getBytes(), 'binary')
|
||||
return supportedKeys.rsa.unmarshalRsaPrivateKey(der, callback)
|
||||
} catch (err) {
|
||||
callback(err)
|
||||
}
|
||||
}
|
||||
|
@@ -1,8 +1,8 @@
|
||||
'use strict'
|
||||
|
||||
const nodeify = require('../nodeify')
|
||||
|
||||
const webcrypto = require('../webcrypto.js')()
|
||||
const webcrypto = require('../webcrypto')
|
||||
const randomBytes = require('../random-bytes')
|
||||
|
||||
exports.utils = require('./rsa-utils')
|
||||
|
||||
@@ -12,7 +12,7 @@ exports.generateKey = function (bits, callback) {
|
||||
name: 'RSASSA-PKCS1-v1_5',
|
||||
modulusLength: bits,
|
||||
publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
|
||||
hash: {name: 'SHA-256'}
|
||||
hash: { name: 'SHA-256' }
|
||||
},
|
||||
true,
|
||||
['sign', 'verify']
|
||||
@@ -31,7 +31,7 @@ exports.unmarshalPrivateKey = function (key, callback) {
|
||||
key,
|
||||
{
|
||||
name: 'RSASSA-PKCS1-v1_5',
|
||||
hash: {name: 'SHA-256'}
|
||||
hash: { name: 'SHA-256' }
|
||||
},
|
||||
true,
|
||||
['sign']
|
||||
@@ -49,9 +49,7 @@ exports.unmarshalPrivateKey = function (key, callback) {
|
||||
})), callback)
|
||||
}
|
||||
|
||||
exports.getRandomValues = function (arr) {
|
||||
return Buffer.from(webcrypto.getRandomValues(arr))
|
||||
}
|
||||
exports.getRandomValues = randomBytes
|
||||
|
||||
exports.hashAndSign = function (key, msg, callback) {
|
||||
nodeify(webcrypto.subtle.importKey(
|
||||
@@ -59,13 +57,13 @@ exports.hashAndSign = function (key, msg, callback) {
|
||||
key,
|
||||
{
|
||||
name: 'RSASSA-PKCS1-v1_5',
|
||||
hash: {name: 'SHA-256'}
|
||||
hash: { name: 'SHA-256' }
|
||||
},
|
||||
false,
|
||||
['sign']
|
||||
).then((privateKey) => {
|
||||
return webcrypto.subtle.sign(
|
||||
{name: 'RSASSA-PKCS1-v1_5'},
|
||||
{ name: 'RSASSA-PKCS1-v1_5' },
|
||||
privateKey,
|
||||
Uint8Array.from(msg)
|
||||
)
|
||||
@@ -78,13 +76,13 @@ exports.hashAndVerify = function (key, sig, msg, callback) {
|
||||
key,
|
||||
{
|
||||
name: 'RSASSA-PKCS1-v1_5',
|
||||
hash: {name: 'SHA-256'}
|
||||
hash: { name: 'SHA-256' }
|
||||
},
|
||||
false,
|
||||
['verify']
|
||||
).then((publicKey) => {
|
||||
return webcrypto.subtle.verify(
|
||||
{name: 'RSASSA-PKCS1-v1_5'},
|
||||
{ name: 'RSASSA-PKCS1-v1_5' },
|
||||
publicKey,
|
||||
sig,
|
||||
msg
|
||||
@@ -105,13 +103,11 @@ function derivePublicFromPrivate (jwKey) {
|
||||
{
|
||||
kty: jwKey.kty,
|
||||
n: jwKey.n,
|
||||
e: jwKey.e,
|
||||
alg: jwKey.alg,
|
||||
kid: jwKey.kid
|
||||
e: jwKey.e
|
||||
},
|
||||
{
|
||||
name: 'RSASSA-PKCS1-v1_5',
|
||||
hash: {name: 'SHA-256'}
|
||||
hash: { name: 'SHA-256' }
|
||||
},
|
||||
true,
|
||||
['verify']
|
||||
|
@@ -2,9 +2,14 @@
|
||||
|
||||
const multihashing = require('multihashing-async')
|
||||
const protobuf = require('protons')
|
||||
const bs58 = require('bs58')
|
||||
const nextTick = require('async/nextTick')
|
||||
|
||||
const crypto = require('./rsa')
|
||||
const pbm = protobuf(require('./keys.proto'))
|
||||
require('node-forge/lib/sha512')
|
||||
require('node-forge/lib/pbe')
|
||||
const forge = require('node-forge/lib/forge')
|
||||
|
||||
class RsaPublicKey {
|
||||
constructor (key) {
|
||||
@@ -50,7 +55,7 @@ class RsaPrivateKey {
|
||||
}
|
||||
|
||||
genSecret () {
|
||||
return crypto.getRandomValues(new Uint8Array(16))
|
||||
return crypto.getRandomValues(16)
|
||||
}
|
||||
|
||||
sign (message, callback) {
|
||||
@@ -89,10 +94,73 @@ class RsaPrivateKey {
|
||||
ensure(callback)
|
||||
multihashing(this.bytes, 'sha2-256', callback)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the ID of the key.
|
||||
*
|
||||
* The key id is the base58 encoding of the SHA-256 multihash of its public key.
|
||||
* The public key is a protobuf encoding containing a type and the DER encoding
|
||||
* of the PKCS SubjectPublicKeyInfo.
|
||||
*
|
||||
* @param {function(Error, id)} callback
|
||||
* @returns {undefined}
|
||||
*/
|
||||
id (callback) {
|
||||
this.public.hash((err, hash) => {
|
||||
if (err) {
|
||||
return callback(err)
|
||||
}
|
||||
callback(null, bs58.encode(hash))
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Exports the key into a password protected PEM format
|
||||
*
|
||||
* @param {string} [format] - Defaults to 'pkcs-8'.
|
||||
* @param {string} password - The password to read the encrypted PEM
|
||||
* @param {function(Error, KeyInfo)} callback
|
||||
* @returns {undefined}
|
||||
*/
|
||||
export (format, password, callback) {
|
||||
if (typeof password === 'function') {
|
||||
callback = password
|
||||
password = format
|
||||
format = 'pkcs-8'
|
||||
}
|
||||
|
||||
ensure(callback)
|
||||
|
||||
nextTick(() => {
|
||||
let err = null
|
||||
let pem = null
|
||||
try {
|
||||
const buffer = new forge.util.ByteBuffer(this.marshal())
|
||||
const asn1 = forge.asn1.fromDer(buffer)
|
||||
const privateKey = forge.pki.privateKeyFromAsn1(asn1)
|
||||
if (format === 'pkcs-8') {
|
||||
const options = {
|
||||
algorithm: 'aes256',
|
||||
count: 10000,
|
||||
saltSize: 128 / 8,
|
||||
prfAlgorithm: 'sha512'
|
||||
}
|
||||
pem = forge.pki.encryptRsaPrivateKey(privateKey, password, options)
|
||||
} else {
|
||||
err = new Error(`Unknown export format '${format}'`)
|
||||
}
|
||||
} catch (_err) {
|
||||
err = _err
|
||||
}
|
||||
|
||||
callback(err, pem)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function unmarshalRsaPrivateKey (bytes, callback) {
|
||||
const jwk = crypto.utils.pkcs1ToJwk(bytes)
|
||||
|
||||
crypto.unmarshalPrivateKey(jwk, (err, keys) => {
|
||||
if (err) {
|
||||
return callback(err)
|
||||
@@ -108,18 +176,28 @@ function unmarshalRsaPublicKey (bytes) {
|
||||
return new RsaPublicKey(jwk)
|
||||
}
|
||||
|
||||
function generateKeyPair (bits, cb) {
|
||||
crypto.generateKey(bits, (err, keys) => {
|
||||
function fromJwk (jwk, callback) {
|
||||
crypto.unmarshalPrivateKey(jwk, (err, keys) => {
|
||||
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) {
|
||||
if (typeof cb !== 'function') {
|
||||
function generateKeyPair (bits, callback) {
|
||||
crypto.generateKey(bits, (err, keys) => {
|
||||
if (err) {
|
||||
return callback(err)
|
||||
}
|
||||
|
||||
callback(null, new RsaPrivateKey(keys.privateKey, keys.publicKey))
|
||||
})
|
||||
}
|
||||
|
||||
function ensure (callback) {
|
||||
if (typeof callback !== 'function') {
|
||||
throw new Error('callback is required')
|
||||
}
|
||||
}
|
||||
@@ -129,5 +207,6 @@ module.exports = {
|
||||
RsaPrivateKey,
|
||||
unmarshalRsaPublicKey,
|
||||
unmarshalRsaPrivateKey,
|
||||
generateKeyPair
|
||||
generateKeyPair,
|
||||
fromJwk
|
||||
}
|
||||
|
@@ -1,15 +1,37 @@
|
||||
'use strict'
|
||||
|
||||
const crypto = require('crypto')
|
||||
const keypair = require('keypair')
|
||||
const setImmediate = require('async/setImmediate')
|
||||
const randomBytes = require('../random-bytes')
|
||||
const nextTick = require('async/nextTick')
|
||||
|
||||
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 pemToJwk = require('pem-jwk').pem2jwk
|
||||
const jwkToPem = require('pem-jwk').jwk2pem
|
||||
|
||||
exports.utils = require('./rsa-utils')
|
||||
|
||||
exports.generateKey = function (bits, callback) {
|
||||
setImmediate(() => {
|
||||
nextTick(() => {
|
||||
let result
|
||||
try {
|
||||
const key = keypair({ bits: bits })
|
||||
@@ -27,7 +49,7 @@ exports.generateKey = function (bits, callback) {
|
||||
|
||||
// Takes a jwk key
|
||||
exports.unmarshalPrivateKey = function (key, callback) {
|
||||
setImmediate(() => {
|
||||
nextTick(() => {
|
||||
if (!key) {
|
||||
return callback(new Error('Key is invalid'))
|
||||
}
|
||||
@@ -42,12 +64,10 @@ exports.unmarshalPrivateKey = function (key, callback) {
|
||||
})
|
||||
}
|
||||
|
||||
exports.getRandomValues = function (arr) {
|
||||
return crypto.randomBytes(arr.length)
|
||||
}
|
||||
exports.getRandomValues = randomBytes
|
||||
|
||||
exports.hashAndSign = function (key, msg, callback) {
|
||||
setImmediate(() => {
|
||||
nextTick(() => {
|
||||
let result
|
||||
try {
|
||||
const sign = crypto.createSign('RSA-SHA256')
|
||||
@@ -63,7 +83,7 @@ exports.hashAndSign = function (key, msg, callback) {
|
||||
}
|
||||
|
||||
exports.hashAndVerify = function (key, sig, msg, callback) {
|
||||
setImmediate(() => {
|
||||
nextTick(() => {
|
||||
let result
|
||||
try {
|
||||
const verify = crypto.createVerify('RSA-SHA256')
|
||||
|
43
src/pbkdf2.js
Normal file
43
src/pbkdf2.js
Normal file
@@ -0,0 +1,43 @@
|
||||
'use strict'
|
||||
|
||||
const forgePbkdf2 = require('node-forge/lib/pbkdf2')
|
||||
const forgeUtil = require('node-forge/lib/util')
|
||||
|
||||
/**
|
||||
* 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 = forgePbkdf2(
|
||||
password,
|
||||
salt,
|
||||
iterations,
|
||||
keySize,
|
||||
hasher)
|
||||
return forgeUtil.encode64(dek)
|
||||
}
|
||||
|
||||
module.exports = pbkdf2
|
@@ -1,13 +1,9 @@
|
||||
'use strict'
|
||||
const randomBytes = require('iso-random-stream/src/random')
|
||||
|
||||
const rsa = require('./keys/rsa')
|
||||
|
||||
function randomBytes (number) {
|
||||
module.exports = function (number) {
|
||||
if (!number || typeof number !== 'number') {
|
||||
throw new Error('first argument must be a Number bigger than 0')
|
||||
}
|
||||
|
||||
return rsa.getRandomValues(new Uint8Array(number))
|
||||
return randomBytes(number)
|
||||
}
|
||||
|
||||
module.exports = randomBytes
|
||||
|
@@ -2,15 +2,4 @@
|
||||
|
||||
'use strict'
|
||||
|
||||
module.exports = () => {
|
||||
// This is only a shim for interfaces, not for functionality
|
||||
if (typeof self !== 'undefined') {
|
||||
require('webcrypto-shim')(self)
|
||||
|
||||
if (self.crypto) {
|
||||
return self.crypto
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error('Please use an environment with crypto support')
|
||||
}
|
||||
module.exports = self.crypto || self.msCrypto
|
||||
|
@@ -13,7 +13,7 @@ describe('libp2p-crypto', function () {
|
||||
this.timeout(20 * 1000)
|
||||
let key
|
||||
before((done) => {
|
||||
crypto.keys.generateKeyPair('RSA', 2048, (err, _key) => {
|
||||
crypto.keys.generateKeyPair('RSA', 512, (err, _key) => {
|
||||
if (err) {
|
||||
return done(err)
|
||||
}
|
||||
@@ -107,6 +107,32 @@ describe('libp2p-crypto', function () {
|
||||
})
|
||||
})
|
||||
|
||||
describe('pbkdf2', () => {
|
||||
it('generates a derived password using sha1', () => {
|
||||
const p1 = crypto.pbkdf2('password', 'at least 16 character salt', 500, 512 / 8, 'sha1')
|
||||
expect(p1).to.exist()
|
||||
expect(p1).to.be.a('string')
|
||||
})
|
||||
|
||||
it('generates a derived password using sha2-512', () => {
|
||||
const p1 = crypto.pbkdf2('password', 'at least 16 character salt', 500, 512 / 8, 'sha2-512')
|
||||
expect(p1).to.exist()
|
||||
expect(p1).to.be.a('string')
|
||||
})
|
||||
|
||||
it('generates the same derived password with the same options', () => {
|
||||
const p1 = crypto.pbkdf2('password', 'at least 16 character salt', 10, 512 / 8, 'sha1')
|
||||
const p2 = crypto.pbkdf2('password', 'at least 16 character salt', 10, 512 / 8, 'sha1')
|
||||
const p3 = crypto.pbkdf2('password', 'at least 16 character salt', 11, 512 / 8, 'sha1')
|
||||
expect(p2).to.equal(p1)
|
||||
expect(p3).to.not.equal(p2)
|
||||
})
|
||||
|
||||
it('throws on invalid hash name', () => {
|
||||
expect(() => crypto.pbkdf2('password', 'at least 16 character salt', 500, 512 / 8, 'shaX-xxx')).to.throw()
|
||||
})
|
||||
})
|
||||
|
||||
describe('randomBytes', () => {
|
||||
it('throws with no number passed', () => {
|
||||
expect(() => {
|
||||
|
@@ -117,6 +117,15 @@ describe('ed25519', function () {
|
||||
})
|
||||
})
|
||||
|
||||
it('key id', (done) => {
|
||||
key.id((err, id) => {
|
||||
expect(err).to.not.exist()
|
||||
expect(id).to.exist()
|
||||
expect(id).to.be.a('string')
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
describe('key equals', () => {
|
||||
it('equals itself', () => {
|
||||
expect(
|
||||
|
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 */
|
||||
'use strict'
|
||||
|
||||
@@ -5,6 +6,7 @@ const chai = require('chai')
|
||||
const dirtyChai = require('dirty-chai')
|
||||
const expect = chai.expect
|
||||
chai.use(dirtyChai)
|
||||
chai.use(require('chai-string'))
|
||||
|
||||
const crypto = require('../../src')
|
||||
const rsa = crypto.keys.supportedKeys.rsa
|
||||
@@ -17,7 +19,7 @@ describe('RSA', function () {
|
||||
let key
|
||||
|
||||
before((done) => {
|
||||
crypto.keys.generateKeyPair('RSA', 2048, (err, _key) => {
|
||||
crypto.keys.generateKeyPair('RSA', 512, (err, _key) => {
|
||||
if (err) {
|
||||
return done(err)
|
||||
}
|
||||
@@ -78,6 +80,15 @@ describe('RSA', function () {
|
||||
})
|
||||
})
|
||||
|
||||
it('key id', (done) => {
|
||||
key.id((err, id) => {
|
||||
expect(err).to.not.exist()
|
||||
expect(id).to.exist()
|
||||
expect(id).to.be.a('string')
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
describe('key equals', () => {
|
||||
it('equals itself', () => {
|
||||
expect(key.equals(key)).to.eql(true)
|
||||
@@ -86,7 +97,7 @@ describe('RSA', function () {
|
||||
})
|
||||
|
||||
it('not equals other key', (done) => {
|
||||
crypto.keys.generateKeyPair('RSA', 2048, (err, key2) => {
|
||||
crypto.keys.generateKeyPair('RSA', 512, (err, key2) => {
|
||||
if (err) {
|
||||
return done(err)
|
||||
}
|
||||
@@ -134,6 +145,44 @@ describe('RSA', function () {
|
||||
})
|
||||
})
|
||||
|
||||
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)
|
||||
@@ -152,4 +201,238 @@ describe('RSA', function () {
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
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-----
|
||||
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
|
||||
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()
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
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