export function rawDerive()

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)
}