in modules/kdf-ctr-mode-node/src/kdfctr.ts [84:133]
export function rawDerive(
ikm: Buffer,
explicitInfo: Buffer,
length: number,
// omit offset as a parameter because it is unused, causing compile errors due
// to configured project settings
digestAlgorithm: SupportedDigestAlgorithms
): Buffer {
const h = createHash(digestAlgorithm).digest().length
/* Precondition: expected length must be positive */
needs(length > 0, `Requested length ${length} must be positive`)
/* Precondition: length of explicit info + 4 bytes should be under the max 32-bit signed integer */
needs(
4 + explicitInfo.length < INT32_MAX_LIMIT,
`Explicit info length ${explicitInfo.length} must be under ${
INT32_MAX_LIMIT - 4
} bytes`
)
/* Precondition: the digest algorithm should be sha256 */
needs(
SUPPORTED_DIGEST_ALGORITHMS.includes(digestAlgorithm),
`Unsupported digest algorithm ${digestAlgorithm}`
)
/* Precondition: the expected length + digest hash length should be under the max 32-bit signed integer - 1 */
needs(
length + h < INT32_MAX_LIMIT - 1,
`The combined requested and digest hash length ${
length + h
} must be under ${INT32_MAX_LIMIT - 1} bytes`
)
// number of iterations calculated in accordance with SP800-108
const iterations = Math.floor((length + h - 1) / h)
let buffer = Buffer.alloc(0)
let i = Buffer.from(uInt32BE(COUNTER_START_VALUE))
for (let iteration = 1; iteration <= iterations; iteration++) {
const digest = createHmac(digestAlgorithm, ikm)
.update(i)
.update(explicitInfo)
.digest()
buffer = Buffer.concat([buffer, digest])
i = increment(i)
}
needs(buffer.length >= length, 'Failed to derive key of requested length')
return buffer.subarray(0, length)
}