"use strict";
/**
 * PKI.js Ed25519/Ed448 Support Patch
 *
 * This module patches PKI.js to add complete Ed25519/Ed448 support for certificate
 * and OCSP response verification. While PKI.js has some Ed25519/Ed448 support,
 * it currently lacks:
 * - getHashAlgorithm() support for Ed25519/Ed448 OIDs
 * - getAlgorithmByOID() recognition of Ed25519/Ed448
 * - Certificate verification using Ed25519/Ed448 signatures
 * - OCSP response signature verification with Ed25519/Ed448
 *
 * This patch must be loaded before any module that uses PKI.js (including easy-ocsp).
 */
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.applyEd25519Patch = applyEd25519Patch;
const pkijs = __importStar(require("pkijs"));
const node_crypto_1 = require("node:crypto");
// Ed25519/Ed448 OIDs (these are standardized object identifiers, not IP addresses)
const ED25519_OID = '1.3.101.112';
const ED448_OID = '1.3.101.113';
// Algorithm names as constants
const ED25519_NAME = 'Ed25519';
const ED448_NAME = 'Ed448';
// Apply patches only once
let patchesApplied = false;
function isEd25519OrEd448(oid) {
    return oid === ED25519_OID || oid === ED448_OID;
}
function isEdDSAAlgorithmName(name) {
    return name === ED25519_NAME || name === ED448_NAME;
}
function getEdDSAAlgorithmName(oid) {
    return oid === ED25519_OID ? ED25519_NAME : ED448_NAME;
}
function applyEd25519Patch() {
    if (patchesApplied)
        return;
    patchesApplied = true;
    const CryptoEngine = pkijs.CryptoEngine.prototype;
    const Certificate = pkijs.Certificate.prototype;
    // Store original methods
    const originals = {
        getHashAlgorithm: CryptoEngine.getHashAlgorithm,
        getAlgorithmByOID: CryptoEngine.getAlgorithmByOID,
        getAlgorithmParameters: CryptoEngine.getAlgorithmParameters,
        verifyWithPublicKey: CryptoEngine.verifyWithPublicKey,
        certificateVerify: Certificate.verify,
        getPublicKey: Certificate.getPublicKey,
    };
    // Patch getHashAlgorithm - Ed25519/Ed448 don't use separate hashes
    CryptoEngine.getHashAlgorithm = function (...params) {
        const [signatureAlgorithm] = params;
        if (isEd25519OrEd448(signatureAlgorithm.algorithmId)) {
            // EdDSA signatures have built-in hash functions per RFC 8032:
            // - Ed25519 uses SHA-512 internally (Section 5.1.6)
            // - Ed448 uses SHAKE256 internally (Section 5.2.6)
            // The hash is not a parameter - it's part of the algorithm definition.
            // Returning a placeholder since PKI.js expects a string, but our patched
            // verification methods bypass any code that would use this value.
            return 'UNUSED-EDDSA-BUILTIN-HASH';
        }
        return originals.getHashAlgorithm.call(this, signatureAlgorithm);
    };
    // Patch getAlgorithmByOID to recognize Ed25519/Ed448
    CryptoEngine.getAlgorithmByOID = function (...params) {
        const [oid] = params;
        if (isEd25519OrEd448(oid)) {
            return { name: getEdDSAAlgorithmName(oid) };
        }
        return originals.getAlgorithmByOID.call(this, ...params);
    };
    // Patch getAlgorithmParameters
    CryptoEngine.getAlgorithmParameters = function (...params) {
        const [algorithmName, operation] = params;
        if (isEdDSAAlgorithmName(algorithmName)) {
            return {
                algorithm: { name: algorithmName },
                usages: operation === 'sign' ? ['sign'] : ['verify'],
            };
        }
        return originals.getAlgorithmParameters.call(this, ...params);
    };
    // Patch getPublicKey for Ed25519/Ed448
    Certificate.getPublicKey = async function (...params) {
        const [, cryptoEngine = pkijs.getCrypto(true)] = params;
        const algId = this.subjectPublicKeyInfo.algorithm.algorithmId;
        if (isEd25519OrEd448(algId)) {
            const algorithmName = getEdDSAAlgorithmName(algId);
            return cryptoEngine.importKey('spki', this.subjectPublicKeyInfo.toSchema().toBER(false), algorithmName, true, [
                'verify',
            ]);
        }
        return originals.getPublicKey.call(this, ...params);
    };
    // Patch Certificate.verify for Ed25519/Ed448
    Certificate.verify = async function (...params) {
        const [issuerCertificate] = params;
        if (isEd25519OrEd448(this.signatureAlgorithm.algorithmId)) {
            try {
                // Use Node.js X509Certificate for Ed25519/Ed448 verification
                const certDer = this.toSchema().toBER(false);
                const issuerDer = issuerCertificate.toSchema().toBER(false);
                const nodeCert = new node_crypto_1.X509Certificate(Buffer.from(certDer));
                const nodeIssuer = new node_crypto_1.X509Certificate(Buffer.from(issuerDer));
                return nodeCert.verify(nodeIssuer.publicKey);
            }
            catch {
                // Any failure in verification should return false
                return false;
            }
        }
        return originals.certificateVerify.call(this, ...params);
    };
    // Patch verifyWithPublicKey for OCSP response verification
    if (originals.verifyWithPublicKey) {
        CryptoEngine.verifyWithPublicKey = async function (...params) {
            const [data, signature, publicKeyInfo] = params;
            const algId = publicKeyInfo.algorithm.algorithmId;
            if (isEd25519OrEd448(algId)) {
                const algorithmName = getEdDSAAlgorithmName(algId);
                try {
                    // Get crypto.subtle from available sources
                    const cryptoSubtle = this.crypto?.subtle || this.subtle || pkijs.getCrypto(true)?.subtle || node_crypto_1.webcrypto?.subtle;
                    if (!cryptoSubtle) {
                        throw new Error('No crypto.subtle available');
                    }
                    // Import the public key
                    const publicKey = await cryptoSubtle.importKey('spki', publicKeyInfo.toSchema().toBER(false), algorithmName, false, ['verify']);
                    // Handle BIT STRING signature value
                    let signatureValue = signature.valueBlock.valueHexView;
                    // Check if this is a BIT STRING with unused bits
                    if ('unusedBits' in signature.valueBlock && signature.valueBlock.unusedBits > 0) {
                        signatureValue = signatureValue.slice(0, signatureValue.length - 1);
                    }
                    // Verify the signature
                    return await cryptoSubtle.verify(algorithmName, publicKey, signatureValue, data);
                }
                catch {
                    // Any failure in verification should return false
                    return false;
                }
            }
            return originals.verifyWithPublicKey.call(this, ...params);
        };
    }
}
// Apply patch on module load
applyEd25519Patch();
//# sourceMappingURL=pkijs-ed25519-patch.js.map