"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.NodeDefaultCryptographicMaterialsManager = void 0;
const material_management_1 = require("@aws-crypto/material-management");
const serialize_1 = require("@aws-crypto/serialize");
const crypto_1 = require("crypto");
/**
 * The NodeDefaultCryptographicMaterialsManager is a specific implementation of the CryptographicMaterialsManager.
 * New cryptography materials managers SHOULD extend from NodeMaterialsManager.
 * Users should never need to create an instance of a NodeDefaultCryptographicMaterialsManager.
 */
class NodeDefaultCryptographicMaterialsManager {
    constructor(keyring) {
        /* Precondition: keyrings must be a KeyringNode. */
        (0, material_management_1.needs)(keyring instanceof material_management_1.KeyringNode, 'Unsupported type.');
        (0, material_management_1.readOnlyProperty)(this, 'keyring', keyring);
    }
    async getEncryptionMaterials({ suite, encryptionContext, commitmentPolicy, }) {
        suite =
            suite ||
                new material_management_1.NodeAlgorithmSuite(material_management_1.CommitmentPolicySuites[commitmentPolicy].defaultAlgorithmSuite);
        /* Precondition: NodeDefaultCryptographicMaterialsManager must reserve the ENCODED_SIGNER_KEY constant from @aws-crypto/serialize.
         * A CryptographicMaterialsManager can change entries to the encryptionContext
         * but changing these values has consequences.
         * The DefaultCryptographicMaterialsManager uses the value in the encryption context to store public signing key.
         * If the caller is using this value in their encryption context the Default CMM is probably not the CMM they want to use.
         */
        (0, material_management_1.needs)(!Object.prototype.hasOwnProperty.call(encryptionContext, serialize_1.ENCODED_SIGNER_KEY), `Reserved encryptionContext value ${serialize_1.ENCODED_SIGNER_KEY} not allowed.`);
        const material = await this.keyring.onEncrypt(this._initializeEncryptionMaterial(suite, encryptionContext));
        /* Postcondition: The NodeEncryptionMaterial must contain a valid dataKey.
         * This verifies that the data key matches the algorithm suite specification
         * and that the unencrypted data key is non-NULL.
         * See: cryptographic_materials.ts, `getUnencryptedDataKey`
         */
        (0, material_management_1.needs)(material.getUnencryptedDataKey(), 'Unencrypted data key is invalid.');
        /* Postcondition: The NodeEncryptionMaterial must contain at least 1 EncryptedDataKey. */
        (0, material_management_1.needs)(material.encryptedDataKeys.length, 'No EncryptedDataKeys: the ciphertext can never be decrypted.');
        return material;
    }
    async decryptMaterials({ suite, encryptedDataKeys, encryptionContext, }) {
        const material = await this.keyring.onDecrypt(this._initializeDecryptionMaterial(suite, encryptionContext), encryptedDataKeys.slice());
        /* Postcondition: The NodeDecryptionMaterial must contain a valid dataKey.
         * See: cryptographic_materials.ts, `getUnencryptedDataKey` also verifies
         * that the unencrypted data key has not been manipulated,
         * that the data key matches the algorithm suite specification
         * and that the unencrypted data key is non-NULL.
         */
        (0, material_management_1.needs)(material.getUnencryptedDataKey(), 'Unencrypted data key is invalid.');
        return material;
    }
    _initializeEncryptionMaterial(suite, encryptionContext) {
        const { signatureCurve: namedCurve } = suite;
        /* Check for early return (Postcondition): The algorithm suite specification must support a signatureCurve to generate a ECDH key. */
        if (!namedCurve)
            return new material_management_1.NodeEncryptionMaterial(suite, encryptionContext);
        const ecdh = (0, crypto_1.createECDH)(namedCurve);
        ecdh.generateKeys();
        // @ts-ignore I want a compressed buffer.
        const compressPoint = ecdh.getPublicKey(undefined, 'compressed');
        const privateKey = ecdh.getPrivateKey();
        const signatureKey = new material_management_1.SignatureKey(privateKey, new Uint8Array(compressPoint), suite);
        return new material_management_1.NodeEncryptionMaterial(suite, {
            ...encryptionContext,
            [serialize_1.ENCODED_SIGNER_KEY]: compressPoint.toString('base64'),
        }).setSignatureKey(signatureKey);
    }
    _initializeDecryptionMaterial(suite, encryptionContext) {
        const { signatureCurve: namedCurve } = suite;
        if (!namedCurve) {
            /* Precondition: NodeDefaultCryptographicMaterialsManager The context must not contain a public key for a non-signing algorithm suite. */
            (0, material_management_1.needs)(!Object.prototype.hasOwnProperty.call(encryptionContext, serialize_1.ENCODED_SIGNER_KEY), 'Encryption context contains public verification key for unsigned algorithm suite.');
            /* Check for early return (Postcondition): The algorithm suite specification must support a signatureCurve to load a signature key. */
            return new material_management_1.NodeDecryptionMaterial(suite, encryptionContext);
        }
        /* Precondition: NodeDefaultCryptographicMaterialsManager If the algorithm suite specification requires a signatureCurve a context must exist. */
        if (!encryptionContext)
            throw new Error('Encryption context does not contain required public key.');
        const { [serialize_1.ENCODED_SIGNER_KEY]: compressPoint } = encryptionContext;
        /* Precondition: NodeDefaultCryptographicMaterialsManager The context must contain the public key. */
        (0, material_management_1.needs)(compressPoint, 'Context does not contain required public key.');
        const publicKeyBytes = material_management_1.VerificationKey.decodeCompressPoint(Buffer.from(compressPoint, 'base64'), suite);
        return new material_management_1.NodeDecryptionMaterial(suite, encryptionContext).setVerificationKey(new material_management_1.VerificationKey(publicKeyBytes, suite));
    }
}
exports.NodeDefaultCryptographicMaterialsManager = NodeDefaultCryptographicMaterialsManager;
(0, material_management_1.immutableClass)(NodeDefaultCryptographicMaterialsManager);
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm9kZV9jcnlwdG9ncmFwaGljX21hdGVyaWFsc19tYW5hZ2VyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL25vZGVfY3J5cHRvZ3JhcGhpY19tYXRlcmlhbHNfbWFuYWdlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsb0VBQW9FO0FBQ3BFLHNDQUFzQzs7O0FBRXRDLHlFQWlCd0M7QUFFeEMscURBQTBEO0FBRTFELG1DQUFtQztBQVFuQzs7OztHQUlHO0FBQ0gsTUFBYSx3Q0FBd0M7SUFJbkQsWUFBWSxPQUFvQjtRQUM5QixtREFBbUQ7UUFDbkQsSUFBQSwyQkFBSyxFQUFDLE9BQU8sWUFBWSxpQ0FBVyxFQUFFLG1CQUFtQixDQUFDLENBQUE7UUFDMUQsSUFBQSxzQ0FBZ0IsRUFBQyxJQUFJLEVBQUUsU0FBUyxFQUFFLE9BQU8sQ0FBQyxDQUFBO0lBQzVDLENBQUM7SUFFRCxLQUFLLENBQUMsc0JBQXNCLENBQUMsRUFDM0IsS0FBSyxFQUNMLGlCQUFpQixFQUNqQixnQkFBZ0IsR0FDTTtRQUN0QixLQUFLO1lBQ0gsS0FBSztnQkFDTCxJQUFJLHdDQUFrQixDQUNwQiw0Q0FBc0IsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLHFCQUFxQixDQUMvRCxDQUFBO1FBRUg7Ozs7O1dBS0c7UUFDSCxJQUFBLDJCQUFLLEVBQ0gsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQ25DLGlCQUFpQixFQUNqQiw4QkFBa0IsQ0FDbkIsRUFDRCxvQ0FBb0MsOEJBQWtCLGVBQWUsQ0FDdEUsQ0FBQTtRQUVELE1BQU0sUUFBUSxHQUFHLE1BQU0sSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQzNDLElBQUksQ0FBQyw2QkFBNkIsQ0FBQyxLQUFLLEVBQUUsaUJBQWlCLENBQUMsQ0FDN0QsQ0FBQTtRQUVEOzs7O1dBSUc7UUFDSCxJQUFBLDJCQUFLLEVBQUMsUUFBUSxDQUFDLHFCQUFxQixFQUFFLEVBQUUsa0NBQWtDLENBQUMsQ0FBQTtRQUUzRSx5RkFBeUY7UUFDekYsSUFBQSwyQkFBSyxFQUNILFFBQVEsQ0FBQyxpQkFBaUIsQ0FBQyxNQUFNLEVBQ2pDLDhEQUE4RCxDQUMvRCxDQUFBO1FBRUQsT0FBTyxRQUFRLENBQUE7SUFDakIsQ0FBQztJQUVELEtBQUssQ0FBQyxnQkFBZ0IsQ0FBQyxFQUNyQixLQUFLLEVBQ0wsaUJBQWlCLEVBQ2pCLGlCQUFpQixHQUNLO1FBQ3RCLE1BQU0sUUFBUSxHQUFHLE1BQU0sSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQzNDLElBQUksQ0FBQyw2QkFBNkIsQ0FBQyxLQUFLLEVBQUUsaUJBQWlCLENBQUMsRUFDNUQsaUJBQWlCLENBQUMsS0FBSyxFQUFFLENBQzFCLENBQUE7UUFFRDs7Ozs7V0FLRztRQUNILElBQUEsMkJBQUssRUFBQyxRQUFRLENBQUMscUJBQXFCLEVBQUUsRUFBRSxrQ0FBa0MsQ0FBQyxDQUFBO1FBRTNFLE9BQU8sUUFBUSxDQUFBO0lBQ2pCLENBQUM7SUFFRCw2QkFBNkIsQ0FDM0IsS0FBeUIsRUFDekIsaUJBQW9DO1FBRXBDLE1BQU0sRUFBRSxjQUFjLEVBQUUsVUFBVSxFQUFFLEdBQUcsS0FBSyxDQUFBO1FBRTVDLHFJQUFxSTtRQUNySSxJQUFJLENBQUMsVUFBVTtZQUFFLE9BQU8sSUFBSSw0Q0FBc0IsQ0FBQyxLQUFLLEVBQUUsaUJBQWlCLENBQUMsQ0FBQTtRQUU1RSxNQUFNLElBQUksR0FBRyxJQUFBLG1CQUFVLEVBQUMsVUFBVSxDQUFDLENBQUE7UUFDbkMsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFBO1FBQ25CLHlDQUF5QztRQUN6QyxNQUFNLGFBQWEsR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLFNBQVMsRUFBRSxZQUFZLENBQUMsQ0FBQTtRQUNoRSxNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsYUFBYSxFQUFFLENBQUE7UUFDdkMsTUFBTSxZQUFZLEdBQUcsSUFBSSxrQ0FBWSxDQUNuQyxVQUFVLEVBQ1YsSUFBSSxVQUFVLENBQUMsYUFBYSxDQUFDLEVBQzdCLEtBQUssQ0FDTixDQUFBO1FBRUQsT0FBTyxJQUFJLDRDQUFzQixDQUFDLEtBQUssRUFBRTtZQUN2QyxHQUFHLGlCQUFpQjtZQUNwQixDQUFDLDhCQUFrQixDQUFDLEVBQUUsYUFBYSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUM7U0FDdkQsQ0FBQyxDQUFDLGVBQWUsQ0FBQyxZQUFZLENBQUMsQ0FBQTtJQUNsQyxDQUFDO0lBRUQsNkJBQTZCLENBQzNCLEtBQXlCLEVBQ3pCLGlCQUFvQztRQUVwQyxNQUFNLEVBQUUsY0FBYyxFQUFFLFVBQVUsRUFBRSxHQUFHLEtBQUssQ0FBQTtRQUU1QyxJQUFJLENBQUMsVUFBVSxFQUFFO1lBQ2YseUlBQXlJO1lBQ3pJLElBQUEsMkJBQUssRUFDSCxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsY0FBYyxDQUFDLElBQUksQ0FDbkMsaUJBQWlCLEVBQ2pCLDhCQUFrQixDQUNuQixFQUNELG1GQUFtRixDQUNwRixDQUFBO1lBRUQsc0lBQXNJO1lBQ3RJLE9BQU8sSUFBSSw0Q0FBc0IsQ0FBQyxLQUFLLEVBQUUsaUJBQWlCLENBQUMsQ0FBQTtTQUM1RDtRQUVELGlKQUFpSjtRQUNqSixJQUFJLENBQUMsaUJBQWlCO1lBQ3BCLE1BQU0sSUFBSSxLQUFLLENBQ2IsMERBQTBELENBQzNELENBQUE7UUFFSCxNQUFNLEVBQUUsQ0FBQyw4QkFBa0IsQ0FBQyxFQUFFLGFBQWEsRUFBRSxHQUFHLGlCQUFpQixDQUFBO1FBRWpFLHFHQUFxRztRQUNyRyxJQUFBLDJCQUFLLEVBQUMsYUFBYSxFQUFFLCtDQUErQyxDQUFDLENBQUE7UUFFckUsTUFBTSxjQUFjLEdBQUcscUNBQWUsQ0FBQyxtQkFBbUIsQ0FDeEQsTUFBTSxDQUFDLElBQUksQ0FBQyxhQUFhLEVBQUUsUUFBUSxDQUFDLEVBQ3BDLEtBQUssQ0FDTixDQUFBO1FBRUQsT0FBTyxJQUFJLDRDQUFzQixDQUMvQixLQUFLLEVBQ0wsaUJBQWlCLENBQ2xCLENBQUMsa0JBQWtCLENBQUMsSUFBSSxxQ0FBZSxDQUFDLGNBQWMsRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFBO0lBQ2xFLENBQUM7Q0FDRjtBQS9JRCw0RkErSUM7QUFDRCxJQUFBLG9DQUFjLEVBQUMsd0NBQXdDLENBQUMsQ0FBQSJ9