diff --git a/README.md b/README.md index 9bb618e..49dafd0 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,6 @@ needed for libp2p. This is based on this [go implementation](https://github.com/ ## API - ### `generateKeyPair(type, bits, cb)` - `type: String`, only `'RSA'` is currently supported @@ -27,6 +26,16 @@ needed for libp2p. This is based on this [go implementation](https://github.com/ Generates a keypair of the given type and bitsize. +### `generateEphemeralKeyPair(curve)` + +- `curve: String`, one of `'P-256'`, `'P-384'`, `'P-521'` is currently supported + +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. + +Returns a `Buffer`. + ### `marshalPublicKey(key[, type])` - `key: crypto.rsa.RsaPublicKey` diff --git a/package.json b/package.json index ffa89fd..6de6c08 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "author": "Friedel Ziegelmayer ", "license": "MIT", "dependencies": { + "elliptic": "^6.2.3", "multihashing": "^0.2.1", "node-forge": "^0.6.39", "protocol-buffers": "^3.1.6" diff --git a/src/ephemeral-keys.js b/src/ephemeral-keys.js new file mode 100644 index 0000000..12ce31c --- /dev/null +++ b/src/ephemeral-keys.js @@ -0,0 +1,30 @@ +'use strict' + +const EC = require('elliptic').ec + +const curveMap = { + 'P-256': 'p256', + 'P-384': 'p384', + 'P-521': 'p521' +} + +// 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. +module.exports = (curveName) => { + const curve = curveMap[curveName] + if (!curve) { + throw new Error('unsupported curve passed') + } + + const ec = new EC(curve) + + const priv = ec.genKeyPair() + + return (theirPub) => { + const pub = ec.keyFromPublic(theirPub, 'hex') + + return priv.derive(pub.getPublic()).toBuffer('le') + } +} diff --git a/src/index.js b/src/index.js index cda4e04..9c302a9 100644 --- a/src/index.js +++ b/src/index.js @@ -8,6 +8,9 @@ const pbm = protobuf(fs.readFileSync(path.join(__dirname, './crypto.proto'))) exports.utils = require('./utils') const keys = exports.keys = require('./keys') +exports.keyStretcher = require('./key-stretcher') +exports.generateEphemeralKeyPair = require('./ephemeral-keys') + // Generates a keypair of the given type and bitsize exports.generateKeyPair = (type, bits, cb) => { let key = keys[type.toLowerCase()] @@ -18,20 +21,6 @@ exports.generateKeyPair = (type, bits, cb) => { key.generateKeyPair(bits, cb) } -// 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. -exports.generateEphemeralKeyPair = (curveName, cb) => { - throw new Error('Not implemented') -} - -// Generates a set of keys for each party by stretching the shared key. -// (myIV, theirIV, myCipherKey, theirCipherKey, myMACKey, theirMACKey) -exports.keyStretcher = (cipherType, hashType, secret) => { - throw new Error('Not implemented') -} - // Converts a protobuf serialized public key into its // representative object exports.unmarshalPublicKey = (buf) => { diff --git a/src/key-stretcher.js b/src/key-stretcher.js new file mode 100644 index 0000000..0c05312 --- /dev/null +++ b/src/key-stretcher.js @@ -0,0 +1,7 @@ +'use strict' + +// Generates a set of keys for each party by stretching the shared key. +// (myIV, theirIV, myCipherKey, theirCipherKey, myMACKey, theirMACKey) +module.exports = (cipherType, hashType, secret) => { + throw new Error('Not implemented') +} diff --git a/test/ephemeral-keys.spec.js b/test/ephemeral-keys.spec.js new file mode 100644 index 0000000..f6a4ea9 --- /dev/null +++ b/test/ephemeral-keys.spec.js @@ -0,0 +1,17 @@ +/* eslint-env mocha */ +'use strict' + +const expect = require('chai').expect + +const crypto = require('../src') + +describe('generateEphemeralKeyPair', () => { + it('returns a function that generates a shared secret', () => { + const maker = crypto.generateEphemeralKeyPair('P-256') + const ourPublic = '044374add0df35706db7dade25f3959fc051d2ef5166f8a6a0aa632d0ab41cdb4d30e1a064e121ac56155235a6b8d4c5d8fe35e019f507f4e2ff1445e229d7af43' + + expect( + maker(ourPublic) + ).to.have.length(32) + }) +})