@libp2p/crypto
Version:
Crypto primitives for libp2p
67 lines • 2.35 kB
JavaScript
import { InvalidParametersError } from '@libp2p/interface';
import { concat as uint8ArrayConcat } from 'uint8arrays/concat';
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string';
import * as hmac from '../hmac/index.js';
const cipherMap = {
'AES-128': {
ivSize: 16,
keySize: 16
},
'AES-256': {
ivSize: 16,
keySize: 32
},
Blowfish: {
ivSize: 8,
keySize: 32
}
};
/**
* Generates a set of keys for each party by stretching the shared key.
* (myIV, theirIV, myCipherKey, theirCipherKey, myMACKey, theirMACKey)
*/
export async function keyStretcher(cipherType, hash, secret) {
if (cipherType !== 'AES-128' && cipherType !== 'AES-256' && cipherType !== 'Blowfish') {
throw new InvalidParametersError('Cipher type was missing or unsupported');
}
if (hash !== 'SHA1' && hash !== 'SHA256' && hash !== 'SHA512') {
throw new InvalidParametersError('Hash type was missing or unsupported');
}
if (secret == null || !(secret instanceof Uint8Array)) {
throw new InvalidParametersError('Secret was missing or an incorrect type');
}
const cipher = cipherMap[cipherType];
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.subarray(0, half);
const r2 = resultBuffer.subarray(half, resultLength);
const createKey = (res) => ({
iv: res.subarray(0, ivSize),
cipherKey: res.subarray(ivSize, ivSize + cipherKeySize),
macKey: res.subarray(ivSize + cipherKeySize)
});
return {
k1: createKey(r1),
k2: createKey(r2)
};
}
//# sourceMappingURL=key-stretcher.js.map