UNPKG

nstdlib-nightly

Version:

Node.js standard library converted to runtime-agnostic ES modules.

151 lines (127 loc) 3.52 kB
// Source: https://github.com/nodejs/node/blob/65eff1eb/lib/internal/crypto/hkdf.js import { HKDFJob, kCryptoJobAsync, kCryptoJobSync, } from "nstdlib/stub/binding/crypto"; import { validateFunction, validateInteger, validateString, } from "nstdlib/lib/internal/validators"; import { kMaxLength } from "nstdlib/lib/buffer"; import { normalizeHashName, toBuf, validateByteSource, kKeyObject, } from "nstdlib/lib/internal/crypto/util"; import { createSecretKey, isKeyObject } from "nstdlib/lib/internal/crypto/keys"; import { lazyDOMException, promisify } from "nstdlib/lib/internal/util"; import { isAnyArrayBuffer, isArrayBufferView, } from "nstdlib/lib/internal/util/types"; import { codes as __codes__, hideStackFrames, } from "nstdlib/lib/internal/errors"; const { ERR_INVALID_ARG_TYPE, ERR_OUT_OF_RANGE } = __codes__; const validateParameters = hideStackFrames((hash, key, salt, info, length) => { validateString.withoutStackTrace(hash, "digest"); key = prepareKey(key); salt = validateByteSource.withoutStackTrace(salt, "salt"); info = validateByteSource.withoutStackTrace(info, "info"); validateInteger.withoutStackTrace(length, "length", 0, kMaxLength); if (info.byteLength > 1024) { throw new ERR_OUT_OF_RANGE.HideStackFramesError( "info", "must not contain more than 1024 bytes", info.byteLength, ); } return { hash, key, salt, info, length, }; }); function prepareKey(key) { if (isKeyObject(key)) return key; if (isAnyArrayBuffer(key)) return createSecretKey(key); key = toBuf(key); if (!isArrayBufferView(key)) { throw new ERR_INVALID_ARG_TYPE( "ikm", [ "string", "SecretKeyObject", "ArrayBuffer", "TypedArray", "DataView", "Buffer", ], key, ); } return createSecretKey(key); } function hkdf(hash, key, salt, info, length, callback) { ({ hash, key, salt, info, length } = validateParameters( hash, key, salt, info, length, )); validateFunction(callback, "callback"); const job = new HKDFJob(kCryptoJobAsync, hash, key, salt, info, length); job.ondone = (error, bits) => { if (error) return Function.prototype.call.call(callback, job, error); Function.prototype.call.call(callback, job, null, bits); }; job.run(); } function hkdfSync(hash, key, salt, info, length) { ({ hash, key, salt, info, length } = validateParameters( hash, key, salt, info, length, )); const job = new HKDFJob(kCryptoJobSync, hash, key, salt, info, length); const { 0: err, 1: bits } = job.run(); if (err !== undefined) throw err; return bits; } const hkdfPromise = promisify(hkdf); async function hkdfDeriveBits(algorithm, baseKey, length) { const { hash, salt, info } = algorithm; if (length === 0) throw lazyDOMException("length cannot be zero", "OperationError"); if (length === null) throw lazyDOMException("length cannot be null", "OperationError"); if (length % 8) { throw lazyDOMException("length must be a multiple of 8", "OperationError"); } try { return await hkdfPromise( normalizeHashName(hash.name), baseKey[kKeyObject], salt, info, length / 8, ); } catch (err) { throw lazyDOMException( "The operation failed for an operation-specific reason", { name: "OperationError", cause: err }, ); } } export { hkdf }; export { hkdfSync }; export { hkdfDeriveBits };