feat: refactor to use async/await (#131)

BREAKING CHANGE: API refactored to use async/await

feat: WIP use async await
fix: passing tests
chore: update travis node.js versions
fix: skip ursa optional tests on windows
fix: benchmarks
docs: update docs
fix: remove broken and intested private key decrypt
chore: update deps
This commit is contained in:
Alan Shaw 2019-07-10 17:15:26 +01:00 committed by Jacob Heun
parent 5cd0e8cc1a
commit ad7107233e
32 changed files with 690 additions and 1261 deletions

167
README.md
View File

@ -19,28 +19,31 @@ This repo contains the JavaScript implementation of the crypto primitives needed
## Table of Contents ## Table of Contents
- [Install](#install) - [js-libp2p-crypto](#js-libp2p-crypto)
- [API](#api) - [Lead Maintainer](#Lead-Maintainer)
- [`crypto.hmac`](#cryptohmac) - [Table of Contents](#Table-of-Contents)
- [`create(hash, secret, callback)`](#cryptohmaccreatehash-secret-callback) - [Install](#Install)
- [`digest(data, callback)`](#digestdata-callback) - [API](#API)
- [`crypto.aes`](#cryptoaes) - [`crypto.aes`](#cryptoaes)
- [`create(key, iv, callback)`](#cryptoaescreatekey-iv-callback) - [`crypto.aes.create(key, iv)`](#cryptoaescreatekey-iv)
- [`encrypt(data, callback)`](#encryptdata-callback) - [`decrypt(data)`](#decryptdata)
- [`decrypt(data, callback)`](#decryptdata-callback) - [`encrypt(data)`](#encryptdata)
- [`keys`](#cryptokeys) - [`crypto.hmac`](#cryptohmac)
- [`generateKeyPair(type, bits, callback)`](#cryptokeysgeneratekeypairtype-bits-callback) - [`crypto.hmac.create(hash, secret)`](#cryptohmaccreatehash-secret)
- [`generateEphemeralKeyPair(curve, callback)`](#cryptokeysgenerateephemeralkeypaircurve-callback) - [`digest(data)`](#digestdata)
- [`keyStretcher(cipherType, hashType, secret, callback)`](#cryptokeyskeystretcherciphertype-hashtype-secret-callback) - [`crypto.keys`](#cryptokeys)
- [`marshalPublicKey(key[, type], callback)`](#cryptokeysmarshalpublickeykey-type-callback) - [`crypto.keys.generateKeyPair(type, bits)`](#cryptokeysgenerateKeyPairtype-bits)
- [`unmarshalPublicKey(buf)`](#cryptokeysunmarshalpublickeybuf) - [`crypto.keys.generateEphemeralKeyPair(curve)`](#cryptokeysgenerateEphemeralKeyPaircurve)
- [`marshalPrivateKey(key[, type])`](#cryptokeysmarshalprivatekeykey-type) - [`crypto.keys.keyStretcher(cipherType, hashType, secret)`](#cryptokeyskeyStretchercipherType-hashType-secret)
- [`unmarshalPrivateKey(buf, callback)`](#cryptokeysunmarshalprivatekeybuf-callback) - [`crypto.keys.marshalPublicKey(key, [type])`](#cryptokeysmarshalPublicKeykey-type)
- [`import(pem, password, callback)`](#cryptokeysimportpem-password-callback) - [`crypto.keys.unmarshalPublicKey(buf)`](#cryptokeysunmarshalPublicKeybuf)
- [`randomBytes(number)`](#cryptorandombytesnumber) - [`crypto.keys.marshalPrivateKey(key, [type])`](#cryptokeysmarshalPrivateKeykey-type)
- [`pbkdf2(password, salt, iterations, keySize, hash)`](#cryptopbkdf2password-salt-iterations-keysize-hash) - [`crypto.keys.unmarshalPrivateKey(buf)`](#cryptokeysunmarshalPrivateKeybuf)
- [Contribute](#contribute) - [`crypto.keys.import(pem, password)`](#cryptokeysimportpem-password)
- [License](#license) - [`crypto.randomBytes(number)`](#cryptorandomBytesnumber)
- [`crypto.pbkdf2(password, salt, iterations, keySize, hash)`](#cryptopbkdf2password-salt-iterations-keySize-hash)
- [Contribute](#Contribute)
- [License](#License)
## Install ## Install
@ -56,130 +59,121 @@ Expoes an interface to AES encryption (formerly Rijndael), as defined in U.S. Fe
This uses `CTR` mode. This uses `CTR` mode.
#### `crypto.aes.create(key, iv, callback)` #### `crypto.aes.create(key, iv)`
- `key: Buffer` The key, if length `16` then `AES 128` is used. For length `32`, `AES 256` is used. - `key: Buffer` The key, if length `16` then `AES 128` is used. For length `32`, `AES 256` is used.
- `iv: Buffer` Must have length `16`. - `iv: Buffer` Must have length `16`.
- `callback: Function`
##### `decrypt(data, callback)` Returns `Promise<{decrypt<Function>, encrypt<Function>}>`
##### `decrypt(data)`
- `data: Buffer` - `data: Buffer`
- `callback: Function`
##### `encrypt(data, callback)` Returns `Promise<Buffer>`
##### `encrypt(data)`
- `data: Buffer` - `data: Buffer`
- `callback: Function`
Returns `Promise<Buffer>`
```js ```js
var crypto = require('libp2p-crypto') const crypto = require('libp2p-crypto')
// Setting up Key and IV // Setting up Key and IV
// A 16 bytes array, 128 Bits, AES-128 is chosen // 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]) const 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, // 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]) const IV = Buffer.from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15])
async function main () { async function main () {
let decryptedMessage = 'Hello, world!' const decryptedMessage = 'Hello, world!'
let encryptedMessage
// Encrypting // Encrypting
await crypto.aes.create(key128, IV, (err, cipher) => { const cipher = await crypto.aes.create(key128, IV)
if (!err) { const encryptedBuffer = await cipher.encrypt(Buffer.from(decryptedMessage))
cipher.encrypt(Buffer.from(decryptedMessage), (err, encryptedBuffer) => {
if (!err) {
console.log(encryptedBuffer) console.log(encryptedBuffer)
// prints: <Buffer 42 f1 67 d9 2e 42 d0 32 9e b1 f8 3c> // prints: <Buffer 42 f1 67 d9 2e 42 d0 32 9e b1 f8 3c>
encryptedMessage = encryptedBuffer
}
})
}
})
// Decrypting // Decrypting
await crypto.aes.create(key128, IV, (err, cipher) => { const decipher = await crypto.aes.create(key128, IV)
if (!err) { const decryptedBuffer = await cipher.decrypt(encryptedBuffer)
cipher.decrypt(encryptedMessage, (err, decryptedBuffer) => {
if (!err) {
console.log(decryptedBuffer) console.log(decryptedBuffer)
// prints: <Buffer 42 f1 67 d9 2e 42 d0 32 9e b1 f8 3c> // prints: <Buffer 42 f1 67 d9 2e 42 d0 32 9e b1 f8 3c>
console.log(decryptedBuffer.toString('utf-8')) console.log(decryptedBuffer.toString('utf-8'))
// prints: Hello, world! // prints: Hello, world!
}
})
}
})
} }
main()
main()
``` ```
### `crypto.hmac` ### `crypto.hmac`
Exposes an interface to the Keyed-Hash Message Authentication Code (HMAC) as defined in U.S. Federal Information Processing Standards Publication 198. An HMAC is a cryptographic hash that uses a key to sign a message. The receiver verifies the hash by recomputing it using the same key. Exposes an interface to the Keyed-Hash Message Authentication Code (HMAC) as defined in U.S. Federal Information Processing Standards Publication 198. An HMAC is a cryptographic hash that uses a key to sign a message. The receiver verifies the hash by recomputing it using the same key.
#### `crypto.hmac.create(hash, secret, callback)` #### `crypto.hmac.create(hash, secret)`
- `hash: String` - `hash: String`
- `secret: Buffer` - `secret: Buffer`
- `callback: Function`
##### `digest(data, callback)` Returns `Promise<{digest<Function>}>`
##### `digest(data)`
- `data: Buffer` - `data: Buffer`
- `callback: Function`
Returns `Promise<Buffer>`
Example: Example:
```js ```js
var crypto = require('libp2p-crypto') const crypto = require('libp2p-crypto')
let hash = 'SHA1' // 'SHA256' || 'SHA512' async function main () {
const hash = 'SHA1' // 'SHA256' || 'SHA512'
crypto.hmac.create(hash, Buffer.from('secret'), (err, hmac) => { const hmac = await crypto.hmac.create(hash, Buffer.from('secret'))
if (!err) { const sig = await hmac.digest(Buffer.from('hello world'))
hmac.digest(Buffer.from('hello world'), (err, sig) => {
if (!err) {
console.log(sig) console.log(sig)
} }
})
} main()
})
``` ```
### `crypto.keys` ### `crypto.keys`
**Supported Key Types** **Supported Key Types**
The [`generateKeyPair`](#cryptokeysgeneratekeypairtype-bits-callback), [`marshalPublicKey`](#cryptokeysmarshalpublickeykey-type-callback), and [`marshalPrivateKey`](#cryptokeysmarshalprivatekeykey-type) functions accept a string `type` argument. The [`generateKeyPair`](#generatekeypairtype-bits), [`marshalPublicKey`](#marshalpublickeykey-type), and [`marshalPrivateKey`](#marshalprivatekeykey-type) functions accept a string `type` argument.
Currently the `'RSA'` and `'ed25519'` types are supported, although ed25519 keys support only signing and verification of messages. For encryption / decryption support, RSA keys should be used. Currently the `'RSA'` and `'ed25519'` types are supported, although ed25519 keys support only signing and verification of messages. For encryption / decryption support, RSA keys should be used.
Installing the [libp2p-crypto-secp256k1](https://github.com/libp2p/js-libp2p-crypto-secp256k1) module adds support for the `'secp256k1'` type, which supports ECDSA signatures using the secp256k1 elliptic curve popularized by Bitcoin. This module is not installed by default, and should be explicitly depended on if your project requires secp256k1 support. Installing the [libp2p-crypto-secp256k1](https://github.com/libp2p/js-libp2p-crypto-secp256k1) module adds support for the `'secp256k1'` type, which supports ECDSA signatures using the secp256k1 elliptic curve popularized by Bitcoin. This module is not installed by default, and should be explicitly depended on if your project requires secp256k1 support.
### `crypto.keys.generateKeyPair(type, bits, callback)` ### `crypto.keys.generateKeyPair(type, bits)`
- `type: String`, see [Supported Key Types](#supported-key-types) above. - `type: String`, see [Supported Key Types](#supported-key-types) above.
- `bits: Number` Minimum of 1024 - `bits: Number` Minimum of 1024
- `callback: Function`
Returns `Promise<{privateKey<Buffer>, publicKey<Buffer>}>`
Generates a keypair of the given type and bitsize. Generates a keypair of the given type and bitsize.
### `crypto.keys.generateEphemeralKeyPair(curve, callback)` ### `crypto.keys.generateEphemeralKeyPair(curve)`
- `curve: String`, one of `'P-256'`, `'P-384'`, `'P-521'` is currently supported - `curve: String`, one of `'P-256'`, `'P-384'`, `'P-521'` is currently supported
- `callback: Function`
Returns `Promise`
Generates an ephemeral public key and returns a function that will compute the shared secret key. Generates an ephemeral public key and returns a function that will compute the shared secret key.
Focuses only on ECDH now, but can be made more general in the future. Focuses only on ECDH now, but can be made more general in the future.
Calls back with an object of the form Resolves to an object of the form:
```js ```js
{ {
@ -188,16 +182,17 @@ Calls back with an object of the form
} }
``` ```
### `crypto.keys.keyStretcher(cipherType, hashType, secret, callback)` ### `crypto.keys.keyStretcher(cipherType, hashType, secret)`
- `cipherType: String`, one of `'AES-128'`, `'AES-256'`, `'Blowfish'` - `cipherType: String`, one of `'AES-128'`, `'AES-256'`, `'Blowfish'`
- `hashType: String`, one of `'SHA1'`, `SHA256`, `SHA512` - `hashType: String`, one of `'SHA1'`, `SHA256`, `SHA512`
- `secret: Buffer` - `secret: Buffer`
- `callback: Function`
Returns `Promise`
Generates a set of keys for each party by stretching the shared key. Generates a set of keys for each party by stretching the shared key.
Calls back with an object of the form: Resolves to an object of the form:
```js ```js
{ {
@ -214,10 +209,12 @@ Calls back with an object of the form:
} }
``` ```
### `crypto.keys.marshalPublicKey(key[, type], callback)` ### `crypto.keys.marshalPublicKey(key, [type])`
- `key: keys.rsa.RsaPublicKey | keys.ed25519.Ed25519PublicKey | require('libp2p-crypto-secp256k1').Secp256k1PublicKey` - `key: keys.rsa.RsaPublicKey | keys.ed25519.Ed25519PublicKey | require('libp2p-crypto-secp256k1').Secp256k1PublicKey`
- `type: String`, see [Supported Key Types](#supported-key-types) above. - `type: String`, see [Supported Key Types](#supported-key-types) above. Defaults to 'rsa'.
Returns `Buffer`
Converts a public key object into a protobuf serialized public key. Converts a public key object into a protobuf serialized public key.
@ -225,27 +222,33 @@ Converts a public key object into a protobuf serialized public key.
- `buf: Buffer` - `buf: Buffer`
Returns `RsaPublicKey|Ed25519PublicKey|Secp256k1PublicKey`
Converts a protobuf serialized public key into its representative object. Converts a protobuf serialized public key into its representative object.
### `crypto.keys.marshalPrivateKey(key[, type])` ### `crypto.keys.marshalPrivateKey(key, [type])`
- `key: keys.rsa.RsaPrivateKey | keys.ed25519.Ed25519PrivateKey | require('libp2p-crypto-secp256k1').Secp256k1PrivateKey` - `key: keys.rsa.RsaPrivateKey | keys.ed25519.Ed25519PrivateKey | require('libp2p-crypto-secp256k1').Secp256k1PrivateKey`
- `type: String`, see [Supported Key Types](#supported-key-types) above. - `type: String`, see [Supported Key Types](#supported-key-types) above.
Returns `Buffer`
Converts a private key object into a protobuf serialized private key. Converts a private key object into a protobuf serialized private key.
### `crypto.keys.unmarshalPrivateKey(buf, callback)` ### `crypto.keys.unmarshalPrivateKey(buf)`
- `buf: Buffer` - `buf: Buffer`
- `callback: Function`
Returns `Promise<RsaPrivateKey|Ed25519PrivateKey|Secp256k1PrivateKey>`
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)` ### `crypto.keys.import(pem, password)`
- `pem: string` - `pem: string`
- `password: string` - `password: string`
- `callback: Function`
Returns `Promise<RsaPrivateKey>`
Converts a PEM password protected private key into its representative object. Converts a PEM password protected private key into its representative object.
@ -253,6 +256,8 @@ Converts a PEM password protected private key into its representative object.
- `number: Number` - `number: Number`
Returns `Buffer`
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)` ### `crypto.pbkdf2(password, salt, iterations, keySize, hash)`

View File

@ -10,16 +10,11 @@ const secrets = []
const curves = ['P-256', 'P-384', 'P-521'] const curves = ['P-256', 'P-384', 'P-521']
curves.forEach((curve) => { curves.forEach((curve) => {
suite.add(`ephemeral key with secrect ${curve}`, (d) => { suite.add(`ephemeral key with secrect ${curve}`, async (d) => {
crypto.keys.generateEphemeralKeyPair('P-256', (err, res) => { const res = await crypto.keys.generateEphemeralKeyPair('P-256')
if (err) { throw err } const secret = await res.genSharedKey(res.key)
res.genSharedKey(res.key, (err, secret) => {
if (err) { throw err }
secrets.push(secret) secrets.push(secret)
d.resolve() d.resolve()
})
})
}, { defer: true }) }, { defer: true })
}) })

View File

@ -2,7 +2,6 @@
'use strict' 'use strict'
const Benchmark = require('benchmark') const Benchmark = require('benchmark')
const async = require('async')
const crypto = require('../src') const crypto = require('../src')
@ -13,11 +12,9 @@ const keys = []
const ciphers = ['AES-128', 'AES-256', 'Blowfish'] const ciphers = ['AES-128', 'AES-256', 'Blowfish']
const hashes = ['SHA1', 'SHA256', 'SHA512'] const hashes = ['SHA1', 'SHA256', 'SHA512']
async.waterfall([ ;(async () => {
(cb) => crypto.keys.generateEphemeralKeyPair('P-256', cb), const res = await crypto.keys.generateEphemeralKeyPair('P-256')
(res, cb) => res.genSharedKey(res.key, cb) const secret = await res.genSharedKey(res.key)
], (err, secret) => {
if (err) { throw err }
ciphers.forEach((cipher) => hashes.forEach((hash) => { ciphers.forEach((cipher) => hashes.forEach((hash) => {
setup(cipher, hash, secret) setup(cipher, hash, secret)
@ -26,15 +23,12 @@ async.waterfall([
suite suite
.on('cycle', (event) => console.log(String(event.target))) .on('cycle', (event) => console.log(String(event.target)))
.run({ async: true }) .run({ async: true })
}) })()
function setup (cipher, hash, secret) { function setup (cipher, hash, secret) {
suite.add(`keyStretcher ${cipher} ${hash}`, (d) => { suite.add(`keyStretcher ${cipher} ${hash}`, async (d) => {
crypto.keys.keyStretcher(cipher, hash, secret, (err, k) => { const k = await crypto.keys.keyStretcher(cipher, hash, secret)
if (err) { throw err }
keys.push(k) keys.push(k)
d.resolve() d.resolve()
})
}, { defer: true }) }, { defer: true })
} }

View File

@ -10,30 +10,24 @@ const keys = []
const bits = [1024, 2048, 4096] const bits = [1024, 2048, 4096]
bits.forEach((bit) => { bits.forEach((bit) => {
suite.add(`generateKeyPair ${bit}bits`, (d) => { suite.add(`generateKeyPair ${bit}bits`, async (d) => {
crypto.keys.generateKeyPair('RSA', bit, (err, key) => { const key = await crypto.keys.generateKeyPair('RSA', bit)
if (err) { throw err }
keys.push(key) keys.push(key)
d.resolve() d.resolve()
})
}, { }, {
defer: true defer: true
}) })
}) })
suite.add('sign and verify', (d) => { suite.add('sign and verify', async (d) => {
const key = keys[0] const key = keys[0]
const text = key.genSecret() const text = key.genSecret()
key.sign(text, (err, sig) => { const sig = await key.sign(text)
if (err) { throw err } const res = await key.public.verify(text, sig)
key.public.verify(text, sig, (err, res) => {
if (err) { throw err }
if (res !== true) { throw new Error('failed to verify') } if (res !== true) { throw new Error('failed to verify') }
d.resolve() d.resolve()
})
})
}, { }, {
defer: true defer: true
}) })

View File

@ -37,15 +37,14 @@
"dependencies": { "dependencies": {
"asmcrypto.js": "^2.3.2", "asmcrypto.js": "^2.3.2",
"asn1.js": "^5.0.1", "asn1.js": "^5.0.1",
"async": "^2.6.2", "bn.js": "^5.0.0",
"bn.js": "^4.11.8",
"browserify-aes": "^1.2.0", "browserify-aes": "^1.2.0",
"bs58": "^4.0.1", "bs58": "^4.0.1",
"iso-random-stream": "^1.1.0", "iso-random-stream": "^1.1.0",
"keypair": "^1.0.1", "keypair": "^1.0.1",
"libp2p-crypto-secp256k1": "~0.3.0", "libp2p-crypto-secp256k1": "~0.4.0",
"multihashing-async": "~0.6.0", "multihashing-async": "~0.7.0",
"node-forge": "~0.7.6", "node-forge": "~0.8.5",
"pem-jwk": "^2.0.0", "pem-jwk": "^2.0.0",
"protons": "^1.0.1", "protons": "^1.0.1",
"rsa-pem-to-jwk": "^1.1.3", "rsa-pem-to-jwk": "^1.1.3",
@ -53,9 +52,9 @@
"ursa-optional": "~0.9.10" "ursa-optional": "~0.9.10"
}, },
"devDependencies": { "devDependencies": {
"aegir": "^18.2.2", "aegir": "^19.0.5",
"benchmark": "^2.1.4", "benchmark": "^2.1.4",
"bundlesize": "~0.17.1", "bundlesize": "~0.18.0",
"chai": "^4.2.0", "chai": "^4.2.0",
"chai-string": "^1.5.0", "chai-string": "^1.5.0",
"dirty-chai": "^2.0.1" "dirty-chai": "^2.0.1"

View File

@ -1,13 +1,10 @@
'use strict' 'use strict'
const asm = require('asmcrypto.js') const asm = require('asmcrypto.js')
const nextTick = require('async/nextTick')
exports.create = function (key, iv, callback) {
const done = (err, res) => nextTick(() => callback(err, res))
exports.create = async function (key, iv) { // eslint-disable-line require-await
if (key.length !== 16 && key.length !== 32) { if (key.length !== 16 && key.length !== 32) {
return done(new Error('Invalid key length')) throw new Error('Invalid key length')
} }
const enc = new asm.AES_CTR.Encrypt({ const enc = new asm.AES_CTR.Encrypt({
@ -20,36 +17,18 @@ exports.create = function (key, iv, callback) {
}) })
const res = { const res = {
encrypt (data, cb) { async encrypt (data) { // eslint-disable-line require-await
const done = (err, res) => nextTick(() => cb(err, res)) return Buffer.from(
let res
try {
res = Buffer.from(
enc.process(data).result enc.process(data).result
) )
} catch (err) {
return done(err)
}
done(null, res)
}, },
decrypt (data, cb) { async decrypt (data) { // eslint-disable-line require-await
const done = (err, res) => nextTick(() => cb(err, res)) return Buffer.from(
let res
try {
res = Buffer.from(
dec.process(data).result dec.process(data).result
) )
} catch (err) {
return done(err)
}
done(null, res)
} }
} }
done(null, res) return res
} }

View File

@ -7,24 +7,24 @@ const CIPHER_MODES = {
32: 'aes-256-ctr' 32: 'aes-256-ctr'
} }
exports.create = function (key, iv, callback) { exports.create = async function (key, iv) { // eslint-disable-line require-await
const mode = CIPHER_MODES[key.length] const mode = CIPHER_MODES[key.length]
if (!mode) { if (!mode) {
return callback(new Error('Invalid key length')) throw new Error('Invalid key length')
} }
const cipher = ciphers.createCipheriv(mode, key, iv) const cipher = ciphers.createCipheriv(mode, key, iv)
const decipher = ciphers.createDecipheriv(mode, key, iv) const decipher = ciphers.createDecipheriv(mode, key, iv)
const res = { const res = {
encrypt (data, cb) { async encrypt (data) { // eslint-disable-line require-await
cb(null, cipher.update(data)) return cipher.update(data)
}, },
decrypt (data, cb) { async decrypt (data) { // eslint-disable-line require-await
cb(null, decipher.update(data)) return decipher.update(data)
} }
} }
callback(null, res) return res
} }

View File

@ -1,8 +1,6 @@
'use strict' 'use strict'
const nodeify = require('../nodeify') const webcrypto = require('../webcrypto.js')
const crypto = require('../webcrypto')
const lengths = require('./lengths') const lengths = require('./lengths')
const hashTypes = { const hashTypes = {
@ -11,15 +9,14 @@ const hashTypes = {
SHA512: 'SHA-512' SHA512: 'SHA-512'
} }
const sign = (key, data, cb) => { const sign = async (key, data) => {
nodeify(crypto.subtle.sign({ name: 'HMAC' }, key, data) return Buffer.from(await webcrypto.subtle.sign({ name: 'HMAC' }, key, data))
.then((raw) => Buffer.from(raw)), cb)
} }
exports.create = function (hashType, secret, callback) { exports.create = async function (hashType, secret) {
const hash = hashTypes[hashType] const hash = hashTypes[hashType]
nodeify(crypto.subtle.importKey( const key = await webcrypto.subtle.importKey(
'raw', 'raw',
secret, secret,
{ {
@ -28,12 +25,12 @@ exports.create = function (hashType, secret, callback) {
}, },
false, false,
['sign'] ['sign']
).then((key) => { )
return { return {
digest (data, cb) { async digest (data) { // eslint-disable-line require-await
sign(key, data, cb) return sign(key, data)
}, },
length: lengths[hashType] length: lengths[hashType]
} }
}), callback)
} }

View File

@ -2,21 +2,16 @@
const crypto = require('crypto') const crypto = require('crypto')
const lengths = require('./lengths') const lengths = require('./lengths')
const nextTick = require('async/nextTick')
exports.create = function (hash, secret, callback) { exports.create = async function (hash, secret) { // eslint-disable-line require-await
const res = { const res = {
digest (data, cb) { async digest (data) { // eslint-disable-line require-await
const hmac = crypto.createHmac(hash.toLowerCase(), secret) const hmac = crypto.createHmac(hash.toLowerCase(), secret)
hmac.update(data) hmac.update(data)
return hmac.digest()
nextTick(() => {
cb(null, hmac.digest())
})
}, },
length: lengths[hash] length: lengths[hash]
} }
callback(null, res) return res
} }

View File

@ -4,8 +4,6 @@ const hmac = require('./hmac')
const aes = require('./aes') const aes = require('./aes')
const keys = require('./keys') const keys = require('./keys')
exports = module.exports
exports.aes = aes exports.aes = aes
exports.hmac = hmac exports.hmac = hmac
exports.keys = keys exports.keys = keys

View File

@ -1,12 +1,8 @@
'use strict' 'use strict'
const webcrypto = require('../webcrypto') const webcrypto = require('../webcrypto.js')
const nodeify = require('../nodeify')
const BN = require('asn1.js').bignum const BN = require('asn1.js').bignum
const { toBase64, toBn } = require('../util')
const util = require('../util')
const toBase64 = util.toBase64
const toBn = util.toBn
const bits = { const bits = {
'P-256': 256, 'P-256': 256,
@ -14,26 +10,22 @@ const bits = {
'P-521': 521 'P-521': 521
} }
exports.generateEphmeralKeyPair = function (curve, callback) { exports.generateEphmeralKeyPair = async function (curve) {
nodeify(webcrypto.subtle.generateKey( const pair = await webcrypto.subtle.generateKey(
{ {
name: 'ECDH', name: 'ECDH',
namedCurve: curve namedCurve: curve
}, },
true, true,
['deriveBits'] ['deriveBits']
).then((pair) => { )
// forcePrivate is used for testing only
const genSharedKey = (theirPub, forcePrivate, cb) => {
if (typeof forcePrivate === 'function') {
cb = forcePrivate
forcePrivate = undefined
}
// forcePrivate is used for testing only
const genSharedKey = async (theirPub, forcePrivate) => {
let privateKey let privateKey
if (forcePrivate) { if (forcePrivate) {
privateKey = webcrypto.subtle.importKey( privateKey = await webcrypto.subtle.importKey(
'jwk', 'jwk',
unmarshalPrivateKey(curve, forcePrivate), unmarshalPrivateKey(curve, forcePrivate),
{ {
@ -44,11 +36,11 @@ exports.generateEphmeralKeyPair = function (curve, callback) {
['deriveBits'] ['deriveBits']
) )
} else { } else {
privateKey = Promise.resolve(pair.privateKey) privateKey = pair.privateKey
} }
const keys = Promise.all([ const keys = [
webcrypto.subtle.importKey( await webcrypto.subtle.importKey(
'jwk', 'jwk',
unmarshalPublicKey(curve, theirPub), unmarshalPublicKey(curve, theirPub),
{ {
@ -59,9 +51,9 @@ exports.generateEphmeralKeyPair = function (curve, callback) {
[] []
), ),
privateKey privateKey
]) ]
nodeify(keys.then((keys) => webcrypto.subtle.deriveBits( return Buffer.from(await webcrypto.subtle.deriveBits(
{ {
name: 'ECDH', name: 'ECDH',
namedCurve: curve, namedCurve: curve,
@ -69,17 +61,15 @@ exports.generateEphmeralKeyPair = function (curve, callback) {
}, },
keys[1], keys[1],
bits[curve] bits[curve]
)).then((bits) => Buffer.from(bits)), cb) ))
} }
return webcrypto.subtle.exportKey('jwk', pair.publicKey) const publicKey = await webcrypto.subtle.exportKey('jwk', pair.publicKey)
.then((publicKey) => {
return { return {
key: marshalPublicKey(publicKey), key: marshalPublicKey(publicKey),
genSharedKey genSharedKey
} }
})
}), callback)
} }
const curveLengths = { const curveLengths = {

View File

@ -1,7 +1,6 @@
'use strict' 'use strict'
const crypto = require('crypto') const crypto = require('crypto')
const nextTick = require('async/nextTick')
const curves = { const curves = {
'P-256': 'prime256v1', 'P-256': 'prime256v1',
@ -9,33 +8,21 @@ const curves = {
'P-521': 'secp521r1' 'P-521': 'secp521r1'
} }
exports.generateEphmeralKeyPair = function (curve, callback) { exports.generateEphmeralKeyPair = async function (curve) { // eslint-disable-line require-await
if (!curves[curve]) { if (!curves[curve]) {
return callback(new Error(`Unkown curve: ${curve}`)) throw new Error(`Unkown curve: ${curve}`)
} }
const ecdh = crypto.createECDH(curves[curve]) const ecdh = crypto.createECDH(curves[curve])
ecdh.generateKeys() ecdh.generateKeys()
nextTick(() => callback(null, { return {
key: ecdh.getPublicKey(), key: ecdh.getPublicKey(),
genSharedKey (theirPub, forcePrivate, cb) { async genSharedKey (theirPub, forcePrivate) { // eslint-disable-line require-await
if (typeof forcePrivate === 'function') {
cb = forcePrivate
forcePrivate = null
}
if (forcePrivate) { if (forcePrivate) {
ecdh.setPrivateKey(forcePrivate.private) ecdh.setPrivateKey(forcePrivate.private)
} }
let secret return ecdh.computeSecret(theirPub)
try {
secret = ecdh.computeSecret(theirPub)
} catch (err) {
return cb(err)
} }
nextTick(() => cb(null, secret))
} }
}))
} }

View File

@ -12,9 +12,8 @@ class Ed25519PublicKey {
this._key = ensureKey(key, crypto.publicKeyLength) this._key = ensureKey(key, crypto.publicKeyLength)
} }
verify (data, sig, callback) { async verify (data, sig) { // eslint-disable-line require-await
ensure(callback) return crypto.hashAndVerify(this._key, sig, data)
crypto.hashAndVerify(this._key, sig, data, callback)
} }
marshal () { marshal () {
@ -32,9 +31,8 @@ class Ed25519PublicKey {
return this.bytes.equals(key.bytes) return this.bytes.equals(key.bytes)
} }
hash (callback) { async hash () { // eslint-disable-line require-await
ensure(callback) return multihashing(this.bytes, 'sha2-256')
multihashing(this.bytes, 'sha2-256', callback)
} }
} }
@ -46,9 +44,8 @@ class Ed25519PrivateKey {
this._publicKey = ensureKey(publicKey, crypto.publicKeyLength) this._publicKey = ensureKey(publicKey, crypto.publicKeyLength)
} }
sign (message, callback) { async sign (message) { // eslint-disable-line require-await
ensure(callback) return crypto.hashAndSign(this._key, message)
crypto.hashAndSign(this._key, message, callback)
} }
get public () { get public () {
@ -74,9 +71,8 @@ class Ed25519PrivateKey {
return this.bytes.equals(key.bytes) return this.bytes.equals(key.bytes)
} }
hash (callback) { async hash () { // eslint-disable-line require-await
ensure(callback) return multihashing(this.bytes, 'sha2-256')
multihashing(this.bytes, 'sha2-256', callback)
} }
/** /**
@ -86,28 +82,19 @@ class Ed25519PrivateKey {
* The public key is a protobuf encoding containing a type and the DER encoding * The public key is a protobuf encoding containing a type and the DER encoding
* of the PKCS SubjectPublicKeyInfo. * of the PKCS SubjectPublicKeyInfo.
* *
* @param {function(Error, id)} callback * @returns {Promise<String>}
* @returns {undefined}
*/ */
id (callback) { async id () {
this.public.hash((err, hash) => { const hash = await this.public.hash()
if (err) { return bs58.encode(hash)
return callback(err)
}
callback(null, bs58.encode(hash))
})
} }
} }
function unmarshalEd25519PrivateKey (bytes, callback) { function unmarshalEd25519PrivateKey (bytes) {
try {
bytes = ensureKey(bytes, crypto.privateKeyLength + crypto.publicKeyLength) bytes = ensureKey(bytes, crypto.privateKeyLength + crypto.publicKeyLength)
} catch (err) {
return callback(err)
}
const privateKeyBytes = bytes.slice(0, crypto.privateKeyLength) const privateKeyBytes = bytes.slice(0, crypto.privateKeyLength)
const publicKeyBytes = bytes.slice(crypto.privateKeyLength, bytes.length) const publicKeyBytes = bytes.slice(crypto.privateKeyLength, bytes.length)
callback(null, new Ed25519PrivateKey(privateKeyBytes, publicKeyBytes)) return new Ed25519PrivateKey(privateKeyBytes, publicKeyBytes)
} }
function unmarshalEd25519PublicKey (bytes) { function unmarshalEd25519PublicKey (bytes) {
@ -115,52 +102,14 @@ function unmarshalEd25519PublicKey (bytes) {
return new Ed25519PublicKey(bytes) return new Ed25519PublicKey(bytes)
} }
function generateKeyPair (_bits, cb) { async function generateKeyPair () {
if (cb === undefined && typeof _bits === 'function') { const { secretKey, publicKey } = await crypto.generateKey()
cb = _bits return new Ed25519PrivateKey(secretKey, publicKey)
}
crypto.generateKey((err, keys) => {
if (err) {
return cb(err)
}
let privkey
try {
privkey = new Ed25519PrivateKey(keys.secretKey, keys.publicKey)
} catch (err) {
cb(err)
return
}
cb(null, privkey)
})
} }
function generateKeyPairFromSeed (seed, _bits, cb) { async function generateKeyPairFromSeed (seed) {
if (cb === undefined && typeof _bits === 'function') { const { secretKey, publicKey } = await crypto.generateKeyFromSeed(seed)
cb = _bits return new Ed25519PrivateKey(secretKey, publicKey)
}
crypto.generateKeyFromSeed(seed, (err, keys) => {
if (err) {
return cb(err)
}
let privkey
try {
privkey = new Ed25519PrivateKey(keys.secretKey, keys.publicKey)
} catch (err) {
cb(err)
return
}
cb(null, privkey)
})
}
function ensure (cb) {
if (typeof cb !== 'function') {
throw new Error('callback is required')
}
} }
function ensureKey (key, length) { function ensureKey (key, length) {

View File

@ -1,51 +1,23 @@
'use strict' 'use strict'
const nacl = require('tweetnacl') const nacl = require('tweetnacl')
const nextTick = require('async/nextTick')
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 = async function () { // eslint-disable-line require-await
nextTick(() => { return nacl.sign.keyPair()
let result
try {
result = nacl.sign.keyPair()
} catch (err) {
return callback(err)
}
callback(null, result)
})
} }
// seed should be a 32 byte uint8array // seed should be a 32 byte uint8array
exports.generateKeyFromSeed = function (seed, callback) { exports.generateKeyFromSeed = async function (seed) { // eslint-disable-line require-await
nextTick(() => { return nacl.sign.keyPair.fromSeed(seed)
let result
try {
result = nacl.sign.keyPair.fromSeed(seed)
} catch (err) {
return callback(err)
}
callback(null, result)
})
} }
exports.hashAndSign = function (key, msg, callback) { exports.hashAndSign = async function (key, msg) { // eslint-disable-line require-await
nextTick(() => { return Buffer.from(nacl.sign.detached(msg, key))
callback(null, Buffer.from(nacl.sign.detached(msg, key)))
})
} }
exports.hashAndVerify = function (key, sig, msg, callback) { exports.hashAndVerify = async function (key, sig, msg) { // eslint-disable-line require-await
nextTick(() => { return 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)
})
} }

View File

@ -6,6 +6,4 @@ const ecdh = require('./ecdh')
// the shared secret key. // the shared secret key.
// //
// Focuses only on ECDH now, but can be made more general in the future. // Focuses only on ECDH now, but can be made more general in the future.
module.exports = (curve, callback) => { module.exports = async (curve) => ecdh.generateEphmeralKeyPair(curve) // eslint-disable-line require-await
ecdh.generateEphmeralKeyPair(curve, callback)
}

View File

@ -27,27 +27,27 @@ exports.keyStretcher = require('./key-stretcher')
exports.generateEphemeralKeyPair = require('./ephemeral-keys') exports.generateEphemeralKeyPair = require('./ephemeral-keys')
// Generates a keypair of the given type and bitsize // Generates a keypair of the given type and bitsize
exports.generateKeyPair = (type, bits, cb) => { exports.generateKeyPair = async (type, bits) => { // eslint-disable-line require-await
let key = supportedKeys[type.toLowerCase()] let key = supportedKeys[type.toLowerCase()]
if (!key) { if (!key) {
return cb(new Error('invalid or unsupported key type')) throw new Error('invalid or unsupported key type')
} }
key.generateKeyPair(bits, cb) return key.generateKeyPair(bits)
} }
// Generates a keypair of the given type and bitsize // Generates a keypair of the given type and bitsize
// seed is a 32 byte uint8array // seed is a 32 byte uint8array
exports.generateKeyPairFromSeed = (type, seed, bits, cb) => { exports.generateKeyPairFromSeed = async (type, seed, bits) => { // eslint-disable-line require-await
let key = supportedKeys[type.toLowerCase()] let key = supportedKeys[type.toLowerCase()]
if (!key) { if (!key) {
return cb(new Error('invalid or unsupported key type')) throw new Error('invalid or unsupported key type')
} }
if (type.toLowerCase() !== 'ed25519') { if (type.toLowerCase() !== 'ed25519') {
return cb(new Error('Seed key derivation is unimplemented for RSA or secp256k1')) throw new Error('Seed key derivation is unimplemented for RSA or secp256k1')
} }
key.generateKeyPairFromSeed(seed, bits, cb) return key.generateKeyPairFromSeed(seed, bits)
} }
// Converts a protobuf serialized public key into its // Converts a protobuf serialized public key into its
@ -84,29 +84,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 = async (buf) => { // eslint-disable-line require-await
let decoded const decoded = keysPBM.PrivateKey.decode(buf)
try {
decoded = keysPBM.PrivateKey.decode(buf)
} catch (err) {
return callback(err)
}
const data = decoded.Data const data = decoded.Data
switch (decoded.Type) { switch (decoded.Type) {
case keysPBM.KeyType.RSA: case keysPBM.KeyType.RSA:
return supportedKeys.rsa.unmarshalRsaPrivateKey(data, callback) return supportedKeys.rsa.unmarshalRsaPrivateKey(data)
case keysPBM.KeyType.Ed25519: case keysPBM.KeyType.Ed25519:
return supportedKeys.ed25519.unmarshalEd25519PrivateKey(data, callback) return supportedKeys.ed25519.unmarshalEd25519PrivateKey(data)
case keysPBM.KeyType.Secp256k1: case keysPBM.KeyType.Secp256k1:
if (supportedKeys.secp256k1) { if (supportedKeys.secp256k1) {
return supportedKeys.secp256k1.unmarshalSecp256k1PrivateKey(data, callback) return supportedKeys.secp256k1.unmarshalSecp256k1PrivateKey(data)
} else { } else {
return callback(new Error('secp256k1 support requires libp2p-crypto-secp256k1 package')) throw new Error('secp256k1 support requires libp2p-crypto-secp256k1 package')
} }
default: default:
callback(new Error('invalid or unsupported key type')) throw new Error('invalid or unsupported key type')
} }
} }
@ -120,16 +114,12 @@ exports.marshalPrivateKey = (key, type) => {
return key.bytes return key.bytes
} }
exports.import = (pem, password, callback) => { exports.import = async (pem, password) => { // eslint-disable-line require-await
try {
const key = forge.pki.decryptRsaPrivateKey(pem, password) const key = forge.pki.decryptRsaPrivateKey(pem, password)
if (key === null) { if (key === null) {
throw new Error('Cannot read the key, most likely the password is wrong or not a RSA key') 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)) let der = forge.asn1.toDer(forge.pki.privateKeyToAsn1(key))
der = Buffer.from(der.getBytes(), 'binary') der = Buffer.from(der.getBytes(), 'binary')
return supportedKeys.rsa.unmarshalRsaPrivateKey(der, callback) return supportedKeys.rsa.unmarshalRsaPrivateKey(der)
} catch (err) {
callback(err)
}
} }

View File

@ -1,6 +1,5 @@
'use strict' 'use strict'
const whilst = require('async/whilst')
const hmac = require('../hmac') const hmac = require('../hmac')
const cipherMap = { const cipherMap = {
@ -20,15 +19,15 @@ const cipherMap = {
// Generates a set of keys for each party by stretching the shared key. // Generates a set of keys for each party by stretching the shared key.
// (myIV, theirIV, myCipherKey, theirCipherKey, myMACKey, theirMACKey) // (myIV, theirIV, myCipherKey, theirCipherKey, myMACKey, theirMACKey)
module.exports = (cipherType, hash, secret, callback) => { module.exports = async (cipherType, hash, secret) => {
const cipher = cipherMap[cipherType] const cipher = cipherMap[cipherType]
if (!cipher) { if (!cipher) {
return callback(new Error('unkown cipherType passed')) throw new Error('unkown cipherType passed')
} }
if (!hash) { if (!hash) {
return callback(new Error('unkown hashType passed')) throw new Error('unkown hashType passed')
} }
const cipherKeySize = cipher.keySize const cipherKeySize = cipher.keySize
@ -37,31 +36,14 @@ module.exports = (cipherType, hash, secret, callback) => {
const seed = Buffer.from('key expansion') const seed = Buffer.from('key expansion')
const resultLength = 2 * (ivSize + cipherKeySize + hmacKeySize) const resultLength = 2 * (ivSize + cipherKeySize + hmacKeySize)
hmac.create(hash, secret, (err, m) => { const m = await hmac.create(hash, secret)
if (err) { let a = await m.digest(seed)
return callback(err)
}
m.digest(seed, (err, a) => {
if (err) {
return callback(err)
}
let result = [] let result = []
let j = 0 let j = 0
whilst( while (j < resultLength) {
() => j < resultLength, const b = await m.digest(Buffer.concat([a, seed]))
stretch,
finish
)
function stretch (cb) {
m.digest(Buffer.concat([a, seed]), (err, b) => {
if (err) {
return cb(err)
}
let todo = b.length let todo = b.length
if (j + todo > resultLength) { if (j + todo > resultLength) {
@ -69,22 +51,8 @@ module.exports = (cipherType, hash, secret, callback) => {
} }
result.push(b) result.push(b)
j += todo j += todo
a = await m.digest(a)
m.digest(a, (err, _a) => {
if (err) {
return cb(err)
}
a = _a
cb()
})
})
}
function finish (err) {
if (err) {
return callback(err)
} }
const half = resultLength / 2 const half = resultLength / 2
@ -98,11 +66,8 @@ module.exports = (cipherType, hash, secret, callback) => {
macKey: res.slice(ivSize + cipherKeySize) macKey: res.slice(ivSize + cipherKeySize)
}) })
callback(null, { return {
k1: createKey(r1), k1: createKey(r1),
k2: createKey(r2) k2: createKey(r2)
})
} }
})
})
} }

View File

@ -1,13 +1,12 @@
'use strict' 'use strict'
const nodeify = require('../nodeify') const webcrypto = require('../webcrypto.js')
const webcrypto = require('../webcrypto')
const randomBytes = require('../random-bytes') const randomBytes = require('../random-bytes')
exports.utils = require('./rsa-utils') exports.utils = require('./rsa-utils')
exports.generateKey = function (bits, callback) { exports.generateKey = async function (bits) {
nodeify(webcrypto.subtle.generateKey( const pair = await webcrypto.subtle.generateKey(
{ {
name: 'RSASSA-PKCS1-v1_5', name: 'RSASSA-PKCS1-v1_5',
modulusLength: bits, modulusLength: bits,
@ -17,16 +16,18 @@ exports.generateKey = function (bits, callback) {
true, true,
['sign', 'verify'] ['sign', 'verify']
) )
.then(exportKey)
.then((keys) => ({ const keys = await exportKey(pair)
return {
privateKey: keys[0], privateKey: keys[0],
publicKey: keys[1] publicKey: keys[1]
})), callback) }
} }
// Takes a jwk key // Takes a jwk key
exports.unmarshalPrivateKey = function (key, callback) { exports.unmarshalPrivateKey = async function (key) {
const privateKey = webcrypto.subtle.importKey( const privateKey = await webcrypto.subtle.importKey(
'jwk', 'jwk',
key, key,
{ {
@ -37,22 +38,26 @@ exports.unmarshalPrivateKey = function (key, callback) {
['sign'] ['sign']
) )
nodeify(Promise.all([ const pair = [
privateKey, privateKey,
derivePublicFromPrivate(key) await derivePublicFromPrivate(key)
]).then((keys) => exportKey({ ]
const keys = await exportKey({
privateKey: pair[0],
publicKey: pair[1]
})
return {
privateKey: keys[0], privateKey: keys[0],
publicKey: keys[1] publicKey: keys[1]
})).then((keys) => ({ }
privateKey: keys[0],
publicKey: keys[1]
})), callback)
} }
exports.getRandomValues = randomBytes exports.getRandomValues = randomBytes
exports.hashAndSign = function (key, msg, callback) { exports.hashAndSign = async function (key, msg) {
nodeify(webcrypto.subtle.importKey( const privateKey = await webcrypto.subtle.importKey(
'jwk', 'jwk',
key, key,
{ {
@ -61,17 +66,19 @@ exports.hashAndSign = function (key, msg, callback) {
}, },
false, false,
['sign'] ['sign']
).then((privateKey) => { )
return webcrypto.subtle.sign(
const sig = await webcrypto.subtle.sign(
{ name: 'RSASSA-PKCS1-v1_5' }, { name: 'RSASSA-PKCS1-v1_5' },
privateKey, privateKey,
Uint8Array.from(msg) Uint8Array.from(msg)
) )
}).then((sig) => Buffer.from(sig)), callback)
return Buffer.from(sig)
} }
exports.hashAndVerify = function (key, sig, msg, callback) { exports.hashAndVerify = async function (key, sig, msg) {
nodeify(webcrypto.subtle.importKey( const publicKey = await webcrypto.subtle.importKey(
'jwk', 'jwk',
key, key,
{ {
@ -80,14 +87,14 @@ exports.hashAndVerify = function (key, sig, msg, callback) {
}, },
false, false,
['verify'] ['verify']
).then((publicKey) => { )
return webcrypto.subtle.verify( return webcrypto.subtle.verify(
{ name: 'RSASSA-PKCS1-v1_5' }, { name: 'RSASSA-PKCS1-v1_5' },
publicKey, publicKey,
sig, sig,
msg msg
) )
}), callback)
} }
function exportKey (pair) { function exportKey (pair) {

View File

@ -3,7 +3,6 @@
const multihashing = require('multihashing-async') const multihashing = require('multihashing-async')
const protobuf = require('protons') const protobuf = require('protons')
const bs58 = require('bs58') const bs58 = require('bs58')
const nextTick = require('async/nextTick')
const crypto = require('./rsa') const crypto = require('./rsa')
const pbm = protobuf(require('./keys.proto')) const pbm = protobuf(require('./keys.proto'))
@ -16,9 +15,8 @@ class RsaPublicKey {
this._key = key this._key = key
} }
verify (data, sig, callback) { async verify (data, sig) { // eslint-disable-line require-await
ensure(callback) return crypto.hashAndVerify(this._key, sig, data)
crypto.hashAndVerify(this._key, sig, data, callback)
} }
marshal () { marshal () {
@ -40,9 +38,8 @@ class RsaPublicKey {
return this.bytes.equals(key.bytes) return this.bytes.equals(key.bytes)
} }
hash (callback) { async hash () { // eslint-disable-line require-await
ensure(callback) return multihashing(this.bytes, 'sha2-256')
multihashing(this.bytes, 'sha2-256', callback)
} }
} }
@ -58,9 +55,8 @@ class RsaPrivateKey {
return crypto.getRandomValues(16) return crypto.getRandomValues(16)
} }
sign (message, callback) { async sign (message) { // eslint-disable-line require-await
ensure(callback) return crypto.hashAndSign(this._key, message)
crypto.hashAndSign(this._key, message, callback)
} }
get public () { get public () {
@ -71,10 +67,6 @@ class RsaPrivateKey {
return new RsaPublicKey(this._publicKey) return new RsaPublicKey(this._publicKey)
} }
decrypt (msg, callback) {
crypto.decrypt(this._key, msg, callback)
}
marshal () { marshal () {
return crypto.utils.jwkToPkcs1(this._key) return crypto.utils.jwkToPkcs1(this._key)
} }
@ -90,9 +82,8 @@ class RsaPrivateKey {
return this.bytes.equals(key.bytes) return this.bytes.equals(key.bytes)
} }
hash (callback) { async hash () { // eslint-disable-line require-await
ensure(callback) return multihashing(this.bytes, 'sha2-256')
multihashing(this.bytes, 'sha2-256', callback)
} }
/** /**
@ -102,16 +93,11 @@ class RsaPrivateKey {
* The public key is a protobuf encoding containing a type and the DER encoding * The public key is a protobuf encoding containing a type and the DER encoding
* of the PKCS SubjectPublicKeyInfo. * of the PKCS SubjectPublicKeyInfo.
* *
* @param {function(Error, id)} callback * @returns {Promise<String>}
* @returns {undefined}
*/ */
id (callback) { async id () {
this.public.hash((err, hash) => { const hash = await this.public.hash()
if (err) { return bs58.encode(hash)
return callback(err)
}
callback(null, bs58.encode(hash))
})
} }
/** /**
@ -119,25 +105,20 @@ class RsaPrivateKey {
* *
* @param {string} [format] - Defaults to 'pkcs-8'. * @param {string} [format] - Defaults to 'pkcs-8'.
* @param {string} password - The password to read the encrypted PEM * @param {string} password - The password to read the encrypted PEM
* @param {function(Error, KeyInfo)} callback * @returns {KeyInfo}
* @returns {undefined}
*/ */
export (format, password, callback) { async export (format, password) { // eslint-disable-line require-await
if (typeof password === 'function') { if (password == null) {
callback = password
password = format password = format
format = 'pkcs-8' format = 'pkcs-8'
} }
ensure(callback)
nextTick(() => {
let err = null
let pem = null let pem = null
try {
const buffer = new forge.util.ByteBuffer(this.marshal()) const buffer = new forge.util.ByteBuffer(this.marshal())
const asn1 = forge.asn1.fromDer(buffer) const asn1 = forge.asn1.fromDer(buffer)
const privateKey = forge.pki.privateKeyFromAsn1(asn1) const privateKey = forge.pki.privateKeyFromAsn1(asn1)
if (format === 'pkcs-8') { if (format === 'pkcs-8') {
const options = { const options = {
algorithm: 'aes256', algorithm: 'aes256',
@ -147,59 +128,32 @@ class RsaPrivateKey {
} }
pem = forge.pki.encryptRsaPrivateKey(privateKey, password, options) pem = forge.pki.encryptRsaPrivateKey(privateKey, password, options)
} else { } else {
err = new Error(`Unknown export format '${format}'`) throw new Error(`Unknown export format '${format}'`)
}
} catch (_err) {
err = _err
} }
callback(err, pem) return pem
})
} }
} }
function unmarshalRsaPrivateKey (bytes, callback) { async function unmarshalRsaPrivateKey (bytes) {
const jwk = crypto.utils.pkcs1ToJwk(bytes) const jwk = crypto.utils.pkcs1ToJwk(bytes)
const keys = await crypto.unmarshalPrivateKey(jwk)
crypto.unmarshalPrivateKey(jwk, (err, keys) => { return new RsaPrivateKey(keys.privateKey, keys.publicKey)
if (err) {
return callback(err)
}
callback(null, new RsaPrivateKey(keys.privateKey, keys.publicKey))
})
} }
function unmarshalRsaPublicKey (bytes) { function unmarshalRsaPublicKey (bytes) {
const jwk = crypto.utils.pkixToJwk(bytes) const jwk = crypto.utils.pkixToJwk(bytes)
return new RsaPublicKey(jwk) return new RsaPublicKey(jwk)
} }
function fromJwk (jwk, callback) { async function fromJwk (jwk) {
crypto.unmarshalPrivateKey(jwk, (err, keys) => { const keys = await crypto.unmarshalPrivateKey(jwk)
if (err) { return new RsaPrivateKey(keys.privateKey, keys.publicKey)
return callback(err)
}
callback(null, new RsaPrivateKey(keys.privateKey, keys.publicKey))
})
} }
function generateKeyPair (bits, callback) { async function generateKeyPair (bits) {
crypto.generateKey(bits, (err, keys) => { const keys = await crypto.generateKey(bits)
if (err) { return new RsaPrivateKey(keys.privateKey, keys.publicKey)
return callback(err)
}
callback(null, new RsaPrivateKey(keys.privateKey, keys.publicKey))
})
}
function ensure (callback) {
if (typeof callback !== 'function') {
throw new Error('callback is required')
}
} }
module.exports = { module.exports = {

View File

@ -2,7 +2,6 @@
const crypto = require('crypto') const crypto = require('crypto')
const randomBytes = require('../random-bytes') const randomBytes = require('../random-bytes')
const nextTick = require('async/nextTick')
let keypair let keypair
try { try {
@ -30,70 +29,41 @@ const jwkToPem = require('pem-jwk').jwk2pem
exports.utils = require('./rsa-utils') exports.utils = require('./rsa-utils')
exports.generateKey = function (bits, callback) { exports.generateKey = async function (bits) { // eslint-disable-line require-await
nextTick(() => { const key = keypair({ bits })
let result return {
try {
const key = keypair({ bits: bits })
result = {
privateKey: pemToJwk(key.private), privateKey: pemToJwk(key.private),
publicKey: pemToJwk(key.public) publicKey: pemToJwk(key.public)
} }
} catch (err) {
return callback(err)
}
callback(null, result)
})
} }
// Takes a jwk key // Takes a jwk key
exports.unmarshalPrivateKey = function (key, callback) { exports.unmarshalPrivateKey = async function (key) { // eslint-disable-line require-await
nextTick(() => {
if (!key) { if (!key) {
return callback(new Error('Key is invalid')) throw new Error('Key is invalid')
} }
callback(null, { return {
privateKey: key, privateKey: key,
publicKey: { publicKey: {
kty: key.kty, kty: key.kty,
n: key.n, n: key.n,
e: key.e e: key.e
} }
}) }
})
} }
exports.getRandomValues = randomBytes exports.getRandomValues = randomBytes
exports.hashAndSign = function (key, msg, callback) { exports.hashAndSign = async function (key, msg) { // eslint-disable-line require-await
nextTick(() => {
let result
try {
const sign = crypto.createSign('RSA-SHA256') const sign = crypto.createSign('RSA-SHA256')
sign.update(msg) sign.update(msg)
const pem = jwkToPem(key) const pem = jwkToPem(key)
result = sign.sign(pem) return sign.sign(pem)
} catch (err) {
return callback(new Error('Key or message is invalid!: ' + err.message))
}
callback(null, result)
})
} }
exports.hashAndVerify = function (key, sig, msg, callback) { exports.hashAndVerify = async function (key, sig, msg) { // eslint-disable-line require-await
nextTick(() => {
let result
try {
const verify = crypto.createVerify('RSA-SHA256') const verify = crypto.createVerify('RSA-SHA256')
verify.update(msg) verify.update(msg)
const pem = jwkToPem(key) const pem = jwkToPem(key)
result = verify.verify(pem, sig) return verify.verify(pem, sig)
} catch (err) {
return callback(new Error('Key or message is invalid!:' + err.message))
}
callback(null, result)
})
} }

View File

@ -1,11 +0,0 @@
'use strict'
// Based on npmjs.com/nodeify but without additional `nextTick` calls
// to keep the overhead low
module.exports = function nodeify (promise, cb) {
return promise.then((res) => {
cb(null, res)
}, (err) => {
cb(err)
})
}

View File

@ -6,7 +6,6 @@ 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 series = require('async/series')
const crypto = require('../../src') const crypto = require('../../src')
const fixtures = require('./../fixtures/aes') const fixtures = require('./../fixtures/aes')
@ -19,53 +18,43 @@ const bytes = {
describe('AES-CTR', () => { describe('AES-CTR', () => {
Object.keys(bytes).forEach((byte) => { Object.keys(bytes).forEach((byte) => {
it(`${bytes[byte]} - encrypt and decrypt`, (done) => { it(`${bytes[byte]} - encrypt and decrypt`, async () => {
const key = Buffer.alloc(parseInt(byte, 10)) const key = Buffer.alloc(parseInt(byte, 10))
key.fill(5) key.fill(5)
const iv = Buffer.alloc(16) const iv = Buffer.alloc(16)
iv.fill(1) iv.fill(1)
crypto.aes.create(key, iv, (err, cipher) => { const cipher = await crypto.aes.create(key, iv)
expect(err).to.not.exist()
series([ await encryptAndDecrypt(cipher)
encryptAndDecrypt(cipher), await encryptAndDecrypt(cipher)
encryptAndDecrypt(cipher), await encryptAndDecrypt(cipher)
encryptAndDecrypt(cipher), await encryptAndDecrypt(cipher)
encryptAndDecrypt(cipher), await encryptAndDecrypt(cipher)
encryptAndDecrypt(cipher)
], done)
})
}) })
}) })
Object.keys(bytes).forEach((byte) => { Object.keys(bytes).forEach((byte) => {
it(`${bytes[byte]} - fixed - encrypt and decrypt`, (done) => { it(`${bytes[byte]} - fixed - encrypt and decrypt`, async () => {
const key = Buffer.alloc(parseInt(byte, 10)) const key = Buffer.alloc(parseInt(byte, 10))
key.fill(5) key.fill(5)
const iv = Buffer.alloc(16) const iv = Buffer.alloc(16)
iv.fill(1) iv.fill(1)
crypto.aes.create(key, iv, (err, cipher) => { const cipher = await crypto.aes.create(key, iv)
expect(err).to.not.exist()
series(fixtures[byte].inputs.map((rawIn, i) => (cb) => { for (let i = 0; i < fixtures[byte].inputs.length; i++) {
const rawIn = fixtures[byte].inputs[i]
const input = Buffer.from(rawIn) const input = Buffer.from(rawIn)
const output = Buffer.from(fixtures[byte].outputs[i]) const output = Buffer.from(fixtures[byte].outputs[i])
cipher.encrypt(input, (err, res) => { const encrypted = await cipher.encrypt(input)
expect(err).to.not.exist() expect(encrypted).to.have.length(output.length)
expect(res).to.have.length(output.length) expect(encrypted).to.eql(output)
expect(res).to.eql(output) const decrypted = await cipher.decrypt(encrypted)
cipher.decrypt(res, (err, res) => { expect(decrypted).to.eql(input)
expect(err).to.not.exist() }
expect(res).to.eql(input)
cb()
})
})
}), done)
})
}) })
}) })
@ -74,46 +63,35 @@ describe('AES-CTR', () => {
return return
} }
it(`${bytes[byte]} - go interop - encrypt and decrypt`, (done) => { it(`${bytes[byte]} - go interop - encrypt and decrypt`, async () => {
const key = Buffer.alloc(parseInt(byte, 10)) const key = Buffer.alloc(parseInt(byte, 10))
key.fill(5) key.fill(5)
const iv = Buffer.alloc(16) const iv = Buffer.alloc(16)
iv.fill(1) iv.fill(1)
crypto.aes.create(key, iv, (err, cipher) => { const cipher = await crypto.aes.create(key, iv)
expect(err).to.not.exist()
series(goFixtures[byte].inputs.map((rawIn, i) => (cb) => { for (let i = 0; i < goFixtures[byte].inputs.length; i++) {
const rawIn = goFixtures[byte].inputs[i]
const input = Buffer.from(rawIn) const input = Buffer.from(rawIn)
const output = Buffer.from(goFixtures[byte].outputs[i]) const output = Buffer.from(goFixtures[byte].outputs[i])
cipher.encrypt(input, (err, res) => { const encrypted = await cipher.encrypt(input)
expect(err).to.not.exist() expect(encrypted).to.have.length(output.length)
expect(res).to.have.length(output.length) expect(encrypted).to.eql(output)
expect(res).to.be.eql(output) const decrypted = await cipher.decrypt(encrypted)
cipher.decrypt(res, (err, res) => { expect(decrypted).to.eql(input)
expect(err).to.not.exist() }
expect(res).to.be.eql(input)
cb()
})
})
}), done)
})
}) })
}) })
}) })
function encryptAndDecrypt (cipher) { async function encryptAndDecrypt (cipher) {
const data = Buffer.alloc(100) const data = Buffer.alloc(100)
data.fill(Math.ceil(Math.random() * 100)) data.fill(Math.ceil(Math.random() * 100))
return (cb) => {
cipher.encrypt(data, (err, res) => { const encrypted = await cipher.encrypt(data)
expect(err).to.not.exist() const decrypted = await cipher.decrypt(encrypted)
cipher.decrypt(res, (err, res) => {
expect(err).to.not.exist() expect(decrypted).to.be.eql(data)
expect(res).to.be.eql(data)
cb()
})
})
}
} }

View File

@ -12,14 +12,8 @@ const fixtures = require('./fixtures/go-key-rsa')
describe('libp2p-crypto', function () { describe('libp2p-crypto', function () {
this.timeout(20 * 1000) this.timeout(20 * 1000)
let key let key
before((done) => { before(async () => {
crypto.keys.generateKeyPair('RSA', 512, (err, _key) => { key = await crypto.keys.generateKeyPair('RSA', 512)
if (err) {
return done(err)
}
key = _key
done()
})
}) })
it('marshalPublicKey and unmarshalPublicKey', () => { it('marshalPublicKey and unmarshalPublicKey', () => {
@ -33,71 +27,41 @@ describe('libp2p-crypto', function () {
}).to.throw() }).to.throw()
}) })
it('marshalPrivateKey and unmarshalPrivateKey', (done) => { it('marshalPrivateKey and unmarshalPrivateKey', async () => {
expect(() => { expect(() => {
crypto.keys.marshalPrivateKey(key, 'invalid-key-type') crypto.keys.marshalPrivateKey(key, 'invalid-key-type')
}).to.throw() }).to.throw()
crypto.keys.unmarshalPrivateKey(crypto.keys.marshalPrivateKey(key), (err, key2) => { const key2 = await crypto.keys.unmarshalPrivateKey(crypto.keys.marshalPrivateKey(key))
if (err) {
return done(err)
}
expect(key2.equals(key)).to.be.eql(true) expect(key2.equals(key)).to.be.eql(true)
expect(key2.public.equals(key.public)).to.be.eql(true) expect(key2.public.equals(key.public)).to.be.eql(true)
done()
})
}) })
// marshalled keys seem to be slightly different // marshalled keys seem to be slightly different
// unsure as to if this is just a difference in encoding // unsure as to if this is just a difference in encoding
// or a bug // or a bug
describe('go interop', () => { describe('go interop', () => {
it('unmarshals private key', (done) => { it('unmarshals private key', async () => {
crypto.keys.unmarshalPrivateKey(fixtures.private.key, (err, key) => { const key = await crypto.keys.unmarshalPrivateKey(fixtures.private.key)
if (err) {
return done(err)
}
const hash = fixtures.private.hash const hash = fixtures.private.hash
expect(fixtures.private.key).to.eql(key.bytes) expect(fixtures.private.key).to.eql(key.bytes)
const digest = await key.hash()
key.hash((err, digest) => {
if (err) {
return done(err)
}
expect(digest).to.eql(hash) expect(digest).to.eql(hash)
done()
})
})
}) })
it('unmarshals public key', (done) => { it('unmarshals public key', async () => {
const key = crypto.keys.unmarshalPublicKey(fixtures.public.key) const key = crypto.keys.unmarshalPublicKey(fixtures.public.key)
const hash = fixtures.public.hash const hash = fixtures.public.hash
expect(crypto.keys.marshalPublicKey(key)).to.eql(fixtures.public.key) expect(crypto.keys.marshalPublicKey(key)).to.eql(fixtures.public.key)
const digest = await key.hash()
key.hash((err, digest) => {
if (err) {
return done(err)
}
expect(digest).to.eql(hash) expect(digest).to.eql(hash)
done()
})
}) })
it('unmarshal -> marshal, private key', (done) => { it('unmarshal -> marshal, private key', async () => {
crypto.keys.unmarshalPrivateKey(fixtures.private.key, (err, key) => { const key = await crypto.keys.unmarshalPrivateKey(fixtures.private.key)
if (err) {
return done(err)
}
const marshalled = crypto.keys.marshalPrivateKey(key) const marshalled = crypto.keys.marshalPrivateKey(key)
expect(marshalled).to.eql(fixtures.private.key) expect(marshalled).to.eql(fixtures.private.key)
done()
})
}) })
it('unmarshal -> marshal, public key', () => { it('unmarshal -> marshal, public key', () => {

View File

@ -1,11 +1,6 @@
/* eslint-env mocha */ /* eslint-env mocha */
'use strict' 'use strict'
const chai = require('chai')
const dirtyChai = require('dirty-chai')
const expect = chai.expect
chai.use(dirtyChai)
const util = require('util') const util = require('util')
const garbage = [Buffer.from('00010203040506070809', 'hex'), {}, null, false, undefined, true, 1, 0, Buffer.from(''), 'aGVsbG93b3JsZA==', 'helloworld', ''] const garbage = [Buffer.from('00010203040506070809', 'hex'), {}, null, false, undefined, true, 1, 0, Buffer.from(''), 'aGVsbG93b3JsZA==', 'helloworld', '']
@ -23,14 +18,13 @@ function doTests (fncName, fnc, num, skipBuffersAndStrings) {
for (let i = 0; i < num; i++) { for (let i = 0; i < num; i++) {
args.push(garbage) args.push(garbage)
} }
it(fncName + '(' + args.map(garbage => util.inspect(garbage)).join(', ') + ')', cb => { it(fncName + '(' + args.map(garbage => util.inspect(garbage)).join(', ') + ')', async () => {
args.push((err, res) => { try {
expect(err).to.exist() await fnc.apply(null, args)
expect(res).to.not.exist() } catch (err) {
cb() return // expected
}) }
throw new Error('Expected error to be thrown')
fnc.apply(null, args)
}) })
}) })
} }

View File

@ -13,16 +13,10 @@ const hashes = ['SHA1', 'SHA256', 'SHA512']
describe('HMAC', () => { describe('HMAC', () => {
hashes.forEach((hash) => { hashes.forEach((hash) => {
it(`${hash} - sign and verify`, (done) => { it(`${hash} - sign and verify`, async () => {
crypto.hmac.create(hash, Buffer.from('secret'), (err, hmac) => { const hmac = await crypto.hmac.create(hash, Buffer.from('secret'))
expect(err).to.not.exist() const sig = await hmac.digest(Buffer.from('hello world'))
hmac.digest(Buffer.from('hello world'), (err, sig) => {
expect(err).to.not.exist()
expect(sig).to.have.length(hmac.length) expect(sig).to.have.length(hmac.length)
done()
})
})
}) })
}) })
}) })

View File

@ -15,94 +15,51 @@ const testGarbage = require('../helpers/test-garbage-error-handling')
describe('ed25519', function () { describe('ed25519', function () {
this.timeout(20 * 1000) this.timeout(20 * 1000)
let key let key
before((done) => { before(async () => {
crypto.keys.generateKeyPair('Ed25519', 512, (err, _key) => { key = await crypto.keys.generateKeyPair('Ed25519', 512)
if (err) return done(err)
key = _key
done()
})
}) })
it('generates a valid key', (done) => { it('generates a valid key', async () => {
expect(key).to.be.an.instanceof(ed25519.Ed25519PrivateKey) expect(key).to.be.an.instanceof(ed25519.Ed25519PrivateKey)
const digest = await key.hash()
key.hash((err, digest) => {
if (err) {
return done(err)
}
expect(digest).to.have.length(34) expect(digest).to.have.length(34)
done()
})
}) })
it('generates a valid key from seed', (done) => { it('generates a valid key from seed', async () => {
var seed = crypto.randomBytes(32) var seed = crypto.randomBytes(32)
crypto.keys.generateKeyPairFromSeed('Ed25519', seed, 512, (err, seededkey) => { const seededkey = await crypto.keys.generateKeyPairFromSeed('Ed25519', seed, 512)
if (err) return done(err)
expect(seededkey).to.be.an.instanceof(ed25519.Ed25519PrivateKey) expect(seededkey).to.be.an.instanceof(ed25519.Ed25519PrivateKey)
const digest = await seededkey.hash()
seededkey.hash((err, digest) => {
if (err) {
return done(err)
}
expect(digest).to.have.length(34) expect(digest).to.have.length(34)
done()
})
})
}) })
it('generates the same key from the same seed', (done) => { it('generates the same key from the same seed', async () => {
var seed = crypto.randomBytes(32) const seed = crypto.randomBytes(32)
crypto.keys.generateKeyPairFromSeed('Ed25519', seed, 512, (err, seededkey1) => { const seededkey1 = await crypto.keys.generateKeyPairFromSeed('Ed25519', seed, 512)
if (err) return done(err) const seededkey2 = await crypto.keys.generateKeyPairFromSeed('Ed25519', seed, 512)
crypto.keys.generateKeyPairFromSeed('Ed25519', seed, 512, (err, seededkey2) => {
if (err) return done(err)
expect(seededkey1.equals(seededkey2)).to.eql(true) expect(seededkey1.equals(seededkey2)).to.eql(true)
expect(seededkey1.public.equals(seededkey2.public)).to.eql(true) expect(seededkey1.public.equals(seededkey2.public)).to.eql(true)
done()
})
})
}) })
it('generates different keys for different seeds', (done) => { it('generates different keys for different seeds', async () => {
const seed1 = crypto.randomBytes(32) const seed1 = crypto.randomBytes(32)
crypto.keys.generateKeyPairFromSeed('Ed25519', seed1, 512, (err, seededkey1) => { const seededkey1 = await crypto.keys.generateKeyPairFromSeed('Ed25519', seed1, 512)
expect(err).to.not.exist()
const seed2 = crypto.randomBytes(32) const seed2 = crypto.randomBytes(32)
crypto.keys.generateKeyPairFromSeed('Ed25519', seed2, 512, (err, seededkey2) => { const seededkey2 = await crypto.keys.generateKeyPairFromSeed('Ed25519', seed2, 512)
expect(err).to.not.exist()
expect(seededkey1.equals(seededkey2)).to.eql(false) expect(seededkey1.equals(seededkey2)).to.eql(false)
expect(seededkey1.public.equals(seededkey2.public)) expect(seededkey1.public.equals(seededkey2.public)).to.eql(false)
.to.eql(false)
done()
})
})
}) })
it('signs', (done) => { it('signs', async () => {
const text = crypto.randomBytes(512) const text = crypto.randomBytes(512)
const sig = await key.sign(text)
key.sign(text, (err, sig) => { const res = await key.public.verify(text, sig)
expect(err).to.not.exist()
key.public.verify(text, sig, (err, res) => {
expect(err).to.not.exist()
expect(res).to.be.eql(true) expect(res).to.be.eql(true)
done()
})
})
}) })
it('encoding', (done) => { it('encoding', async () => {
const keyMarshal = key.marshal() const keyMarshal = key.marshal()
ed25519.unmarshalEd25519PrivateKey(keyMarshal, (err, key2) => { const key2 = await ed25519.unmarshalEd25519PrivateKey(keyMarshal)
if (err) {
return done(err)
}
const keyMarshal2 = key2.marshal() const keyMarshal2 = key2.marshal()
expect(keyMarshal).to.eql(keyMarshal2) expect(keyMarshal).to.eql(keyMarshal2)
@ -113,17 +70,12 @@ describe('ed25519', function () {
const pkMarshal2 = pk2.marshal() const pkMarshal2 = pk2.marshal()
expect(pkMarshal).to.eql(pkMarshal2) expect(pkMarshal).to.eql(pkMarshal2)
done()
})
}) })
it('key id', (done) => { it('key id', async () => {
key.id((err, id) => { const id = await key.id()
expect(err).to.not.exist()
expect(id).to.exist() expect(id).to.exist()
expect(id).to.be.a('string') expect(id).to.be.a('string')
done()
})
}) })
describe('key equals', () => { describe('key equals', () => {
@ -141,51 +93,27 @@ describe('ed25519', function () {
) )
}) })
it('not equals other key', (done) => { it('not equals other key', async () => {
crypto.keys.generateKeyPair('Ed25519', 512, (err, key2) => { const key2 = await crypto.keys.generateKeyPair('Ed25519', 512)
if (err) return done(err)
expect(key.equals(key2)).to.eql(false) expect(key.equals(key2)).to.eql(false)
expect(key2.equals(key)).to.eql(false) expect(key2.equals(key)).to.eql(false)
expect(key.public.equals(key2.public)).to.eql(false) expect(key.public.equals(key2.public)).to.eql(false)
expect(key2.public.equals(key.public)).to.eql(false) expect(key2.public.equals(key.public)).to.eql(false)
done()
})
}) })
}) })
it('sign and verify', (done) => { it('sign and verify', async () => {
const data = Buffer.from('hello world') const data = Buffer.from('hello world')
key.sign(data, (err, sig) => { const sig = await key.sign(data)
if (err) { const valid = await key.public.verify(data, sig)
return done(err)
}
key.public.verify(data, sig, (err, valid) => {
if (err) {
return done(err)
}
expect(valid).to.eql(true) expect(valid).to.eql(true)
done()
})
})
}) })
it('fails to verify for different data', (done) => { it('fails to verify for different data', async () => {
const data = Buffer.from('hello world') const data = Buffer.from('hello world')
key.sign(data, (err, sig) => { const sig = await key.sign(data)
if (err) { const valid = await key.public.verify(Buffer.from('hello'), sig)
return done(err)
}
key.public.verify(Buffer.from('hello'), sig, (err, valid) => {
if (err) {
return done(err)
}
expect(valid).to.be.eql(false) expect(valid).to.be.eql(false)
done()
})
})
}) })
describe('returns error via cb instead of crashing', () => { describe('returns error via cb instead of crashing', () => {
@ -197,30 +125,20 @@ describe('ed25519', function () {
describe('go interop', () => { describe('go interop', () => {
let privateKey let privateKey
before((done) => { before(async () => {
crypto.keys.unmarshalPrivateKey(fixtures.verify.privateKey, (err, key) => { const key = await crypto.keys.unmarshalPrivateKey(fixtures.verify.privateKey)
expect(err).to.not.exist()
privateKey = key privateKey = key
done()
})
}) })
it('verifies with data from go', (done) => { it('verifies with data from go', async () => {
const key = crypto.keys.unmarshalPublicKey(fixtures.verify.publicKey) const key = crypto.keys.unmarshalPublicKey(fixtures.verify.publicKey)
const ok = await key.verify(fixtures.verify.data, fixtures.verify.signature)
key.verify(fixtures.verify.data, fixtures.verify.signature, (err, ok) => {
expect(err).to.not.exist()
expect(ok).to.eql(true) expect(ok).to.eql(true)
done()
})
}) })
it('generates the same signature as go', (done) => { it('generates the same signature as go', async () => {
privateKey.sign(fixtures.verify.data, (err, sig) => { const sig = await privateKey.sign(fixtures.verify.data)
expect(err).to.not.exist()
expect(sig).to.eql(fixtures.verify.signature) expect(sig).to.eql(fixtures.verify.signature)
done()
})
}) })
}) })
}) })

View File

@ -6,7 +6,6 @@ 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 parallel = require('async/parallel')
const fixtures = require('../fixtures/go-elliptic-key') const fixtures = require('../fixtures/go-elliptic-key')
const crypto = require('../../src') const crypto = require('../../src')
@ -25,49 +24,40 @@ const secretLengths = {
describe('generateEphemeralKeyPair', () => { describe('generateEphemeralKeyPair', () => {
curves.forEach((curve) => { curves.forEach((curve) => {
it(`generate and shared key ${curve}`, (done) => { it(`generate and shared key ${curve}`, async () => {
parallel([ const keys = await Promise.all([
(cb) => crypto.keys.generateEphemeralKeyPair(curve, cb), crypto.keys.generateEphemeralKeyPair(curve),
(cb) => crypto.keys.generateEphemeralKeyPair(curve, cb) crypto.keys.generateEphemeralKeyPair(curve)
], (err, keys) => { ])
expect(err).to.not.exist()
expect(keys[0].key).to.have.length(lengths[curve]) expect(keys[0].key).to.have.length(lengths[curve])
expect(keys[1].key).to.have.length(lengths[curve]) expect(keys[1].key).to.have.length(lengths[curve])
keys[0].genSharedKey(keys[1].key, (err, shared) => { const shared = await keys[0].genSharedKey(keys[1].key)
expect(err).to.not.exist()
expect(shared).to.have.length(secretLengths[curve]) expect(shared).to.have.length(secretLengths[curve])
done()
})
})
}) })
}) })
describe('go interop', () => { describe('go interop', () => {
it('generates a shared secret', (done) => { it('generates a shared secret', async () => {
const curve = fixtures.curve const curve = fixtures.curve
parallel([ const keys = await Promise.all([
(cb) => crypto.keys.generateEphemeralKeyPair(curve, cb), crypto.keys.generateEphemeralKeyPair(curve),
(cb) => crypto.keys.generateEphemeralKeyPair(curve, cb) crypto.keys.generateEphemeralKeyPair(curve)
], (err, res) => { ])
expect(err).to.not.exist()
const alice = res[0] const alice = keys[0]
const bob = res[1] const bob = keys[1]
bob.key = fixtures.bob.public bob.key = fixtures.bob.public
parallel([ const secrets = await Promise.all([
(cb) => alice.genSharedKey(bob.key, cb), alice.genSharedKey(bob.key),
(cb) => bob.genSharedKey(alice.key, fixtures.bob, cb) bob.genSharedKey(alice.key, fixtures.bob)
], (err, secrets) => { ])
expect(err).to.not.exist()
expect(secrets[0]).to.eql(secrets[1]) expect(secrets[0]).to.eql(secrets[1])
expect(secrets[0]).to.have.length(32) expect(secrets[0]).to.have.length(32)
done()
})
})
}) })
}) })
}) })

View File

@ -16,35 +16,17 @@ describe('keyStretcher', () => {
let res let res
let secret let secret
before((done) => { before(async () => {
crypto.keys.generateEphemeralKeyPair('P-256', (err, _res) => { res = await crypto.keys.generateEphemeralKeyPair('P-256')
if (err) { secret = await res.genSharedKey(res.key)
return done(err)
}
res = _res
res.genSharedKey(res.key, (err, _secret) => {
if (err) {
return done(err)
}
secret = _secret
done()
})
})
}) })
ciphers.forEach((cipher) => { ciphers.forEach((cipher) => {
hashes.forEach((hash) => { hashes.forEach((hash) => {
it(`${cipher} - ${hash}`, (done) => { it(`${cipher} - ${hash}`, async () => {
crypto.keys.keyStretcher(cipher, hash, secret, (err, keys) => { const keys = await crypto.keys.keyStretcher(cipher, hash, secret)
if (err) {
return done(err)
}
expect(keys.k1).to.exist() expect(keys.k1).to.exist()
expect(keys.k2).to.exist() expect(keys.k2).to.exist()
done()
})
}) })
}) })
}) })
@ -52,14 +34,11 @@ describe('keyStretcher', () => {
describe('go interop', () => { describe('go interop', () => {
fixtures.forEach((test) => { fixtures.forEach((test) => {
it(`${test.cipher} - ${test.hash}`, (done) => { it(`${test.cipher} - ${test.hash}`, async () => {
const cipher = test.cipher const cipher = test.cipher
const hash = test.hash const hash = test.hash
const secret = test.secret const secret = test.secret
crypto.keys.keyStretcher(cipher, hash, secret, (err, keys) => { const keys = await crypto.keys.keyStretcher(cipher, hash, secret)
if (err) {
return done(err)
}
expect(keys.k1.iv).to.be.eql(test.k1.iv) expect(keys.k1.iv).to.be.eql(test.k1.iv)
expect(keys.k1.cipherKey).to.be.eql(test.k1.cipherKey) expect(keys.k1.cipherKey).to.be.eql(test.k1.cipherKey)
@ -68,8 +47,6 @@ describe('keyStretcher', () => {
expect(keys.k2.iv).to.be.eql(test.k2.iv) expect(keys.k2.iv).to.be.eql(test.k2.iv)
expect(keys.k2.cipherKey).to.be.eql(test.k2.cipherKey) expect(keys.k2.cipherKey).to.be.eql(test.k2.cipherKey)
expect(keys.k2.macKey).to.be.eql(test.k2.macKey) expect(keys.k2.macKey).to.be.eql(test.k2.macKey)
done()
})
}) })
}) })
}) })

View File

@ -32,23 +32,11 @@ describe('RSA crypto libs', function () {
rsa = crypto.keys.supportedKeys.rsa rsa = crypto.keys.supportedKeys.rsa
}) })
it('generates a valid key', (done) => { it('generates a valid key', async () => {
crypto.keys.generateKeyPair('RSA', 512, (err, key) => { const key = await crypto.keys.generateKeyPair('RSA', 512)
if (err) {
return done(err)
}
expect(key).to.be.an.instanceof(rsa.RsaPrivateKey) expect(key).to.be.an.instanceof(rsa.RsaPrivateKey)
const digest = await key.hash()
key.hash((err, digest) => {
if (err) {
return done(err)
}
expect(digest).to.have.length(34) expect(digest).to.have.length(34)
done()
})
})
}) })
after(() => { after(() => {

View File

@ -18,54 +18,26 @@ describe('RSA', function () {
this.timeout(20 * 1000) this.timeout(20 * 1000)
let key let key
before((done) => { before(async () => {
crypto.keys.generateKeyPair('RSA', 512, (err, _key) => { key = await crypto.keys.generateKeyPair('RSA', 512)
if (err) {
return done(err)
}
key = _key
done()
})
}) })
it('generates a valid key', (done) => { it('generates a valid key', async () => {
expect(key).to.be.an.instanceof(rsa.RsaPrivateKey) expect(key).to.be.an.instanceof(rsa.RsaPrivateKey)
const digest = await key.hash()
key.hash((err, digest) => {
if (err) {
return done(err)
}
expect(digest).to.have.length(34) expect(digest).to.have.length(34)
done()
})
}) })
it('signs', (done) => { it('signs', async () => {
const text = key.genSecret() const text = key.genSecret()
const sig = await key.sign(text)
key.sign(text, (err, sig) => { const res = await key.public.verify(text, sig)
if (err) {
return done(err)
}
key.public.verify(text, sig, (err, res) => {
if (err) {
return done(err)
}
expect(res).to.be.eql(true) expect(res).to.be.eql(true)
done()
})
})
}) })
it('encoding', (done) => { it('encoding', async () => {
const keyMarshal = key.marshal() const keyMarshal = key.marshal()
rsa.unmarshalRsaPrivateKey(keyMarshal, (err, key2) => { const key2 = await rsa.unmarshalRsaPrivateKey(keyMarshal)
if (err) {
return done(err)
}
const keyMarshal2 = key2.marshal() const keyMarshal2 = key2.marshal()
expect(keyMarshal).to.eql(keyMarshal2) expect(keyMarshal).to.eql(keyMarshal2)
@ -76,17 +48,12 @@ describe('RSA', function () {
const pkMarshal2 = pk2.marshal() const pkMarshal2 = pk2.marshal()
expect(pkMarshal).to.eql(pkMarshal2) expect(pkMarshal).to.eql(pkMarshal2)
done()
})
}) })
it('key id', (done) => { it('key id', async () => {
key.id((err, id) => { const id = await key.id()
expect(err).to.not.exist()
expect(id).to.exist() expect(id).to.exist()
expect(id).to.be.a('string') expect(id).to.be.a('string')
done()
})
}) })
describe('key equals', () => { describe('key equals', () => {
@ -96,90 +63,54 @@ describe('RSA', function () {
expect(key.public.equals(key.public)).to.eql(true) expect(key.public.equals(key.public)).to.eql(true)
}) })
it('not equals other key', (done) => { it('not equals other key', async () => {
crypto.keys.generateKeyPair('RSA', 512, (err, key2) => { const key2 = await crypto.keys.generateKeyPair('RSA', 512)
if (err) {
return done(err)
}
expect(key.equals(key2)).to.eql(false) expect(key.equals(key2)).to.eql(false)
expect(key2.equals(key)).to.eql(false) expect(key2.equals(key)).to.eql(false)
expect(key.public.equals(key2.public)).to.eql(false) expect(key.public.equals(key2.public)).to.eql(false)
expect(key2.public.equals(key.public)).to.eql(false) expect(key2.public.equals(key.public)).to.eql(false)
done()
})
}) })
}) })
it('sign and verify', (done) => { it('sign and verify', async () => {
const data = Buffer.from('hello world') const data = Buffer.from('hello world')
key.sign(data, (err, sig) => { const sig = await key.sign(data)
if (err) { const valid = await key.public.verify(data, sig)
return done(err)
}
key.public.verify(data, sig, (err, valid) => {
if (err) {
return done(err)
}
expect(valid).to.be.eql(true) expect(valid).to.be.eql(true)
done()
})
})
}) })
it('fails to verify for different data', (done) => { it('fails to verify for different data', async () => {
const data = Buffer.from('hello world') const data = Buffer.from('hello world')
key.sign(data, (err, sig) => { const sig = await key.sign(data)
if (err) { const valid = await key.public.verify(Buffer.from('hello'), sig)
return done(err)
}
key.public.verify(Buffer.from('hello'), sig, (err, valid) => {
if (err) {
return done(err)
}
expect(valid).to.be.eql(false) expect(valid).to.be.eql(false)
done()
})
})
}) })
describe('export and import', () => { describe('export and import', () => {
it('password protected PKCS #8', (done) => { it('password protected PKCS #8', async () => {
key.export('pkcs-8', 'my secret', (err, pem) => { const pem = await key.export('pkcs-8', 'my secret')
expect(err).to.not.exist()
expect(pem).to.startsWith('-----BEGIN ENCRYPTED PRIVATE KEY-----') expect(pem).to.startsWith('-----BEGIN ENCRYPTED PRIVATE KEY-----')
crypto.keys.import(pem, 'my secret', (err, clone) => { const clone = await crypto.keys.import(pem, 'my secret')
expect(err).to.not.exist()
expect(clone).to.exist() expect(clone).to.exist()
expect(key.equals(clone)).to.eql(true) expect(key.equals(clone)).to.eql(true)
done()
})
})
}) })
it('defaults to PKCS #8', (done) => { it('defaults to PKCS #8', async () => {
key.export('another secret', (err, pem) => { const pem = await key.export('another secret')
expect(err).to.not.exist()
expect(pem).to.startsWith('-----BEGIN ENCRYPTED PRIVATE KEY-----') expect(pem).to.startsWith('-----BEGIN ENCRYPTED PRIVATE KEY-----')
crypto.keys.import(pem, 'another secret', (err, clone) => { const clone = await crypto.keys.import(pem, 'another secret')
expect(err).to.not.exist()
expect(clone).to.exist() expect(clone).to.exist()
expect(key.equals(clone)).to.eql(true) expect(key.equals(clone)).to.eql(true)
done()
})
})
}) })
it('needs correct password', (done) => { it('needs correct password', async () => {
key.export('another secret', (err, pem) => { const pem = await key.export('another secret')
expect(err).to.not.exist() try {
crypto.keys.import(pem, 'not the secret', (err, clone) => { await crypto.keys.import(pem, 'not the secret')
expect(err).to.exist() } catch (err) {
done() return // expected
}) }
}) throw new Error('Expected error to be thrown')
}) })
}) })
@ -190,20 +121,15 @@ describe('RSA', function () {
}) })
describe('go interop', () => { describe('go interop', () => {
it('verifies with data from go', (done) => { it('verifies with data from go', async () => {
const key = crypto.keys.unmarshalPublicKey(fixtures.verify.publicKey) const key = crypto.keys.unmarshalPublicKey(fixtures.verify.publicKey)
const ok = await key.verify(fixtures.verify.data, fixtures.verify.signature)
key.verify(fixtures.verify.data, fixtures.verify.signature, (err, ok) => {
if (err) throw err
expect(err).to.not.exist()
expect(ok).to.equal(true) expect(ok).to.equal(true)
done()
})
}) })
}) })
describe('openssl interop', () => { describe('openssl interop', () => {
it('can read a private key', (done) => { it('can read a private key', async () => {
/* /*
* Generated with * Generated with
* openssl genpkey -algorithm RSA * openssl genpkey -algorithm RSA
@ -251,19 +177,14 @@ gnjREs10u7zyqBIZH7KYVgyh27WxLr859ap8cKAH6Fb+UOPtZo3sUeeume60aebn
4pMwXeXP+LO8NIfRXV8mgrm86g== 4pMwXeXP+LO8NIfRXV8mgrm86g==
-----END PRIVATE KEY----- -----END PRIVATE KEY-----
` `
crypto.keys.import(pem, '', (err, key) => { const key = await crypto.keys.import(pem, '')
expect(err).to.not.exist()
expect(key).to.exist() expect(key).to.exist()
key.id((err, id) => { const id = await key.id()
expect(err).to.not.exist()
expect(id).to.equal('QmfWu2Xp8DZzCkZZzoPB9rcrq4R4RZid6AWE6kmrUAzuHy') expect(id).to.equal('QmfWu2Xp8DZzCkZZzoPB9rcrq4R4RZid6AWE6kmrUAzuHy')
done()
})
})
}) })
// AssertionError: expected 'this only supports pkcs5PBES2' to not exist // AssertionError: expected 'this only supports pkcs5PBES2' to not exist
it.skip('can read a private encrypted key (v1)', (done) => { it.skip('can read a private encrypted key (v1)', async () => {
/* /*
* Generated with * Generated with
* openssl genpkey -algorithm RSA * openssl genpkey -algorithm RSA
@ -290,14 +211,11 @@ mBdkD5r+ixWF174naw53L8U9wF8kiK7pIE1N9TR4USEeovLwX6Ni/2MMDZedOfof
0uxzo5Y= 0uxzo5Y=
-----END ENCRYPTED PRIVATE KEY----- -----END ENCRYPTED PRIVATE KEY-----
` `
crypto.keys.import(pem, 'mypassword', (err, key) => { const key = await crypto.keys.import(pem, 'mypassword')
expect(err).to.not.exist()
expect(key).to.exist() expect(key).to.exist()
done()
})
}) })
it('can read a private encrypted key (v2 aes-128-cbc)', (done) => { it('can read a private encrypted key (v2 aes-128-cbc)', async () => {
/* /*
* Generated with * Generated with
* openssl genpkey -algorithm RSA * openssl genpkey -algorithm RSA
@ -325,14 +243,11 @@ ePGbz+UtSb9xczvqpRCOiFLh2MG1dUgWuHazjOtUcVWvilKnkjCMzZ9s1qG0sUDj
nPyn nPyn
-----END ENCRYPTED PRIVATE KEY----- -----END ENCRYPTED PRIVATE KEY-----
` `
crypto.keys.import(pem, 'mypassword', (err, key) => { const key = await crypto.keys.import(pem, 'mypassword')
expect(err).to.not.exist()
expect(key).to.exist() expect(key).to.exist()
done()
})
}) })
it('can read a private encrypted key (v2 aes-256-cbc)', (done) => { it('can read a private encrypted key (v2 aes-256-cbc)', async () => {
/* /*
* Generated with * Generated with
* openssl genpkey -algorithm RSA * openssl genpkey -algorithm RSA
@ -360,14 +275,11 @@ mBUuWAZMpz7njBi7h+JDfmSW/GAaMwrVFC2gef5375R0TejAh+COAjItyoeYEvv8
DQd8 DQd8
-----END ENCRYPTED PRIVATE KEY----- -----END ENCRYPTED PRIVATE KEY-----
` `
crypto.keys.import(pem, 'mypassword', (err, key) => { const key = await crypto.keys.import(pem, 'mypassword')
expect(err).to.not.exist()
expect(key).to.exist() expect(key).to.exist()
done()
})
}) })
it('can read a private encrypted key (v2 des)', (done) => { it('can read a private encrypted key (v2 des)', async () => {
/* /*
* Generated with * Generated with
* openssl genpkey -algorithm RSA * openssl genpkey -algorithm RSA
@ -394,14 +306,11 @@ A+qCKbprxyL8SKI5vug2hE+mfC1leXVRtUYm1DnE+oet99bFd0fN20NwTw0rOeRg
EBqQkwAUXR1tNekF8CWLOrfC/wbLRxVRkayb8bQUfdgukLpz0bgw EBqQkwAUXR1tNekF8CWLOrfC/wbLRxVRkayb8bQUfdgukLpz0bgw
-----END ENCRYPTED PRIVATE KEY----- -----END ENCRYPTED PRIVATE KEY-----
` `
crypto.keys.import(pem, 'mypassword', (err, key) => { const key = await crypto.keys.import(pem, 'mypassword')
expect(err).to.not.exist()
expect(key).to.exist() expect(key).to.exist()
done()
})
}) })
it('can read a private encrypted key (v2 des3)', (done) => { it('can read a private encrypted key (v2 des3)', async () => {
/* /*
* Generated with * Generated with
* openssl genpkey -algorithm RSA * openssl genpkey -algorithm RSA
@ -428,11 +337,8 @@ NT2TO3kSzXpQ5M2VjOoHPm2fqxD/js+ThDB3QLi4+C7HqakfiTY1lYzXl9/vayt6
DUD29r9pYL9ErB9tYko2rat54EY7k7Ts6S5jf+8G7Zz234We1APhvqaG DUD29r9pYL9ErB9tYko2rat54EY7k7Ts6S5jf+8G7Zz234We1APhvqaG
-----END ENCRYPTED PRIVATE KEY----- -----END ENCRYPTED PRIVATE KEY-----
` `
crypto.keys.import(pem, 'mypassword', (err, key) => { const key = await crypto.keys.import(pem, 'mypassword')
expect(err).to.not.exist()
expect(key).to.exist() expect(key).to.exist()
done()
})
}) })
}) })
}) })

View File

@ -18,12 +18,12 @@ const mockPrivateKey = {
} }
const mockSecp256k1Module = { const mockSecp256k1Module = {
generateKeyPair (bits, callback) { generateKeyPair (bits) {
callback(null, mockPrivateKey) return mockPrivateKey
}, },
unmarshalSecp256k1PrivateKey (buf, callback) { unmarshalSecp256k1PrivateKey (buf) {
callback(null, mockPrivateKey) return mockPrivateKey
}, },
unmarshalSecp256k1PublicKey (buf) { unmarshalSecp256k1PublicKey (buf) {
@ -34,20 +34,22 @@ 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', async () => {
crypto.keys.generateKeyPair('secp256k1', 256, (err, key) => { try {
expect(err).to.exist() await crypto.keys.generateKeyPair('secp256k1', 256)
expect(key).to.not.exist() } catch (err) {
done() return // expected
}) }
throw new Error('Expected error to be thrown')
}) })
it('fails to unmarshal a secp256k1 private key', (done) => { it('fails to unmarshal a secp256k1 private key', async () => {
crypto.keys.unmarshalPrivateKey(fixtures.pbmPrivateKey, (err, key) => { try {
expect(err).to.exist() await crypto.keys.unmarshalPrivateKey(fixtures.pbmPrivateKey)
expect(key).to.not.exist() } catch (err) {
done() return // expected
}) }
throw new Error('Expected error to be thrown')
}) })
it('fails to unmarshal a secp256k1 public key', () => { it('fails to unmarshal a secp256k1 public key', () => {
@ -60,29 +62,22 @@ describe('without libp2p-crypto-secp256k1 module present', () => {
describe('with libp2p-crypto-secp256k1 module present', () => { describe('with libp2p-crypto-secp256k1 module present', () => {
let key let key
before((done) => { before(async () => {
crypto.keys.supportedKeys.secp256k1 = mockSecp256k1Module crypto.keys.supportedKeys.secp256k1 = mockSecp256k1Module
crypto.keys.generateKeyPair('secp256k1', 256, (err, _key) => { key = await crypto.keys.generateKeyPair('secp256k1', 256)
if (err) return done(err)
key = _key
done()
})
}) })
after((done) => { after(() => {
delete crypto.keys.secp256k1 delete crypto.keys.secp256k1
done()
}) })
it('generates a valid key', (done) => { it('generates a valid key', () => {
expect(key).to.exist() expect(key).to.exist()
done()
}) })
it('protobuf encoding', (done) => { it('protobuf encoding', async () => {
const keyMarshal = crypto.keys.marshalPrivateKey(key) const keyMarshal = crypto.keys.marshalPrivateKey(key)
crypto.keys.unmarshalPrivateKey(keyMarshal, (err, key2) => { const key2 = await crypto.keys.unmarshalPrivateKey(keyMarshal)
if (err) return done(err)
const keyMarshal2 = crypto.keys.marshalPrivateKey(key2) const keyMarshal2 = crypto.keys.marshalPrivateKey(key2)
expect(keyMarshal).to.eql(keyMarshal2) expect(keyMarshal).to.eql(keyMarshal2)
@ -93,7 +88,5 @@ describe('with libp2p-crypto-secp256k1 module present', () => {
const pkMarshal2 = crypto.keys.marshalPublicKey(pk2) const pkMarshal2 = crypto.keys.marshalPublicKey(pk2)
expect(pkMarshal).to.eql(pkMarshal2) expect(pkMarshal).to.eql(pkMarshal2)
done()
})
}) })
}) })