feat: add marshal and unmarshl methods

This commit is contained in:
dignifiedquire 2016-05-19 21:45:43 +02:00
parent f3a22ea5ff
commit ca0b5305a2
5 changed files with 230 additions and 110 deletions

View File

@ -24,3 +24,31 @@ needed for libp2p. This is based on this [go implementation](https://github.com/
- `type: String`, only `'RSA'` is currently supported - `type: String`, only `'RSA'` is currently supported
- `bits: Number` - `bits: Number`
- `cb: Function`, with the signature `function (err, privateKey)` - `cb: Function`, with the signature `function (err, privateKey)`
Generates a keypair of the given type and bitsize.
### `marshalPublicKey(key[, type])`
- `key: crypto.rsa.RsaPublicKey`
- `type: String`, only `'RSA'` is currently supported
Converts a public key object into a protobuf serialized public key.
### `unmarshalPublicKey(buf)`
- `buf: Buffer`
Converts a protobuf serialized public key into its representative object.
### `marshalPrivateKey(key[, type])`
- `key: crypto.rsa.RsaPrivateKey`
- `type: String`, only `'RSA'` is currently supported
Converts a private key object into a protobuf serialized private key.
### `unmarshalPrivateKey(buf)`
- `buf: Buffer`
Converts a protobuf serialized private key into its representative object.

View File

@ -1,5 +1,10 @@
'use strict' 'use strict'
const protobuf = require('protocol-buffers')
const fs = require('fs')
const path = require('path')
const pbm = protobuf(fs.readFileSync(path.join(__dirname, './crypto.proto')))
exports.utils = require('./utils') exports.utils = require('./utils')
const keys = exports.keys = require('./keys') const keys = exports.keys = require('./keys')
@ -26,3 +31,59 @@ exports.generateEphemeralKeyPair = (curveName, cb) => {
exports.keyStretcher = (cipherType, hashType, secret) => { exports.keyStretcher = (cipherType, hashType, secret) => {
throw new Error('Not implemented') throw new Error('Not implemented')
} }
// Converts a protobuf serialized public key into its
// representative object
exports.unmarshalPublicKey = (buf) => {
const decoded = pbm.PublicKey.decode(buf)
switch (decoded.Type) {
case pbm.KeyType.RSA:
return keys.rsa.unmarshalRsaPublicKey(decoded.Data)
default:
throw new Error('invalid or unsupported key type')
}
}
// Converts a public key object into a protobuf serialized public key
exports.marshalPublicKey = (key, type) => {
type = (type || 'rsa').toLowerCase()
// for now only rsa is supported
if (type !== 'rsa') {
throw new Error('invalid or unsupported key type')
}
return pbm.PublicKey.encode({
Type: pbm.KeyType.RSA,
Data: key.marshal()
})
}
// Converts a protobuf serialized private key into its
// representative object
exports.unmarshalPrivateKey = (buf) => {
const decoded = pbm.PrivateKey.decode(buf)
switch (decoded.Type) {
case pbm.KeyType.RSA:
return keys.rsa.unmarshalRsaPrivateKey(decoded.Data)
default:
throw new Error('invalid or unsupported key type')
}
}
// Converts a private key object into a protobuf serialized private key
exports.marshalPrivateKey = (key, type) => {
type = (type || 'rsa').toLowerCase()
// for now only rsa is supported
if (type !== 'rsa') {
throw new Error('invalid or unsupported key type')
}
return pbm.PrivateKey.encode({
Type: pbm.KeyType.RSA,
Data: key.marshal()
})
}

View File

@ -25,7 +25,7 @@ class RsaPublicKey {
} }
marshal () { marshal () {
return forge.asn1.toDer(pki.publicKeyToAsn1(this._key)).bytes() return new Buffer(forge.asn1.toDer(pki.publicKeyToAsn1(this._key)).bytes(), 'binary')
} }
get bytes () { get bytes () {
@ -74,7 +74,7 @@ class RsaPrivateKey {
} }
marshal () { marshal () {
return forge.asn1.toDer(pki.privateKeyToAsn1(this._privateKey)).bytes() return new Buffer(forge.asn1.toDer(pki.privateKeyToAsn1(this._privateKey)).bytes(), 'binary')
} }
get bytes () { get bytes () {
@ -94,12 +94,18 @@ class RsaPrivateKey {
} }
function unmarshalRsaPrivateKey (bytes) { function unmarshalRsaPrivateKey (bytes) {
if (Buffer.isBuffer(bytes)) {
bytes = forge.util.createBuffer(bytes.toString('binary'))
}
const key = pki.privateKeyFromAsn1(forge.asn1.fromDer(bytes)) const key = pki.privateKeyFromAsn1(forge.asn1.fromDer(bytes))
return new RsaPrivateKey(key) return new RsaPrivateKey(key)
} }
function unmarshalRsaPublicKey (bytes) { function unmarshalRsaPublicKey (bytes) {
if (Buffer.isBuffer(bytes)) {
bytes = forge.util.createBuffer(bytes.toString('binary'))
}
const key = pki.publicKeyFromAsn1(forge.asn1.fromDer(bytes)) const key = pki.publicKeyFromAsn1(forge.asn1.fromDer(bytes))
return new RsaPublicKey(key) return new RsaPublicKey(key)

View File

@ -4,116 +4,26 @@
const expect = require('chai').expect const expect = require('chai').expect
const crypto = require('../src') const crypto = require('../src')
const rsa = crypto.keys.rsa
describe('libp2p-crypto', () => { describe('libp2p-crypto', () => {
describe('generateKeyPair', () => { let key
describe('RSA', () => { before((done) => {
let key crypto.generateKeyPair('RSA', 2048, (err, _key) => {
before((done) => { if (err) return done(err)
crypto.generateKeyPair('RSA', 2048, (err, _key) => { key = _key
if (err) return done(err) done()
key = _key
done()
})
})
it('generates a valid key', () => {
expect(
key
).to.be.an.instanceof(
rsa.RsaPrivateKey
)
expect(
key.hash()
).to.have.length(
34
)
})
it('signs', () => {
const pk = key.public
const text = key.genSecret()
const sig = key.sign(text)
expect(
pk.verify(text, sig)
).to.be.eql(
true
)
})
it('encoding', () => {
const keyMarshal = key.marshal()
const key2 = rsa.unmarshalRsaPrivateKey(keyMarshal)
const keyMarshal2 = key2.marshal()
expect(
keyMarshal
).to.be.eql(
keyMarshal2
)
const pk = key.public
const pkMarshal = pk.marshal()
const pk2 = rsa.unmarshalRsaPublicKey(pkMarshal)
const pkMarshal2 = pk2.marshal()
expect(
pkMarshal
).to.be.eql(
pkMarshal2
)
})
describe('key equals', () => {
it('equals itself', () => {
expect(
key.equals(key)
).to.be.eql(
true
)
expect(
key.public.equals(key.public)
).to.be.eql(
true
)
})
it('not equals other key', (done) => {
crypto.generateKeyPair('RSA', 2048, (err, key2) => {
if (err) return done(err)
expect(
key.equals(key2)
).to.be.eql(
false
)
expect(
key2.equals(key)
).to.be.eql(
false
)
expect(
key.public.equals(key2.public)
).to.be.eql(
false
)
expect(
key2.public.equals(key.public)
).to.be.eql(
false
)
done()
})
})
})
}) })
}) })
it('marshalPublicKey and unmarshalPublicKey', () => {
const key2 = crypto.unmarshalPublicKey(crypto.marshalPublicKey(key.public))
expect(key2.equals(key.public)).to.be.eql(true)
})
it('marshalPrivateKey and unmarshalPrivateKey', () => {
const key2 = crypto.unmarshalPrivateKey(crypto.marshalPrivateKey(key))
expect(key2.equals(key)).to.be.eql(true)
})
}) })

115
test/rsa.spec.js Normal file
View File

@ -0,0 +1,115 @@
/* eslint-env mocha */
'use strict'
const expect = require('chai').expect
const crypto = require('../src')
const rsa = crypto.keys.rsa
describe('RSA', () => {
let key
before((done) => {
crypto.generateKeyPair('RSA', 2048, (err, _key) => {
if (err) return done(err)
key = _key
done()
})
})
it('generates a valid key', () => {
expect(
key
).to.be.an.instanceof(
rsa.RsaPrivateKey
)
expect(
key.hash()
).to.have.length(
34
)
})
it('signs', () => {
const pk = key.public
const text = key.genSecret()
const sig = key.sign(text)
expect(
pk.verify(text, sig)
).to.be.eql(
true
)
})
it('encoding', () => {
const keyMarshal = key.marshal()
const key2 = rsa.unmarshalRsaPrivateKey(keyMarshal)
const keyMarshal2 = key2.marshal()
expect(
keyMarshal
).to.be.eql(
keyMarshal2
)
const pk = key.public
const pkMarshal = pk.marshal()
const pk2 = rsa.unmarshalRsaPublicKey(pkMarshal)
const pkMarshal2 = pk2.marshal()
expect(
pkMarshal
).to.be.eql(
pkMarshal2
)
})
describe('key equals', () => {
it('equals itself', () => {
expect(
key.equals(key)
).to.be.eql(
true
)
expect(
key.public.equals(key.public)
).to.be.eql(
true
)
})
it('not equals other key', (done) => {
crypto.generateKeyPair('RSA', 2048, (err, key2) => {
if (err) return done(err)
expect(
key.equals(key2)
).to.be.eql(
false
)
expect(
key2.equals(key)
).to.be.eql(
false
)
expect(
key.public.equals(key2.public)
).to.be.eql(
false
)
expect(
key2.public.equals(key.public)
).to.be.eql(
false
)
done()
})
})
})
})