I am trying to implement HKDF with CryptoJS. (It’s not allowed to use native crypto in my case.) The output of my implementation is different from the output from CyberChef, so I think my implementation is wrong somewhere. I cannot figure out what is wrong. Below is my code:
function toUint8Array(wordArray) {
// copy from: https://gist.github.com/lettergram/ba6733a854f835bca22b
var words = wordArray.words;
var sigBytes = wordArray.sigBytes;
var u8 = new Uint8Array(sigBytes);
for (var i = 0; i < sigBytes; i++) {
var byte = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
u8[i]=byte;
}
return u8;
}
/**
* HKDF (HMAC-based Key Derivation Function) implementation.
*
* @param {Uint8Array} salt - The salt value used in the extraction phase.
* @param {Uint8Array} ikm - The input key material.
* @param {Uint8Array} info - Contextual information for the extraction.
* @param {number} length - The desired length of the output key material in bytes.
* @returns {Uint8Array} The derived key material
*/
function hkdfSha256(salt, ikm, info, length) {
const prk = CryptoJS.HmacSHA256(CryptoJS.lib.WordArray.create(ikm), CryptoJS.lib.WordArray.create(salt)); // HKDF-Extract
let okm = CryptoJS.lib.WordArray.create();
let previousBlock = CryptoJS.lib.WordArray.create();
const wordArrayInfo = CryptoJS.lib.WordArray.create(info)
for (let i = 1; okm.sigBytes < length; i++) {
previousBlock = CryptoJS.HmacSHA256(previousBlock.concat(wordArrayInfo).concat(CryptoJS.lib.WordArray.create([i], 1)), prk);
okm.concat(previousBlock);
}
return toUint8Array(okm);
// return new Uint8Array(new Int32Array(okm.words).buffer, 0, length);
}
function main() {
const salt = CryptoJS.enc.Hex.parse('f339a9b6f339a9b6');
const ikm = CryptoJS.enc.Utf8.parse('Hello');
const info = CryptoJS.enc.Hex.parse('');
const length = 32;
let outputKeyMaterial = hkdfSha256(toUint8Array(salt), toUint8Array(ikm), toUint8Array(info), length);
console.log(CryptoJS.lib.WordArray.create(outputKeyMaterial).toString());
// output: 4ac2a7fe494a5920aaac2f4771ec73468a14f8af1d49bf3d11ce75c8fda8f4e1
// CyberChef: 3d18bc7eccb941ded1260bef702b94d899f4defa0365a49ee83543c59f336fe6
}
This is the recipe of the CyberChef