"use strict";
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
Object.defineProperty(exports, "__esModule", { value: true });
exports.HKDF = void 0;
const crypto_1 = require("crypto");
const errors_1 = require("./errors");
/**
 * Factory function to curry the hash algorithm
 *
 * @param algorithm [String] The name of the hash algorithm to use
 * @return [Function] The extract function decorated with expand and verify functions
 */
function HKDF(algorithm = 'sha256') {
    // Check the length and support
    const hashLength = (function () {
        try {
            return crypto_1.createHash(algorithm).digest().length;
        }
        catch (ex) {
            throw new errors_1.UnsupportedAlgorithm(algorithm);
        }
    })();
    // (<= 255*HashLen) from https://tools.ietf.org/html/rfc5869
    const maxLength = 255 * hashLength;
    // decorate the return function
    extractExpand.extract = extract;
    extractExpand.expand = expand;
    return extractExpand;
    // implementation
    /**
     * Extracts a prk and returns a function to expand the given initial key
     *
     * @param ikm [String|Buffer] The initial key
     * @param salt [String|Buffer] Optional salt for the extraction
     * @return [Function] expand function with the extracted key curried onto it
     */
    function extractExpand(ikm, salt) {
        const prk = extract(ikm, salt);
        return (length, info) => expand(prk, length, info);
    }
    /**
     * Extracts a prk and returns a function to expand the given initial key
     *
     * @param ikm [String|Buffer] The initial key
     * @param salt [String|Buffer] Optional salt for the extraction
     * @return [Buffer] the expanded key
     */
    function extract(ikm, salt) {
        const _salt = salt || Buffer.alloc(hashLength, 0).toString();
        return crypto_1.createHmac(algorithm, _salt).update(ikm).digest();
    }
    /**
     * Expands a given key
     *
     * @param prk [Buffer] The key to expand from
     * @param length [Number] The length of the expanded key
     * @param info [Buffer] Data to bind the expanded key to application/context specific information
     * @return [Buffer] the expanded
     */
    function expand(prk, length, info) {
        if (length > maxLength) {
            throw new errors_1.KeyLengthError(maxLength, algorithm);
        }
        info = info || Buffer.alloc(0);
        const N = Math.ceil(length / hashLength);
        const memo = [];
        /* L/length octets are returned from T(1)...T(N), and T(0) is definitionally empty/zero length.
         * Elide T(0) into the Buffer.alloc(0) case and then return L octets of T indexed 0...L-1.
         */
        for (let i = 0; i < N; i++) {
            memo[i] = crypto_1.createHmac(algorithm, prk)
                .update(memo[i - 1] || Buffer.alloc(0))
                .update(info)
                .update(Buffer.alloc(1, i + 1))
                .digest();
        }
        return Buffer.concat(memo, length);
    }
}
exports.HKDF = HKDF;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGtkZi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9oa2RmLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSxvRUFBb0U7QUFDcEUsc0NBQXNDOzs7QUFFdEMsbUNBQStDO0FBQy9DLHFDQUErRDtBQUUvRDs7Ozs7R0FLRztBQUNILFNBQWdCLElBQUksQ0FBQyxTQUFTLEdBQUcsUUFBUTtJQUN2QywrQkFBK0I7SUFDL0IsTUFBTSxVQUFVLEdBQUcsQ0FBQztRQUNsQixJQUFJO1lBQ0YsT0FBTyxtQkFBVSxDQUFDLFNBQVMsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLE1BQU0sQ0FBQTtTQUM3QztRQUFDLE9BQU8sRUFBRSxFQUFFO1lBQ1gsTUFBTSxJQUFJLDZCQUFvQixDQUFDLFNBQVMsQ0FBQyxDQUFBO1NBQzFDO0lBQ0gsQ0FBQyxDQUFDLEVBQUUsQ0FBQTtJQUVKLDREQUE0RDtJQUM1RCxNQUFNLFNBQVMsR0FBRyxHQUFHLEdBQUcsVUFBVSxDQUFBO0lBRWxDLCtCQUErQjtJQUMvQixhQUFhLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQTtJQUMvQixhQUFhLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQTtJQUU3QixPQUFPLGFBQWEsQ0FBQTtJQUVwQixpQkFBaUI7SUFFakI7Ozs7OztPQU1HO0lBQ0gsU0FBUyxhQUFhLENBQ3BCLEdBQXdCLEVBQ3hCLElBQWtDO1FBRWxDLE1BQU0sR0FBRyxHQUFHLE9BQU8sQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLENBQUE7UUFDOUIsT0FBTyxDQUFDLE1BQWMsRUFBRSxJQUFpQixFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsR0FBRyxFQUFFLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQTtJQUN6RSxDQUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ0gsU0FBUyxPQUFPLENBQ2QsR0FBd0IsRUFDeEIsSUFBa0M7UUFFbEMsTUFBTSxLQUFLLEdBQUcsSUFBSSxJQUFJLE1BQU0sQ0FBQyxLQUFLLENBQUMsVUFBVSxFQUFFLENBQUMsQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFBO1FBQzVELE9BQU8sbUJBQVUsQ0FBQyxTQUFTLEVBQUUsS0FBSyxDQUFDLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFBO0lBQzFELENBQUM7SUFFRDs7Ozs7OztPQU9HO0lBQ0gsU0FBUyxNQUFNLENBQUMsR0FBZSxFQUFFLE1BQWMsRUFBRSxJQUFpQjtRQUNoRSxJQUFJLE1BQU0sR0FBRyxTQUFTLEVBQUU7WUFDdEIsTUFBTSxJQUFJLHVCQUFjLENBQUMsU0FBUyxFQUFFLFNBQVMsQ0FBQyxDQUFBO1NBQy9DO1FBRUQsSUFBSSxHQUFHLElBQUksSUFBSSxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFBO1FBQzlCLE1BQU0sQ0FBQyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxHQUFHLFVBQVUsQ0FBQyxDQUFBO1FBQ3hDLE1BQU0sSUFBSSxHQUFhLEVBQUUsQ0FBQTtRQUV6Qjs7V0FFRztRQUNILEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUU7WUFDMUIsSUFBSSxDQUFDLENBQUMsQ0FBQyxHQUFHLG1CQUFVLENBQUMsU0FBUyxFQUFFLEdBQUcsQ0FBQztpQkFDakMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztpQkFDdEMsTUFBTSxDQUFDLElBQUksQ0FBQztpQkFDWixNQUFNLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO2lCQUM5QixNQUFNLEVBQUUsQ0FBQTtTQUNaO1FBQ0QsT0FBTyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksRUFBRSxNQUFNLENBQUMsQ0FBQTtJQUNwQyxDQUFDO0FBQ0gsQ0FBQztBQWhGRCxvQkFnRkMifQ==