mirror of
https://github.com/fluencelabs/js-libp2p-crypto
synced 2025-03-15 19:50:58 +00:00
feat: add marshal and unmarshl methods
This commit is contained in:
parent
f3a22ea5ff
commit
ca0b5305a2
28
README.md
28
README.md
@ -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.
|
||||||
|
61
src/index.js
61
src/index.js
@ -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()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
@ -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)
|
||||||
|
@ -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
115
test/rsa.spec.js
Normal 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()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
Loading…
x
Reference in New Issue
Block a user