mirror of
https://github.com/fluencelabs/js-libp2p-crypto
synced 2025-04-24 23:32:30 +00:00
* fix: replace node buffers with uint8arrays All usage of node buffers have been replaced with uint8arrays. BREAKING CHANGES: - Where node Buffers were returned, now Uint8Arrays are * chore: remove commented code
78 lines
1.8 KiB
JavaScript
78 lines
1.8 KiB
JavaScript
'use strict'
|
|
|
|
const errcode = require('err-code')
|
|
const uint8ArrayConcat = require('uint8arrays/concat')
|
|
const uint8ArrayFromString = require('uint8arrays/from-string')
|
|
const hmac = require('../hmac')
|
|
|
|
const cipherMap = {
|
|
'AES-128': {
|
|
ivSize: 16,
|
|
keySize: 16
|
|
},
|
|
'AES-256': {
|
|
ivSize: 16,
|
|
keySize: 32
|
|
},
|
|
Blowfish: {
|
|
ivSize: 8,
|
|
cipherKeySize: 32
|
|
}
|
|
}
|
|
|
|
// Generates a set of keys for each party by stretching the shared key.
|
|
// (myIV, theirIV, myCipherKey, theirCipherKey, myMACKey, theirMACKey)
|
|
module.exports = async (cipherType, hash, secret) => {
|
|
const cipher = cipherMap[cipherType]
|
|
|
|
if (!cipher) {
|
|
const allowed = Object.keys(cipherMap).join(' / ')
|
|
throw errcode(new Error(`unknown cipher type '${cipherType}'. Must be ${allowed}`), 'ERR_INVALID_CIPHER_TYPE')
|
|
}
|
|
|
|
if (!hash) {
|
|
throw errcode(new Error('missing hash type'), 'ERR_MISSING_HASH_TYPE')
|
|
}
|
|
|
|
const cipherKeySize = cipher.keySize
|
|
const ivSize = cipher.ivSize
|
|
const hmacKeySize = 20
|
|
const seed = uint8ArrayFromString('key expansion')
|
|
const resultLength = 2 * (ivSize + cipherKeySize + hmacKeySize)
|
|
|
|
const m = await hmac.create(hash, secret)
|
|
let a = await m.digest(seed)
|
|
|
|
const result = []
|
|
let j = 0
|
|
|
|
while (j < resultLength) {
|
|
const b = await m.digest(uint8ArrayConcat([a, seed]))
|
|
let todo = b.length
|
|
|
|
if (j + todo > resultLength) {
|
|
todo = resultLength - j
|
|
}
|
|
|
|
result.push(b)
|
|
j += todo
|
|
a = await m.digest(a)
|
|
}
|
|
|
|
const half = resultLength / 2
|
|
const resultBuffer = uint8ArrayConcat(result)
|
|
const r1 = resultBuffer.slice(0, half)
|
|
const r2 = resultBuffer.slice(half, resultLength)
|
|
|
|
const createKey = (res) => ({
|
|
iv: res.slice(0, ivSize),
|
|
cipherKey: res.slice(ivSize, ivSize + cipherKeySize),
|
|
macKey: res.slice(ivSize + cipherKeySize)
|
|
})
|
|
|
|
return {
|
|
k1: createKey(r1),
|
|
k2: createKey(r2)
|
|
}
|
|
}
|