mirror of
https://github.com/fluencelabs/js-libp2p-crypto
synced 2025-07-21 22:52:05 +00:00
Compare commits
34 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
2b0b7abd78 | ||
|
17f2065d21 | ||
|
2f065167fa | ||
|
e0ecce18ce | ||
|
cea1140ec6 | ||
|
e5b7c1f622 | ||
|
20326199d9 | ||
|
4e56e1724f | ||
|
7d63f698c0 | ||
|
a49df7786c | ||
|
c73adb00cc | ||
|
8a95de4700 | ||
|
c35a65133f | ||
|
4eb4aa05de | ||
|
21f96a4eb7 | ||
|
39b5124526 | ||
|
93e50dde10 | ||
|
e383da5d44 | ||
|
9b687f380c | ||
|
82abede64a | ||
|
a56ab406e4 | ||
|
d753941c6e | ||
|
6022eb0838 | ||
|
1c6d0912cd | ||
|
e18804c31e | ||
|
133a2c8833 | ||
|
fad0865b2b | ||
|
4edef07182 | ||
|
19c6ce7c06 | ||
|
3fa76a874f | ||
|
6e0fd6f257 | ||
|
c91d9b61c8 | ||
|
76eeb5aa18 | ||
|
843b5e33d6 |
20
CHANGELOG.md
Normal file
20
CHANGELOG.md
Normal file
@@ -0,0 +1,20 @@
|
||||
<a name="0.8.7"></a>
|
||||
## [0.8.7](https://github.com/libp2p/js-libp2p-crypto/compare/v0.8.6...v0.8.7) (2017-03-21)
|
||||
|
||||
|
||||
|
||||
<a name="0.8.6"></a>
|
||||
## [0.8.6](https://github.com/libp2p/js-libp2p-crypto/compare/v0.8.5...v0.8.6) (2017-03-03)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **package:** update tweetnacl to version 1.0.0-rc.1 ([4e56e17](https://github.com/libp2p/js-libp2p-crypto/commit/4e56e17))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **keys:** implement generateKeyPairFromSeed for ed25519 ([e5b7c1f](https://github.com/libp2p/js-libp2p-crypto/commit/e5b7c1f))
|
||||
|
||||
|
||||
|
22
README.md
22
README.md
@@ -107,9 +107,21 @@ Depending on the environment this is either an instance of [node-webcrypto-ossl]
|
||||
|
||||
### `keys`
|
||||
|
||||
#### Supported Key Types
|
||||
|
||||
The [`generateKeyPair`](#generatekeypairtype-bits-callback), [`marshalPublicKey`](#marshalpublickeykey-type-callback), 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.
|
||||
|
||||
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.
|
||||
|
||||
### `generateKeyPair(type, bits, callback)`
|
||||
|
||||
- `type: String`, only `'RSA'` is currently supported
|
||||
- `type: String`, see [Supported Key Types](#supported-key-types) above.
|
||||
- `bits: Number` Minimum of 1024
|
||||
- `callback: Function`
|
||||
|
||||
@@ -160,8 +172,8 @@ Calls back with an object of the form
|
||||
|
||||
### `marshalPublicKey(key[, type], callback)`
|
||||
|
||||
- `key: crypto.rsa.RsaPublicKey`
|
||||
- `type: String`, only `'RSA'` is currently supported
|
||||
- `key: keys.rsa.RsaPublicKey | keys.ed25519.Ed25519PublicKey | require('libp2p-crypto-secp256k1').Secp256k1PublicKey`
|
||||
- `type: String`, see [Supported Key Types](#supported-key-types) above.
|
||||
|
||||
Converts a public key object into a protobuf serialized public key.
|
||||
|
||||
@@ -173,8 +185,8 @@ Converts a protobuf serialized public key into its representative object.
|
||||
|
||||
### `marshalPrivateKey(key[, type])`
|
||||
|
||||
- `key: crypto.rsa.RsaPrivateKey`
|
||||
- `type: String`, only `'RSA'` is currently supported
|
||||
- `key: keys.rsa.RsaPrivateKey | keys.ed25519.Ed25519PrivateKey | require('libp2p-crypto-secp256k1').Secp256k1PrivateKey`
|
||||
- `type: String`, see [Supported Key Types](#supported-key-types) above.
|
||||
|
||||
Converts a private key object into a protobuf serialized private key.
|
||||
|
||||
|
39
package.json
39
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "libp2p-crypto",
|
||||
"version": "0.7.7",
|
||||
"version": "0.8.7",
|
||||
"description": "Crypto primitives for libp2p",
|
||||
"main": "src/index.js",
|
||||
"browser": {
|
||||
@@ -17,10 +17,10 @@
|
||||
"test": "npm run test:node && npm run test:no-webcrypto && npm run test:browser",
|
||||
"test:node": "aegir-test --env node",
|
||||
"test:no-webcrypto": "NO_WEBCRYPTO=true aegir-test --env node",
|
||||
"test:browser": "aegir-test --env browser --webworker",
|
||||
"release": "aegir-release --webworker",
|
||||
"release-minor": "aegir-release --type minor --webworker",
|
||||
"release-major": "aegir-release --type major --webworker",
|
||||
"test:browser": "aegir-test --env browser",
|
||||
"release": "aegir-release",
|
||||
"release-minor": "aegir-release --type minor",
|
||||
"release-major": "aegir-release --type major",
|
||||
"coverage": "aegir-coverage",
|
||||
"coverage-publish": "aegir-coverage publish"
|
||||
},
|
||||
@@ -34,50 +34,55 @@
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"asn1.js": "^4.9.1",
|
||||
"async": "^2.1.4",
|
||||
"async": "^2.1.5",
|
||||
"browserify-aes": "^1.0.6",
|
||||
"keypair": "^1.0.1",
|
||||
"multihashing-async": "^0.4.0",
|
||||
"nodeify": "^1.0.0",
|
||||
"libp2p-crypto-secp256k1": "^0.1.4",
|
||||
"multihashing-async": "~0.4.4",
|
||||
"nodeify": "^1.0.1",
|
||||
"pem-jwk": "^1.5.1",
|
||||
"protocol-buffers": "^3.2.1",
|
||||
"rsa-pem-to-jwk": "^1.1.3",
|
||||
"safe-buffer": "^5.0.1",
|
||||
"tweetnacl": "^0.14.5",
|
||||
"tweetnacl": "^1.0.0-rc.1",
|
||||
"webcrypto-shim": "github:dignifiedquire/webcrypto-shim#master"
|
||||
},
|
||||
"devDependencies": {
|
||||
"aegir": "^9.4.0",
|
||||
"aegir": "^11.0.0",
|
||||
"benchmark": "^2.1.3",
|
||||
"chai": "^3.5.0",
|
||||
"dirty-chai": "^1.2.2",
|
||||
"pre-commit": "^1.2.2"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"node-webcrypto-ossl": "^1.0.16"
|
||||
"node-webcrypto-ossl": "^1.0.21"
|
||||
},
|
||||
"pre-commit": [
|
||||
"lint",
|
||||
"test"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=4.0.0"
|
||||
"node": ">=4.0.0",
|
||||
"npm": ">=3.0.0"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/ipfs/js-libp2p-crypto.git"
|
||||
"url": "https://github.com/libp2p/js-libp2p-crypto.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/ipfs/js-libp2p-crypto/issues"
|
||||
"url": "https://github.com/libp2p/js-libp2p-crypto/issues"
|
||||
},
|
||||
"homepage": "https://github.com/ipfs/js-libp2p-crypto",
|
||||
"homepage": "https://github.com/libp2p/js-libp2p-crypto",
|
||||
"contributors": [
|
||||
"David Dias <daviddias.p@gmail.com>",
|
||||
"Dmitriy Ryajov <dryajov@gmail.com>",
|
||||
"Friedel Ziegelmayer <dignifiedquire@gmail.com>",
|
||||
"Greenkeeper <support@greenkeeper.io>",
|
||||
"Jack Kleeman <jackkleeman@gmail.com>",
|
||||
"Richard Littauer <richard.littauer@gmail.com>",
|
||||
"Tom Swindell <t.swindell@rubyx.co.uk>",
|
||||
"Yusef Napora <yusef@napora.org>",
|
||||
"dryajov <dryajov@gmail.com>",
|
||||
"greenkeeper[bot] <greenkeeper[bot]@users.noreply.github.com>",
|
||||
"greenkeeperio-bot <support@greenkeeper.io>",
|
||||
"nikuda <nikuda@gmail.com>"
|
||||
]
|
||||
}
|
@@ -3,6 +3,7 @@
|
||||
module.exports = `enum KeyType {
|
||||
RSA = 0;
|
||||
Ed25519 = 1;
|
||||
Secp256k1 = 2;
|
||||
}
|
||||
|
||||
message PublicKey {
|
||||
|
@@ -22,6 +22,22 @@ exports.generateKey = function (callback) {
|
||||
done(null, keys)
|
||||
}
|
||||
|
||||
// seed should be a 32 byte uint8array
|
||||
exports.generateKeyFromSeed = function (seed, callback) {
|
||||
const done = (err, res) => setImmediate(() => {
|
||||
callback(err, res)
|
||||
})
|
||||
|
||||
let keys
|
||||
try {
|
||||
keys = nacl.sign.keyPair.fromSeed(seed)
|
||||
} catch (err) {
|
||||
done(err)
|
||||
return
|
||||
}
|
||||
done(null, keys)
|
||||
}
|
||||
|
||||
exports.hashAndSign = function (key, msg, callback) {
|
||||
setImmediate(() => {
|
||||
callback(null, Buffer.from(nacl.sign.detached(msg, key)))
|
||||
|
@@ -3,12 +3,12 @@
|
||||
'use strict'
|
||||
|
||||
module.exports = function getWebCrypto () {
|
||||
if (typeof window !== 'undefined') {
|
||||
if (typeof self !== 'undefined') {
|
||||
// This is only a shim for interfaces, not for functionality
|
||||
require('webcrypto-shim')(window)
|
||||
require('webcrypto-shim')(self)
|
||||
|
||||
if (window.crypto) {
|
||||
return window.crypto
|
||||
if (self.crypto) {
|
||||
return self.crypto
|
||||
}
|
||||
}
|
||||
|
||||
|
36
src/index.js
36
src/index.js
@@ -5,12 +5,17 @@ const protobuf = require('protocol-buffers')
|
||||
const pbm = protobuf(require('./crypto.proto'))
|
||||
const c = require('./crypto')
|
||||
|
||||
exports.protobuf = pbm
|
||||
|
||||
exports.hmac = c.hmac
|
||||
exports.aes = c.aes
|
||||
exports.webcrypto = c.webcrypto
|
||||
|
||||
const keys = exports.keys = require('./keys')
|
||||
const KEY_TYPES = ['rsa', 'ed25519']
|
||||
function isValidKeyType (keyType) {
|
||||
const key = keys[keyType.toLowerCase()]
|
||||
return key !== undefined
|
||||
}
|
||||
|
||||
exports.keyStretcher = require('./key-stretcher')
|
||||
exports.generateEphemeralKeyPair = require('./ephemeral-keys')
|
||||
@@ -25,6 +30,19 @@ exports.generateKeyPair = (type, bits, cb) => {
|
||||
key.generateKeyPair(bits, cb)
|
||||
}
|
||||
|
||||
// Generates a keypair of the given type and bitsize
|
||||
// seed is a 32 byte uint8array
|
||||
exports.generateKeyPairFromSeed = (type, seed, bits, cb) => {
|
||||
let key = keys[type.toLowerCase()]
|
||||
if (!key) {
|
||||
return cb(new Error('invalid or unsupported key type'))
|
||||
}
|
||||
if (type.toLowerCase() !== 'ed25519') {
|
||||
return cb(new Error('Seed key derivation is unimplemented for RSA or secp256k1'))
|
||||
}
|
||||
key.generateKeyPairFromSeed(seed, bits, cb)
|
||||
}
|
||||
|
||||
// Converts a protobuf serialized public key into its
|
||||
// representative object
|
||||
exports.unmarshalPublicKey = (buf) => {
|
||||
@@ -35,6 +53,12 @@ exports.unmarshalPublicKey = (buf) => {
|
||||
return keys.rsa.unmarshalRsaPublicKey(decoded.Data)
|
||||
case pbm.KeyType.Ed25519:
|
||||
return keys.ed25519.unmarshalEd25519PublicKey(decoded.Data)
|
||||
case pbm.KeyType.Secp256k1:
|
||||
if (keys.secp256k1) {
|
||||
return keys.secp256k1.unmarshalSecp256k1PublicKey(decoded.Data)
|
||||
} else {
|
||||
throw new Error('secp256k1 support requires libp2p-crypto-secp256k1 package')
|
||||
}
|
||||
default:
|
||||
throw new Error('invalid or unsupported key type')
|
||||
}
|
||||
@@ -43,7 +67,7 @@ exports.unmarshalPublicKey = (buf) => {
|
||||
// Converts a public key object into a protobuf serialized public key
|
||||
exports.marshalPublicKey = (key, type) => {
|
||||
type = (type || 'rsa').toLowerCase()
|
||||
if (KEY_TYPES.indexOf(type) < 0) {
|
||||
if (!isValidKeyType(type)) {
|
||||
throw new Error('invalid or unsupported key type')
|
||||
}
|
||||
|
||||
@@ -60,6 +84,12 @@ exports.unmarshalPrivateKey = (buf, callback) => {
|
||||
return keys.rsa.unmarshalRsaPrivateKey(decoded.Data, callback)
|
||||
case pbm.KeyType.Ed25519:
|
||||
return keys.ed25519.unmarshalEd25519PrivateKey(decoded.Data, callback)
|
||||
case pbm.KeyType.Secp256k1:
|
||||
if (keys.secp256k1) {
|
||||
return keys.secp256k1.unmarshalSecp256k1PrivateKey(decoded.Data, callback)
|
||||
} else {
|
||||
return callback(new Error('secp256k1 support requires libp2p-crypto-secp256k1 package'))
|
||||
}
|
||||
default:
|
||||
callback(new Error('invalid or unsupported key type'))
|
||||
}
|
||||
@@ -68,7 +98,7 @@ exports.unmarshalPrivateKey = (buf, callback) => {
|
||||
// Converts a private key object into a protobuf serialized private key
|
||||
exports.marshalPrivateKey = (key, type) => {
|
||||
type = (type || 'rsa').toLowerCase()
|
||||
if (KEY_TYPES.indexOf(type) < 0) {
|
||||
if (!isValidKeyType(type)) {
|
||||
throw new Error('invalid or unsupported key type')
|
||||
}
|
||||
|
||||
|
@@ -117,6 +117,27 @@ function generateKeyPair (_bits, cb) {
|
||||
})
|
||||
}
|
||||
|
||||
function generateKeyPairFromSeed (seed, _bits, cb) {
|
||||
if (cb === undefined && typeof _bits === 'function') {
|
||||
cb = _bits
|
||||
}
|
||||
|
||||
crypto.generateKeyFromSeed(seed, (err, keys) => {
|
||||
if (err) {
|
||||
return cb(err)
|
||||
}
|
||||
let privkey
|
||||
try {
|
||||
privkey = new Ed25519PrivateKey(keys.secretKey, keys.publicKey)
|
||||
} catch (err) {
|
||||
cb(err)
|
||||
return
|
||||
}
|
||||
|
||||
cb(null, privkey)
|
||||
})
|
||||
}
|
||||
|
||||
function ensure (cb) {
|
||||
if (typeof cb !== 'function') {
|
||||
throw new Error('callback is required')
|
||||
@@ -138,5 +159,6 @@ module.exports = {
|
||||
Ed25519PrivateKey,
|
||||
unmarshalEd25519PrivateKey,
|
||||
unmarshalEd25519PublicKey,
|
||||
generateKeyPair
|
||||
generateKeyPair,
|
||||
generateKeyPairFromSeed
|
||||
}
|
||||
|
@@ -2,5 +2,6 @@
|
||||
|
||||
module.exports = {
|
||||
rsa: require('./rsa'),
|
||||
ed25519: require('./ed25519')
|
||||
ed25519: require('./ed25519'),
|
||||
secp256k1: require('libp2p-crypto-secp256k1')
|
||||
}
|
||||
|
@@ -2,7 +2,10 @@
|
||||
/* eslint-env mocha */
|
||||
'use strict'
|
||||
|
||||
const expect = require('chai').expect
|
||||
const chai = require('chai')
|
||||
const dirtyChai = require('dirty-chai')
|
||||
const expect = chai.expect
|
||||
chai.use(dirtyChai)
|
||||
const series = require('async/series')
|
||||
const Buffer = require('safe-buffer').Buffer
|
||||
|
||||
@@ -25,7 +28,7 @@ describe('AES-CTR', () => {
|
||||
iv.fill(1)
|
||||
|
||||
crypto.aes.create(key, iv, (err, cipher) => {
|
||||
expect(err).to.not.exist
|
||||
expect(err).to.not.exist()
|
||||
|
||||
series([
|
||||
encryptAndDecrypt(cipher),
|
||||
@@ -46,17 +49,17 @@ describe('AES-CTR', () => {
|
||||
iv.fill(1)
|
||||
|
||||
crypto.aes.create(key, iv, (err, cipher) => {
|
||||
expect(err).to.not.exist
|
||||
expect(err).to.not.exist()
|
||||
|
||||
series(fixtures[byte].inputs.map((rawIn, i) => (cb) => {
|
||||
const input = Buffer.from(rawIn)
|
||||
const output = Buffer.from(fixtures[byte].outputs[i])
|
||||
cipher.encrypt(input, (err, res) => {
|
||||
expect(err).to.not.exist
|
||||
expect(err).to.not.exist()
|
||||
expect(res).to.have.length(output.length)
|
||||
expect(res).to.be.eql(output)
|
||||
cipher.decrypt(res, (err, res) => {
|
||||
expect(err).to.not.exist
|
||||
expect(err).to.not.exist()
|
||||
expect(res).to.be.eql(input)
|
||||
cb()
|
||||
})
|
||||
@@ -79,17 +82,17 @@ describe('AES-CTR', () => {
|
||||
iv.fill(1)
|
||||
|
||||
crypto.aes.create(key, iv, (err, cipher) => {
|
||||
expect(err).to.not.exist
|
||||
expect(err).to.not.exist()
|
||||
|
||||
series(goFixtures[byte].inputs.map((rawIn, i) => (cb) => {
|
||||
const input = Buffer.from(rawIn)
|
||||
const output = Buffer.from(goFixtures[byte].outputs[i])
|
||||
cipher.encrypt(input, (err, res) => {
|
||||
expect(err).to.not.exist
|
||||
expect(err).to.not.exist()
|
||||
expect(res).to.have.length(output.length)
|
||||
expect(res).to.be.eql(output)
|
||||
cipher.decrypt(res, (err, res) => {
|
||||
expect(err).to.not.exist
|
||||
expect(err).to.not.exist()
|
||||
expect(res).to.be.eql(input)
|
||||
cb()
|
||||
})
|
||||
@@ -105,9 +108,9 @@ function encryptAndDecrypt (cipher) {
|
||||
data.fill(Math.ceil(Math.random() * 100))
|
||||
return (cb) => {
|
||||
cipher.encrypt(data, (err, res) => {
|
||||
expect(err).to.not.exist
|
||||
expect(err).to.not.exist()
|
||||
cipher.decrypt(res, (err, res) => {
|
||||
expect(err).to.not.exist
|
||||
expect(err).to.not.exist()
|
||||
expect(res).to.be.eql(data)
|
||||
cb()
|
||||
})
|
||||
|
@@ -1,7 +1,10 @@
|
||||
/* eslint-env mocha */
|
||||
'use strict'
|
||||
|
||||
const expect = require('chai').expect
|
||||
const chai = require('chai')
|
||||
const dirtyChai = require('dirty-chai')
|
||||
const expect = chai.expect
|
||||
chai.use(dirtyChai)
|
||||
const Buffer = require('safe-buffer').Buffer
|
||||
|
||||
const crypto = require('../src')
|
||||
@@ -35,6 +38,70 @@ describe('ed25519', () => {
|
||||
})
|
||||
})
|
||||
|
||||
it('generates a valid key from seed', (done) => {
|
||||
var seed = crypto.randomBytes(32)
|
||||
crypto.generateKeyPairFromSeed('Ed25519', seed, 512, (err, seededkey) => {
|
||||
if (err) return done(err)
|
||||
expect(
|
||||
seededkey
|
||||
).to.be.an.instanceof(
|
||||
ed25519.Ed25519PrivateKey
|
||||
)
|
||||
|
||||
seededkey.hash((err, digest) => {
|
||||
if (err) {
|
||||
return done(err)
|
||||
}
|
||||
|
||||
expect(digest).to.have.length(34)
|
||||
done()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it('generates the same key from the same seed', (done) => {
|
||||
var seed = crypto.randomBytes(32)
|
||||
crypto.generateKeyPairFromSeed('Ed25519', seed, 512, (err, seededkey1) => {
|
||||
if (err) return done(err)
|
||||
crypto.generateKeyPairFromSeed('Ed25519', seed, 512, (err, seededkey2) => {
|
||||
if (err) return done(err)
|
||||
expect(
|
||||
seededkey1.equals(seededkey2)
|
||||
).to.be.eql(
|
||||
true
|
||||
)
|
||||
expect(
|
||||
seededkey1.public.equals(seededkey2.public)
|
||||
).to.be.eql(
|
||||
true
|
||||
)
|
||||
done()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it('generates different keys for different seeds', (done) => {
|
||||
var seed1 = crypto.randomBytes(32)
|
||||
crypto.generateKeyPairFromSeed('Ed25519', seed1, 512, (err, seededkey1) => {
|
||||
if (err) return done(err)
|
||||
var seed2 = crypto.randomBytes(32)
|
||||
crypto.generateKeyPairFromSeed('Ed25519', seed2, 512, (err, seededkey2) => {
|
||||
if (err) return done(err)
|
||||
expect(
|
||||
seededkey1.equals(seededkey2)
|
||||
).to.be.eql(
|
||||
false
|
||||
)
|
||||
expect(
|
||||
seededkey1.public.equals(seededkey2.public)
|
||||
).to.be.eql(
|
||||
false
|
||||
)
|
||||
done()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it('signs', (done) => {
|
||||
const text = crypto.randomBytes(512)
|
||||
|
||||
@@ -167,7 +234,7 @@ describe('ed25519', () => {
|
||||
let privateKey
|
||||
before((done) => {
|
||||
crypto.unmarshalPrivateKey(fixtures.verify.privateKey, (err, key) => {
|
||||
expect(err).to.not.exist
|
||||
expect(err).to.not.exist()
|
||||
privateKey = key
|
||||
done()
|
||||
})
|
||||
@@ -178,7 +245,7 @@ describe('ed25519', () => {
|
||||
|
||||
key.verify(fixtures.verify.data, fixtures.verify.signature, (err, ok) => {
|
||||
if (err) throw err
|
||||
expect(err).to.not.exist
|
||||
expect(err).to.not.exist()
|
||||
expect(ok).to.be.eql(true)
|
||||
done()
|
||||
})
|
||||
@@ -186,7 +253,7 @@ describe('ed25519', () => {
|
||||
|
||||
it('generates the same signature as go', (done) => {
|
||||
privateKey.sign(fixtures.verify.data, (err, sig) => {
|
||||
expect(err).to.not.exist
|
||||
expect(err).to.not.exist()
|
||||
expect(sig).to.deep.equal(fixtures.verify.signature)
|
||||
done()
|
||||
})
|
||||
|
@@ -2,7 +2,10 @@
|
||||
/* eslint-env mocha */
|
||||
'use strict'
|
||||
|
||||
const expect = require('chai').expect
|
||||
const chai = require('chai')
|
||||
const dirtyChai = require('dirty-chai')
|
||||
const expect = chai.expect
|
||||
chai.use(dirtyChai)
|
||||
const parallel = require('async/parallel')
|
||||
|
||||
const fixtures = require('./fixtures/go-elliptic-key')
|
||||
@@ -27,12 +30,12 @@ describe('generateEphemeralKeyPair', () => {
|
||||
(cb) => crypto.generateEphemeralKeyPair(curve, cb),
|
||||
(cb) => crypto.generateEphemeralKeyPair(curve, cb)
|
||||
], (err, keys) => {
|
||||
expect(err).to.not.exist
|
||||
expect(err).to.not.exist()
|
||||
expect(keys[0].key).to.have.length(lengths[curve])
|
||||
expect(keys[1].key).to.have.length(lengths[curve])
|
||||
|
||||
keys[0].genSharedKey(keys[1].key, (err, shared) => {
|
||||
expect(err).to.not.exist
|
||||
expect(err).to.not.exist()
|
||||
expect(shared).to.have.length(secretLengths[curve])
|
||||
done()
|
||||
})
|
||||
@@ -48,7 +51,7 @@ describe('generateEphemeralKeyPair', () => {
|
||||
(cb) => crypto.generateEphemeralKeyPair(curve, cb),
|
||||
(cb) => crypto.generateEphemeralKeyPair(curve, cb)
|
||||
], (err, res) => {
|
||||
expect(err).to.not.exist
|
||||
expect(err).to.not.exist()
|
||||
const alice = res[0]
|
||||
const bob = res[1]
|
||||
bob.key = fixtures.bob.public
|
||||
@@ -57,7 +60,7 @@ describe('generateEphemeralKeyPair', () => {
|
||||
(cb) => alice.genSharedKey(bob.key, cb),
|
||||
(cb) => bob.genSharedKey(alice.key, fixtures.bob, cb)
|
||||
], (err, secrets) => {
|
||||
expect(err).to.not.exist
|
||||
expect(err).to.not.exist()
|
||||
|
||||
expect(
|
||||
secrets[0]
|
||||
|
11
test/fixtures/secp256k1.js
vendored
Normal file
11
test/fixtures/secp256k1.js
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
'use strict'
|
||||
|
||||
const Buffer = require('safe-buffer').Buffer
|
||||
|
||||
module.exports = {
|
||||
|
||||
// protobuf marshaled key pair generated with libp2p-crypto-secp256k1
|
||||
// and marshaled with libp2p-crypto.marshalPublicKey / marshalPrivateKey
|
||||
pbmPrivateKey: Buffer.from('08021220e0600103010000000100000000000000be1dc82c2e000000e8d6030301000000', 'hex'),
|
||||
pbmPublicKey: Buffer.from('0802122103a9a7272a726fa083abf31ba44037f8347fbc5e5d3113d62a7c6bc26752fd8ee1', 'hex')
|
||||
}
|
@@ -3,7 +3,10 @@
|
||||
'use strict'
|
||||
|
||||
const Buffer = require('safe-buffer').Buffer
|
||||
const expect = require('chai').expect
|
||||
const chai = require('chai')
|
||||
const dirtyChai = require('dirty-chai')
|
||||
const expect = chai.expect
|
||||
chai.use(dirtyChai)
|
||||
|
||||
const crypto = require('../src')
|
||||
|
||||
@@ -13,10 +16,10 @@ describe('HMAC', () => {
|
||||
hashes.forEach((hash) => {
|
||||
it(`${hash} - sign and verify`, (done) => {
|
||||
crypto.hmac.create(hash, Buffer.from('secret'), (err, hmac) => {
|
||||
expect(err).to.not.exist
|
||||
expect(err).to.not.exist()
|
||||
|
||||
hmac.digest(Buffer.from('hello world'), (err, sig) => {
|
||||
expect(err).to.not.exist
|
||||
expect(err).to.not.exist()
|
||||
expect(sig).to.have.length(hmac.length)
|
||||
done()
|
||||
})
|
||||
|
@@ -2,8 +2,10 @@
|
||||
/* eslint-env mocha */
|
||||
'use strict'
|
||||
|
||||
const expect = require('chai').expect
|
||||
|
||||
const chai = require('chai')
|
||||
const dirtyChai = require('dirty-chai')
|
||||
const expect = chai.expect
|
||||
chai.use(dirtyChai)
|
||||
const crypto = require('../src')
|
||||
const fixtures = require('./fixtures/go-key-rsa')
|
||||
|
||||
@@ -23,9 +25,17 @@ describe('libp2p-crypto', () => {
|
||||
const key2 = crypto.unmarshalPublicKey(crypto.marshalPublicKey(key.public))
|
||||
|
||||
expect(key2.equals(key.public)).to.be.eql(true)
|
||||
|
||||
expect(() => {
|
||||
crypto.marshalPublicKey(key.public, 'invalid-key-type')
|
||||
}).to.throw()
|
||||
})
|
||||
|
||||
it('marshalPrivateKey and unmarshalPrivateKey', (done) => {
|
||||
expect(() => {
|
||||
crypto.marshalPrivateKey(key, 'invalid-key-type')
|
||||
}).to.throw()
|
||||
|
||||
crypto.unmarshalPrivateKey(crypto.marshalPrivateKey(key), (err, key2) => {
|
||||
if (err) {
|
||||
return done(err)
|
||||
@@ -103,7 +113,7 @@ describe('libp2p-crypto', () => {
|
||||
it('throws with no number passed', () => {
|
||||
expect(() => {
|
||||
crypto.randomBytes()
|
||||
}).to.throw
|
||||
}).to.throw()
|
||||
})
|
||||
|
||||
it('generates different random things', () => {
|
||||
|
@@ -2,8 +2,10 @@
|
||||
/* eslint-env mocha */
|
||||
'use strict'
|
||||
|
||||
const expect = require('chai').expect
|
||||
|
||||
const chai = require('chai')
|
||||
const dirtyChai = require('dirty-chai')
|
||||
const expect = chai.expect
|
||||
chai.use(dirtyChai)
|
||||
const crypto = require('../src')
|
||||
const fixtures = require('./fixtures/go-stretch-key')
|
||||
|
||||
@@ -39,8 +41,8 @@ describe('keyStretcher', () => {
|
||||
return done(err)
|
||||
}
|
||||
|
||||
expect(keys.k1).to.exist
|
||||
expect(keys.k2).to.exist
|
||||
expect(keys.k1).to.exist()
|
||||
expect(keys.k2).to.exist()
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
@@ -1,7 +1,10 @@
|
||||
/* eslint-env mocha */
|
||||
'use strict'
|
||||
|
||||
const expect = require('chai').expect
|
||||
const chai = require('chai')
|
||||
const dirtyChai = require('dirty-chai')
|
||||
const expect = chai.expect
|
||||
chai.use(dirtyChai)
|
||||
const Buffer = require('safe-buffer').Buffer
|
||||
|
||||
const crypto = require('../src')
|
||||
@@ -169,8 +172,8 @@ describe('RSA', () => {
|
||||
|
||||
key.verify(fixtures.verify.data, fixtures.verify.signature, (err, ok) => {
|
||||
if (err) throw err
|
||||
expect(err).to.not.exist
|
||||
expect(ok).to.be.eql(true)
|
||||
expect(err).to.not.exist()
|
||||
expect(ok).to.equal(true)
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
107
test/secp256k1.spec.js
Normal file
107
test/secp256k1.spec.js
Normal file
@@ -0,0 +1,107 @@
|
||||
/* eslint-env mocha */
|
||||
'use strict'
|
||||
|
||||
const chai = require('chai')
|
||||
const dirtyChai = require('dirty-chai')
|
||||
const expect = chai.expect
|
||||
chai.use(dirtyChai)
|
||||
const fixtures = require('./fixtures/secp256k1')
|
||||
const crypto = require('../src')
|
||||
|
||||
const mockPublicKey = {
|
||||
bytes: fixtures.pbmPublicKey
|
||||
}
|
||||
|
||||
const mockPrivateKey = {
|
||||
bytes: fixtures.pbmPrivateKey,
|
||||
public: mockPublicKey
|
||||
}
|
||||
|
||||
const mockSecp256k1Module = {
|
||||
generateKeyPair (bits, callback) {
|
||||
callback(null, mockPrivateKey)
|
||||
},
|
||||
|
||||
unmarshalSecp256k1PrivateKey (buf, callback) {
|
||||
callback(null, mockPrivateKey)
|
||||
},
|
||||
|
||||
unmarshalSecp256k1PublicKey (buf) {
|
||||
return mockPublicKey
|
||||
}
|
||||
}
|
||||
|
||||
describe('with libp2p-crypto-secp256k1 module present', () => {
|
||||
let key
|
||||
|
||||
before((done) => {
|
||||
crypto.keys['secp256k1'] = mockSecp256k1Module
|
||||
crypto.generateKeyPair('secp256k1', 256, (err, _key) => {
|
||||
if (err) return done(err)
|
||||
key = _key
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
after((done) => {
|
||||
delete crypto.keys['secp256k1']
|
||||
done()
|
||||
})
|
||||
|
||||
it('generates a valid key', (done) => {
|
||||
expect(
|
||||
key
|
||||
).to.exist()
|
||||
done()
|
||||
})
|
||||
|
||||
it('protobuf encoding', (done) => {
|
||||
const keyMarshal = crypto.marshalPrivateKey(key)
|
||||
crypto.unmarshalPrivateKey(keyMarshal, (err, key2) => {
|
||||
if (err) return done(err)
|
||||
const keyMarshal2 = crypto.marshalPrivateKey(key2)
|
||||
|
||||
expect(
|
||||
keyMarshal
|
||||
).to.be.eql(
|
||||
keyMarshal2
|
||||
)
|
||||
|
||||
const pk = key.public
|
||||
const pkMarshal = crypto.marshalPublicKey(pk)
|
||||
const pk2 = crypto.unmarshalPublicKey(pkMarshal)
|
||||
const pkMarshal2 = crypto.marshalPublicKey(pk2)
|
||||
|
||||
expect(
|
||||
pkMarshal
|
||||
).to.be.eql(
|
||||
pkMarshal2
|
||||
)
|
||||
done()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('without libp2p-crypto-secp256k1 module present', () => {
|
||||
it('fails to generate a secp256k1 key', (done) => {
|
||||
crypto.generateKeyPair('secp256k1', 256, (err, key) => {
|
||||
expect(err).to.exist()
|
||||
expect(key).to.not.exist()
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it('fails to unmarshal a secp256k1 private key', (done) => {
|
||||
crypto.unmarshalPrivateKey(fixtures.pbmPrivateKey, (err, key) => {
|
||||
expect(err).to.exist()
|
||||
expect(key).to.not.exist()
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it('fails to unmarshal a secp256k1 public key', () => {
|
||||
expect(() => {
|
||||
crypto.unmarshalPublicKey(fixtures.pbmPublicKey)
|
||||
}).to.throw(Error)
|
||||
})
|
||||
})
|
@@ -2,7 +2,11 @@
|
||||
/* eslint-env mocha */
|
||||
'use strict'
|
||||
|
||||
const expect = require('chai').expect
|
||||
const chai = require('chai')
|
||||
const dirtyChai = require('dirty-chai')
|
||||
const expect = chai.expect
|
||||
chai.use(dirtyChai)
|
||||
|
||||
const util = require('../src/crypto/util')
|
||||
const BN = require('bn.js')
|
||||
|
||||
|
Reference in New Issue
Block a user