// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
import { RSA_PKCS1_OAEP_PADDING, RSA_PKCS1_PADDING } from "constants";
import { publicEncrypt } from "node:crypto";
import { createVerify } from "./crypto.js";
import { convertJWKtoPEM } from "./conversions.js";
import { LocalCryptographyUnsupportedError } from "./models.js";
/**
 * An RSA cryptography provider supporting RSA algorithms.
 */
export class RsaCryptographyProvider {
    constructor(key) {
        this.key = key;
    }
    isSupported(algorithm, operation) {
        return (this.applicableAlgorithms.includes(algorithm) && this.applicableOperations.includes(operation));
    }
    encrypt(encryptParameters, _options) {
        this.ensureValid();
        const keyPEM = convertJWKtoPEM(this.key);
        const padding = encryptParameters.algorithm === "RSA1_5" ? RSA_PKCS1_PADDING : RSA_PKCS1_OAEP_PADDING;
        return Promise.resolve({
            algorithm: encryptParameters.algorithm,
            keyID: this.key.kid,
            result: publicEncrypt({ key: keyPEM, padding: padding }, Buffer.from(encryptParameters.plaintext)),
        });
    }
    decrypt(_decryptParameters, _options) {
        throw new LocalCryptographyUnsupportedError("Decrypting using a local JsonWebKey is not supported.");
    }
    wrapKey(algorithm, keyToWrap, _options) {
        this.ensureValid();
        const keyPEM = convertJWKtoPEM(this.key);
        const padding = algorithm === "RSA1_5" ? RSA_PKCS1_PADDING : RSA_PKCS1_OAEP_PADDING;
        return Promise.resolve({
            algorithm: algorithm,
            result: publicEncrypt({ key: keyPEM, padding }, Buffer.from(keyToWrap)),
            keyID: this.key.kid,
        });
    }
    unwrapKey(_algorithm, _encryptedKey, _options) {
        throw new LocalCryptographyUnsupportedError("Unwrapping a key using a local JsonWebKey is not supported.");
    }
    sign(_algorithm, _digest, _options) {
        throw new LocalCryptographyUnsupportedError("Signing a digest using a local JsonWebKey is not supported.");
    }
    signData(_algorithm, _data, _options) {
        throw new LocalCryptographyUnsupportedError("Signing a block of data using a local JsonWebKey is not supported.");
    }
    async verify(_algorithm, _digest, _signature, _options) {
        throw new LocalCryptographyUnsupportedError("Verifying a digest using a local JsonWebKey is not supported.");
    }
    verifyData(algorithm, data, signature, _options) {
        this.ensureValid();
        const keyPEM = convertJWKtoPEM(this.key);
        const verifier = createVerify(algorithm, data);
        return Promise.resolve({
            result: verifier.verify(keyPEM, Buffer.from(signature)),
            keyID: this.key.kid,
        });
    }
    /**
     * The {@link JsonWebKey} used to perform crypto operations.
     */
    key;
    /**
     * The set of algorithms this provider supports
     */
    applicableAlgorithms = [
        "RSA1_5",
        "RSA-OAEP",
        "PS256",
        "RS256",
        "PS384",
        "RS384",
        "PS512",
        "RS512",
    ];
    /**
     * The set of operations this provider supports
     */
    applicableOperations = [
        "encrypt",
        "wrapKey",
        "verifyData",
    ];
    /**
     * Mapping between signature algorithms and their corresponding hash algorithms. Externally used for testing.
     * @internal
     */
    signatureAlgorithmToHashAlgorithm = {
        PS256: "SHA256",
        RS256: "SHA256",
        PS384: "SHA384",
        RS384: "SHA384",
        PS512: "SHA512",
        RS512: "SHA512",
    };
    ensureValid() {
        if (this.key &&
            this.key.kty?.toUpperCase() !== "RSA" &&
            this.key.kty?.toUpperCase() !== "RSA-HSM") {
            throw new Error("Key type does not match the algorithm RSA");
        }
    }
}
//# sourceMappingURL=rsaCryptographyProvider.js.map