mirror of
https://github.com/fluencelabs/js-libp2p-crypto
synced 2025-03-15 15:21:07 +00:00
first pass at stretchKey
This commit is contained in:
parent
d415fa8007
commit
fe202607eb
@ -34,7 +34,13 @@ Generates an ephemeral public key and returns a function that will compute the s
|
||||
|
||||
Focuses only on ECDH now, but can be made more general in the future.
|
||||
|
||||
Returns a `Buffer`.
|
||||
Returns an object of the form
|
||||
```js
|
||||
{
|
||||
key: Buffer,
|
||||
genSharedKey: Function
|
||||
}
|
||||
```
|
||||
|
||||
### `marshalPublicKey(key[, type])`
|
||||
|
||||
|
@ -22,9 +22,14 @@ module.exports = (curveName) => {
|
||||
|
||||
const priv = ec.genKeyPair()
|
||||
|
||||
return (theirPub) => {
|
||||
const genSharedKey = (theirPub) => {
|
||||
const pub = ec.keyFromPublic(theirPub, 'hex')
|
||||
|
||||
return priv.derive(pub.getPublic()).toBuffer('le')
|
||||
}
|
||||
|
||||
return {
|
||||
key: priv.getPublic(),
|
||||
genSharedKey
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,97 @@
|
||||
'use strict'
|
||||
|
||||
const forge = require('node-forge')
|
||||
const createBuffer = forge.util.createBuffer
|
||||
|
||||
const cipherMap = {
|
||||
'AES-128': {
|
||||
ivSize: 16,
|
||||
keySize: 16
|
||||
},
|
||||
'AES-256': {
|
||||
ivSize: 16,
|
||||
keySize: 32
|
||||
},
|
||||
'Blowfish': {
|
||||
ivSize: 8,
|
||||
cipherKeySize: 32
|
||||
}
|
||||
}
|
||||
|
||||
const hashMap = {
|
||||
'SHA1': 'sha1',
|
||||
'SHA256': 'sha256',
|
||||
'SHA512': 'sha512'
|
||||
}
|
||||
|
||||
// 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')
|
||||
const cipher = cipherMap[cipherType]
|
||||
const hash = hashMap[hashType]
|
||||
|
||||
if (!cipher) {
|
||||
throw new Error('unkown cipherType passed')
|
||||
}
|
||||
|
||||
if (!hash) {
|
||||
throw new Error('unkown hashType passed')
|
||||
}
|
||||
|
||||
if (Buffer.isBuffer(secret)) {
|
||||
secret = createBuffer(secret.toString('binary'))
|
||||
}
|
||||
|
||||
const cipherKeySize = cipher.keySize
|
||||
const ivSize = cipher.ivSize
|
||||
const hmacKeySize = 20
|
||||
const seed = 'key expansion'
|
||||
const resultLength = 2 * (ivSize + cipherKeySize + hmacKeySize)
|
||||
|
||||
const m = forge.hmac.create()
|
||||
m.start(hash, secret)
|
||||
m.update(seed)
|
||||
|
||||
let a = m.digest().bytes()
|
||||
const result = createBuffer()
|
||||
|
||||
let j = 0
|
||||
for (; j < resultLength;) {
|
||||
m.start(hash, secret)
|
||||
m.update(a)
|
||||
m.update(seed)
|
||||
|
||||
const b = createBuffer(m.digest(), 'raw')
|
||||
let todo = b.length()
|
||||
|
||||
if (j + todo > resultLength) {
|
||||
todo = resultLength - j
|
||||
}
|
||||
|
||||
result.putBytes(b.getBytes(todo))
|
||||
|
||||
j += todo
|
||||
|
||||
m.start(hash, secret)
|
||||
m.update(a)
|
||||
a = m.digest().bytes()
|
||||
}
|
||||
|
||||
const half = resultLength / 2
|
||||
const r1 = createBuffer(result.getBytes(half))
|
||||
const r2 = createBuffer(result.getBytes())
|
||||
|
||||
const k1 = {
|
||||
IV: r1.getBytes(ivSize),
|
||||
CipherKey: r1.getBytes(cipherKeySize),
|
||||
MacKey: r1.getBytes()
|
||||
}
|
||||
|
||||
const k2 = {
|
||||
IV: r2.getBytes(ivSize),
|
||||
CipherKey: r2.getBytes(cipherKeySize),
|
||||
MacKey: r2.getBytes()
|
||||
}
|
||||
|
||||
return {k1, k2}
|
||||
}
|
||||
|
@ -7,11 +7,15 @@ const crypto = require('../src')
|
||||
|
||||
describe('generateEphemeralKeyPair', () => {
|
||||
it('returns a function that generates a shared secret', () => {
|
||||
const maker = crypto.generateEphemeralKeyPair('P-256')
|
||||
const res = crypto.generateEphemeralKeyPair('P-256')
|
||||
const ourPublic = '044374add0df35706db7dade25f3959fc051d2ef5166f8a6a0aa632d0ab41cdb4d30e1a064e121ac56155235a6b8d4c5d8fe35e019f507f4e2ff1445e229d7af43'
|
||||
|
||||
expect(
|
||||
maker(ourPublic)
|
||||
res.genSharedKey(ourPublic)
|
||||
).to.have.length(32)
|
||||
|
||||
expect(
|
||||
res.key
|
||||
).to.exist
|
||||
})
|
||||
})
|
||||
|
0
test/fixtures/go-rsa.key
vendored
Normal file
0
test/fixtures/go-rsa.key
vendored
Normal file
25
test/key-stretcher.spec.js
Normal file
25
test/key-stretcher.spec.js
Normal file
@ -0,0 +1,25 @@
|
||||
/* eslint-env mocha */
|
||||
'use strict'
|
||||
|
||||
const expect = require('chai').expect
|
||||
|
||||
const crypto = require('../src')
|
||||
|
||||
describe('keyStretcher', () => {
|
||||
describe('generate', () => {
|
||||
const ciphers = ['AES-128', 'AES-256', 'Blowfish']
|
||||
const hashes = ['SHA1', 'SHA256'/*, 'SHA512'*/]
|
||||
const res = crypto.generateEphemeralKeyPair('P-256')
|
||||
const secret = res.genSharedKey(res.key)
|
||||
|
||||
ciphers.forEach((cipher) => {
|
||||
hashes.forEach((hash) => {
|
||||
it(`${cipher} - ${hash}`, () => {
|
||||
const keys = crypto.keyStretcher(cipher, hash, secret)
|
||||
expect(keys.k1).to.exist
|
||||
expect(keys.k2).to.exist
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
Loading…
x
Reference in New Issue
Block a user