2021-12-07 13:18:08 -05:00

41 lines
1.1 KiB
JavaScript

const { createHash } = require('crypto')
const ecdhComputeSecret = require('./compute_secret')
const concat = (key, length, value) => {
const iterations = Math.ceil(length / 32)
let res
for (let iter = 1; iter <= iterations; iter++) {
const buf = Buffer.allocUnsafe(4 + key.length + value.length)
buf.writeUInt32BE(iter, 0)
key.copy(buf, 4)
value.copy(buf, 4 + key.length)
if (!res) {
res = createHash('sha256').update(buf).digest()
} else {
res = Buffer.concat([res, createHash('sha256').update(buf).digest()])
}
}
return res.slice(0, length)
}
const uint32be = (value, buf = Buffer.allocUnsafe(4)) => {
buf.writeUInt32BE(value)
return buf
}
const lengthAndInput = input => Buffer.concat([uint32be(input.length), input])
module.exports = (alg, keyLen, privKey, pubKey, { apu = Buffer.alloc(0), apv = Buffer.alloc(0) } = {}, computeSecret = ecdhComputeSecret) => {
const value = Buffer.concat([
lengthAndInput(Buffer.from(alg)),
lengthAndInput(apu),
lengthAndInput(apv),
uint32be(keyLen)
])
const sharedSecret = computeSecret(privKey, pubKey)
return concat(sharedSecret, keyLen / 8, value)
}