// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import { NodeAlgorithmSuite, NodeEncryptionMaterial, NodeDecryptionMaterial, SignatureKey, needs, VerificationKey, immutableClass, readOnlyProperty, KeyringNode, CommitmentPolicySuites, } from '@aws-crypto/material-management';
import { ENCODED_SIGNER_KEY } from '@aws-crypto/serialize';
import { createECDH } from '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.
 */
export class NodeDefaultCryptographicMaterialsManager {
    constructor(keyring) {
        /* Precondition: keyrings must be a KeyringNode. */
        needs(keyring instanceof KeyringNode, 'Unsupported type.');
        readOnlyProperty(this, 'keyring', keyring);
    }
    async getEncryptionMaterials({ suite, encryptionContext, commitmentPolicy, }) {
        suite =
            suite ||
                new NodeAlgorithmSuite(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.
         */
        needs(!Object.prototype.hasOwnProperty.call(encryptionContext, ENCODED_SIGNER_KEY), `Reserved encryptionContext value ${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`
         */
        needs(material.getUnencryptedDataKey(), 'Unencrypted data key is invalid.');
        /* Postcondition: The NodeEncryptionMaterial must contain at least 1 EncryptedDataKey. */
        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.
         */
        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 NodeEncryptionMaterial(suite, encryptionContext);
        const ecdh = createECDH(namedCurve);
        ecdh.generateKeys();
        // @ts-ignore I want a compressed buffer.
        const compressPoint = ecdh.getPublicKey(undefined, 'compressed');
        const privateKey = ecdh.getPrivateKey();
        const signatureKey = new SignatureKey(privateKey, new Uint8Array(compressPoint), suite);
        return new NodeEncryptionMaterial(suite, {
            ...encryptionContext,
            [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. */
            needs(!Object.prototype.hasOwnProperty.call(encryptionContext, 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 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 { [ENCODED_SIGNER_KEY]: compressPoint } = encryptionContext;
        /* Precondition: NodeDefaultCryptographicMaterialsManager The context must contain the public key. */
        needs(compressPoint, 'Context does not contain required public key.');
        const publicKeyBytes = VerificationKey.decodeCompressPoint(Buffer.from(compressPoint, 'base64'), suite);
        return new NodeDecryptionMaterial(suite, encryptionContext).setVerificationKey(new VerificationKey(publicKeyBytes, suite));
    }
}
immutableClass(NodeDefaultCryptographicMaterialsManager);
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm9kZV9jcnlwdG9ncmFwaGljX21hdGVyaWFsc19tYW5hZ2VyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL25vZGVfY3J5cHRvZ3JhcGhpY19tYXRlcmlhbHNfbWFuYWdlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxvRUFBb0U7QUFDcEUsc0NBQXNDO0FBRXRDLE9BQU8sRUFLTCxrQkFBa0IsRUFDbEIsc0JBQXNCLEVBQ3RCLHNCQUFzQixFQUN0QixZQUFZLEVBQ1osS0FBSyxFQUNMLGVBQWUsRUFDZixjQUFjLEVBQ2QsZ0JBQWdCLEVBQ2hCLFdBQVcsRUFHWCxzQkFBc0IsR0FDdkIsTUFBTSxpQ0FBaUMsQ0FBQTtBQUV4QyxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQTtBQUUxRCxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sUUFBUSxDQUFBO0FBUW5DOzs7O0dBSUc7QUFDSCxNQUFNLE9BQU8sd0NBQXdDO0lBSW5ELFlBQVksT0FBb0I7UUFDOUIsbURBQW1EO1FBQ25ELEtBQUssQ0FBQyxPQUFPLFlBQVksV0FBVyxFQUFFLG1CQUFtQixDQUFDLENBQUE7UUFDMUQsZ0JBQWdCLENBQUMsSUFBSSxFQUFFLFNBQVMsRUFBRSxPQUFPLENBQUMsQ0FBQTtJQUM1QyxDQUFDO0lBRUQsS0FBSyxDQUFDLHNCQUFzQixDQUFDLEVBQzNCLEtBQUssRUFDTCxpQkFBaUIsRUFDakIsZ0JBQWdCLEdBQ007UUFDdEIsS0FBSztZQUNILEtBQUs7Z0JBQ0wsSUFBSSxrQkFBa0IsQ0FDcEIsc0JBQXNCLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxxQkFBcUIsQ0FDL0QsQ0FBQTtRQUVIOzs7OztXQUtHO1FBQ0gsS0FBSyxDQUNILENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUNuQyxpQkFBaUIsRUFDakIsa0JBQWtCLENBQ25CLEVBQ0Qsb0NBQW9DLGtCQUFrQixlQUFlLENBQ3RF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