js-libp2p-crypto/test/secp256k1.spec.js

269 lines
8.1 KiB
JavaScript
Raw Normal View History

2017-02-09 06:35:39 -05:00
/* eslint-env mocha */
'use strict'
const chai = require('chai')
const dirtyChai = require('dirty-chai')
const expect = chai.expect
chai.use(dirtyChai)
2017-02-09 06:35:39 -05:00
const libp2pCrypto = require('libp2p-crypto')
2017-07-22 13:31:42 -07:00
const keysPBM = libp2pCrypto.keys.keysPBM
2017-02-09 06:35:39 -05:00
const randomBytes = libp2pCrypto.randomBytes
2017-07-22 13:31:42 -07:00
const crypto = require('../src/crypto')(randomBytes)
2017-02-09 06:35:39 -05:00
describe('secp256k1 keys', () => {
let key
2017-07-22 13:31:42 -07:00
const secp256k1 = require('../src')(keysPBM, randomBytes)
before(async () => {
key = await secp256k1.generateKeyPair()
2017-02-09 06:35:39 -05:00
})
it('generates a valid key', async () => {
expect(key).to.be.an.instanceof(secp256k1.Secp256k1PrivateKey)
expect(key.public).to.be.an.instanceof(secp256k1.Secp256k1PublicKey)
2017-02-09 06:35:39 -05:00
const digest = await key.hash()
expect(digest).to.have.length(34)
2017-02-09 06:35:39 -05:00
const publicDigest = await key.public.hash()
expect(publicDigest).to.have.length(34)
2017-02-09 06:35:39 -05:00
})
it('optionally accepts a `bits` argument when generating a key', async () => {
const _key = await secp256k1.generateKeyPair(256)
expect(_key).to.be.an.instanceof(secp256k1.Secp256k1PrivateKey)
2017-02-09 06:35:39 -05:00
})
it('signs', async () => {
2017-02-09 06:35:39 -05:00
const text = randomBytes(512)
const sig = await key.sign(text)
const res = await key.public.verify(text, sig)
expect(res).to.equal(true)
2017-02-09 06:35:39 -05:00
})
it('encoding', async () => {
2017-02-09 06:35:39 -05:00
const keyMarshal = key.marshal()
const key2 = await secp256k1.unmarshalSecp256k1PrivateKey(keyMarshal)
const keyMarshal2 = key2.marshal()
2017-02-09 06:35:39 -05:00
expect(keyMarshal).to.eql(keyMarshal2)
2017-02-09 06:35:39 -05:00
const pk = key.public
const pkMarshal = pk.marshal()
const pk2 = secp256k1.unmarshalSecp256k1PublicKey(pkMarshal)
const pkMarshal2 = pk2.marshal()
2017-02-09 06:35:39 -05:00
expect(pkMarshal).to.eql(pkMarshal2)
2017-02-09 06:35:39 -05:00
})
it('key id', async () => {
const id = await key.id()
expect(id).to.exist()
expect(id).to.be.a('string')
})
2017-02-09 06:35:39 -05:00
describe('key equals', () => {
it('equals itself', () => {
expect(key.equals(key)).to.eql(true)
expect(key.public.equals(key.public)).to.eql(true)
2017-02-09 06:35:39 -05:00
})
it('not equals other key', async () => {
const key2 = await secp256k1.generateKeyPair(256)
expect(key.equals(key2)).to.eql(false)
expect(key2.equals(key)).to.eql(false)
expect(key.public.equals(key2.public)).to.eql(false)
expect(key2.public.equals(key.public)).to.eql(false)
2017-02-09 06:35:39 -05:00
})
})
it('sign and verify', async () => {
2017-02-09 06:35:39 -05:00
const data = Buffer.from('hello world')
const sig = await key.sign(data)
const valid = await key.public.verify(data, sig)
expect(valid).to.eql(true)
2017-02-09 06:35:39 -05:00
})
it('fails to verify for different data', async () => {
2017-02-09 06:35:39 -05:00
const data = Buffer.from('hello world')
const sig = await key.sign(data)
const valid = await key.public.verify(Buffer.from('hello'), sig)
expect(valid).to.eql(false)
2017-02-09 06:35:39 -05:00
})
})
describe('key generation error', () => {
let generateKey
2017-07-22 13:31:42 -07:00
let secp256k1
2017-02-09 06:35:39 -05:00
before(() => {
2017-02-09 06:35:39 -05:00
generateKey = crypto.generateKey
crypto.generateKey = () => { throw new Error('Error generating key') }
2017-07-22 13:31:42 -07:00
secp256k1 = require('../src')(keysPBM, randomBytes, crypto)
2017-02-09 06:35:39 -05:00
})
after(() => {
2017-02-09 06:35:39 -05:00
crypto.generateKey = generateKey
})
it('returns an error if key generation fails', async () => {
try {
await secp256k1.generateKeyPair()
} catch (err) {
return expect(err.message).to.equal('Error generating key')
}
throw new Error('Expected error to be thrown')
2017-02-09 06:35:39 -05:00
})
})
describe('handles generation of invalid key', () => {
let generateKey
2017-07-22 13:31:42 -07:00
let secp256k1
2017-02-09 06:35:39 -05:00
before(() => {
2017-02-09 06:35:39 -05:00
generateKey = crypto.generateKey
crypto.generateKey = () => Buffer.from('not a real key')
2017-07-22 13:31:42 -07:00
secp256k1 = require('../src')(keysPBM, randomBytes, crypto)
2017-02-09 06:35:39 -05:00
})
after(() => {
2017-02-09 06:35:39 -05:00
crypto.generateKey = generateKey
})
it('returns an error if key generator returns an invalid key', async () => {
try {
await secp256k1.generateKeyPair()
} catch (err) {
return expect(err.message).to.equal('Invalid private key')
}
throw new Error('Expected error to be thrown')
2017-02-09 06:35:39 -05:00
})
})
describe('crypto functions', () => {
let privKey
let pubKey
2017-02-09 06:35:39 -05:00
before(async () => {
privKey = await crypto.generateKey()
pubKey = crypto.computePublicKey(privKey)
2017-02-09 06:35:39 -05:00
})
it('generates valid keys', () => {
2017-02-09 06:35:39 -05:00
expect(() => {
crypto.validatePrivateKey(privKey)
crypto.validatePublicKey(pubKey)
}).to.not.throw()
})
it('does not validate an invalid key', () => {
expect(() => crypto.validatePublicKey(Buffer.from('42'))).to.throw()
expect(() => crypto.validatePrivateKey(Buffer.from('42'))).to.throw()
2017-02-09 06:35:39 -05:00
})
it('validates a correct signature', async () => {
const sig = await crypto.hashAndSign(privKey, Buffer.from('hello'))
const valid = await crypto.hashAndVerify(pubKey, sig, Buffer.from('hello'))
expect(valid).to.equal(true)
2017-02-09 06:35:39 -05:00
})
it('errors if given a null buffer to sign', async () => {
try {
await crypto.hashAndSign(privKey, null)
} catch (err) {
return // expected
}
throw new Error('Expected error to be thrown')
2017-02-09 06:35:39 -05:00
})
it('errors when signing with an invalid key', async () => {
try {
await crypto.hashAndSign(Buffer.from('42'), Buffer.from('Hello'))
} catch (err) {
return expect(err.message).to.equal('private key length is invalid')
}
throw new Error('Expected error to be thrown')
2017-02-09 06:35:39 -05:00
})
it('errors if given a null buffer to validate', async () => {
const sig = await crypto.hashAndSign(privKey, Buffer.from('hello'))
2017-02-09 06:35:39 -05:00
try {
await crypto.hashAndVerify(privKey, sig, null)
} catch (err) {
return // expected
}
throw new Error('Expected error to be thrown')
2017-02-09 06:35:39 -05:00
})
it('errors when validating a message with an invalid signature', async () => {
try {
await crypto.hashAndVerify(pubKey, Buffer.from('invalid-sig'), Buffer.from('hello'))
} catch (err) {
return expect(err.message).to.equal('couldn\'t parse DER signature')
}
throw new Error('Expected error to be thrown')
2017-02-09 06:35:39 -05:00
})
it('errors when signing with an invalid key', async () => {
try {
await crypto.hashAndSign(Buffer.from('42'), Buffer.from('Hello'))
} catch (err) {
return expect(err.message).to.equal('private key length is invalid')
}
throw new Error('Expected error to be thrown')
2017-02-09 06:35:39 -05:00
})
it('throws when compressing an invalid public key', () => {
expect(() => crypto.compressPublicKey(Buffer.from('42'))).to.throw()
2017-02-09 06:35:39 -05:00
})
it('throws when decompressing an invalid public key', () => {
expect(() => crypto.decompressPublicKey(Buffer.from('42'))).to.throw()
2017-02-09 06:35:39 -05:00
})
it('compresses/decompresses a valid public key', () => {
2017-02-09 06:35:39 -05:00
const decompressed = crypto.decompressPublicKey(pubKey)
expect(decompressed).to.exist()
2017-02-09 06:35:39 -05:00
expect(decompressed.length).to.be.eql(65)
const recompressed = crypto.compressPublicKey(decompressed)
expect(recompressed).to.eql(pubKey)
2017-02-09 06:35:39 -05:00
})
})
describe('go interop', () => {
2017-07-22 13:31:42 -07:00
const secp256k1 = require('../src')(keysPBM, randomBytes)
2017-02-09 06:35:39 -05:00
const fixtures = require('./fixtures/go-interop')
it('loads a private key marshaled by go-libp2p-crypto', async () => {
2017-02-09 06:35:39 -05:00
// we need to first extract the key data from the protobuf, which is
// normally handled by js-libp2p-crypto
2017-07-22 13:31:42 -07:00
const decoded = keysPBM.PrivateKey.decode(fixtures.privateKey)
expect(decoded.Type).to.eql(keysPBM.KeyType.Secp256k1)
2017-02-09 06:35:39 -05:00
const key = await secp256k1.unmarshalSecp256k1PrivateKey(decoded.Data)
expect(key).to.be.an.instanceof(secp256k1.Secp256k1PrivateKey)
expect(key.bytes).to.eql(fixtures.privateKey)
2017-02-09 06:35:39 -05:00
})
it('loads a public key marshaled by go-libp2p-crypto', () => {
2017-07-22 13:31:42 -07:00
const decoded = keysPBM.PublicKey.decode(fixtures.publicKey)
expect(decoded.Type).to.be.eql(keysPBM.KeyType.Secp256k1)
2017-02-09 06:35:39 -05:00
const key = secp256k1.unmarshalSecp256k1PublicKey(decoded.Data)
expect(key).to.be.an.instanceof(secp256k1.Secp256k1PublicKey)
expect(key.bytes).to.eql(fixtures.publicKey)
2017-02-09 06:35:39 -05:00
})
it('generates the same signature as go-libp2p-crypto', async () => {
2017-07-22 13:31:42 -07:00
const decoded = keysPBM.PrivateKey.decode(fixtures.privateKey)
expect(decoded.Type).to.eql(keysPBM.KeyType.Secp256k1)
2017-02-09 06:35:39 -05:00
const key = await secp256k1.unmarshalSecp256k1PrivateKey(decoded.Data)
const sig = await key.sign(fixtures.message)
expect(sig).to.eql(fixtures.signature)
2017-02-09 06:35:39 -05:00
})
})