"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 (0, 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 (0, 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] = (0, 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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGtkZi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9oa2RmLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSxvRUFBb0U7QUFDcEUsc0NBQXNDOzs7QUFFdEMsbUNBQStDO0FBQy9DLHFDQUErRDtBQUUvRDs7Ozs7R0FLRztBQUNILFNBQWdCLElBQUksQ0FBQyxTQUFTLEdBQUcsUUFBUTtJQUN2QywrQkFBK0I7SUFDL0IsTUFBTSxVQUFVLEdBQUcsQ0FBQztRQUNsQixJQUFJO1lBQ0YsT0FBTyxJQUFBLG1CQUFVLEVBQUMsU0FBUyxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsTUFBTSxDQUFBO1NBQzdDO1FBQUMsT0FBTyxFQUFFLEVBQUU7WUFDWCxNQUFNLElBQUksNkJBQW9CLENBQUMsU0FBUyxDQUFDLENBQUE7U0FDMUM7SUFDSCxDQUFDLENBQUMsRUFBRSxDQUFBO0lBRUosNERBQTREO0lBQzVELE1BQU0sU0FBUyxHQUFHLEdBQUcsR0FBRyxVQUFVLENBQUE7SUFFbEMsK0JBQStCO0lBQy9CLGFBQWEsQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFBO0lBQy9CLGFBQWEsQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFBO0lBRTdCLE9BQU8sYUFBYSxDQUFBO0lBRXBCLGlCQUFpQjtJQUVqQjs7Ozs7O09BTUc7SUFDSCxTQUFTLGFBQWEsQ0FDcEIsR0FBd0IsRUFDeEIsSUFBa0M7UUFFbEMsTUFBTSxHQUFHLEdBQUcsT0FBTyxDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsQ0FBQTtRQUM5QixPQUFPLENBQUMsTUFBYyxFQUFFLElBQWlCLEVBQUUsRUFBRSxDQUFDLE1BQU0sQ0FBQyxHQUFHLEVBQUUsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFBO0lBQ3pFLENBQUM7SUFFRDs7Ozs7O09BTUc7SUFDSCxTQUFTLE9BQU8sQ0FDZCxHQUF3QixFQUN4QixJQUFrQztRQUVsQyxNQUFNLEtBQUssR0FBRyxJQUFJLElBQUksTUFBTSxDQUFDLEtBQUssQ0FBQyxVQUFVLEVBQUUsQ0FBQyxDQUFDLENBQUMsUUFBUSxFQUFFLENBQUE7UUFDNUQsT0FBTyxJQUFBLG1CQUFVLEVBQUMsU0FBUyxFQUFFLEtBQUssQ0FBQyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQTtJQUMxRCxDQUFDO0lBRUQ7Ozs7Ozs7T0FPRztJQUNILFNBQVMsTUFBTSxDQUFDLEdBQWUsRUFBRSxNQUFjLEVBQUUsSUFBaUI7UUFDaEUsSUFBSSxNQUFNLEdBQUcsU0FBUyxFQUFFO1lBQ3RCLE1BQU0sSUFBSSx1QkFBYyxDQUFDLFNBQVMsRUFBRSxTQUFTLENBQUMsQ0FBQTtTQUMvQztRQUVELElBQUksR0FBRyxJQUFJLElBQUksTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQTtRQUM5QixNQUFNLENBQUMsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sR0FBRyxVQUFVLENBQUMsQ0FBQTtRQUN4QyxNQUFNLElBQUksR0FBYSxFQUFFLENBQUE7UUFFekI7O1dBRUc7UUFDSCxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFO1lBQzFCLElBQUksQ0FBQyxDQUFDLENBQUMsR0FBRyxJQUFBLG1CQUFVLEVBQUMsU0FBUyxFQUFFLEdBQUcsQ0FBQztpQkFDakMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztpQkFDdEMsTUFBTSxDQUFDLElBQUksQ0FBQztpQkFDWixNQUFNLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO2lCQUM5QixNQUFNLEVBQUUsQ0FBQTtTQUNaO1FBQ0QsT0FBTyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksRUFBRSxNQUFNLENBQUMsQ0FBQTtJQUNwQyxDQUFDO0FBQ0gsQ0FBQztBQWhGRCxvQkFnRkMifQ==