/**
 * KMS-backed Signing
 *
 * Alternative to Sigstore for air-gapped deployments.
 * Supports AWS KMS, GCP KMS, and HashiCorp Vault.
 *
 * @module enterprise/signing/kms
 */
import { createHash, createSign, createVerify } from "crypto";
// ============================================================================
// AWS KMS Client
// ============================================================================
/**
 * AWS KMS signing client
 */
export class AWSKMSClient {
    config;
    constructor(config) {
        if (config.provider !== "aws") {
            throw new Error("AWSKMSClient requires provider: 'aws'");
        }
        this.config = config;
    }
    /**
     * Sign content using AWS KMS
     */
    async sign(content) {
        const digest = createHash("sha256").update(content).digest();
        const digestBase64 = digest.toString("base64");
        // Build AWS Signature Version 4 request
        const body = JSON.stringify({
            KeyId: this.config.keyId,
            Message: digestBase64,
            MessageType: "DIGEST",
            SigningAlgorithm: "RSASSA_PKCS1_V1_5_SHA_256",
        });
        const response = await this.kmsRequest("Sign", body);
        const data = (await response.json());
        return {
            content,
            digest: digest.toString("hex"),
            signature: data.Signature,
            provider: "aws",
            keyId: data.KeyId,
            signedAt: new Date().toISOString(),
            algorithm: "RSASSA_PKCS1_V1_5_SHA_256",
        };
    }
    /**
     * Verify signature using AWS KMS
     */
    async verify(artifact) {
        const digest = createHash("sha256").update(artifact.content).digest();
        const digestBase64 = digest.toString("base64");
        const body = JSON.stringify({
            KeyId: this.config.keyId,
            Message: digestBase64,
            MessageType: "DIGEST",
            Signature: artifact.signature,
            SigningAlgorithm: artifact.algorithm,
        });
        try {
            const response = await this.kmsRequest("Verify", body);
            const data = (await response.json());
            return {
                valid: data.SignatureValid,
                keyId: this.config.keyId,
                verifiedAt: new Date().toISOString(),
            };
        }
        catch (error) {
            return {
                valid: false,
                keyId: this.config.keyId,
                error: error instanceof Error ? error.message : String(error),
                verifiedAt: new Date().toISOString(),
            };
        }
    }
    /**
     * Make AWS KMS API request
     */
    async kmsRequest(action, body) {
        const { region, accessKeyId, secretAccessKey, sessionToken } = this.config.aws || {};
        if (!region) {
            throw new Error("AWS region required");
        }
        const url = `https://kms.${region}.amazonaws.com/`;
        const host = `kms.${region}.amazonaws.com`;
        const date = new Date();
        const amzDate = date.toISOString().replace(/[:-]|\.\d{3}/g, "");
        const dateStamp = amzDate.slice(0, 8);
        // Build headers
        const headers = {
            "Content-Type": "application/x-amz-json-1.1",
            "X-Amz-Target": `TrentService.${action}`,
            "X-Amz-Date": amzDate,
            Host: host,
        };
        if (sessionToken) {
            headers["X-Amz-Security-Token"] = sessionToken;
        }
        // Sign request with SigV4 (simplified - production would use full SigV4)
        if (accessKeyId && secretAccessKey) {
            const signature = this.signRequest("POST", "/", headers, body, accessKeyId, secretAccessKey, region, dateStamp);
            headers["Authorization"] = signature;
        }
        const response = await fetch(url, {
            method: "POST",
            headers,
            body,
        });
        if (!response.ok) {
            const error = await response.text();
            throw new Error(`AWS KMS error: ${error}`);
        }
        return response;
    }
    /**
     * Sign AWS request (simplified SigV4)
     */
    signRequest(_method, _path, headers, _body, accessKeyId, _secretAccessKey, _region, _dateStamp) {
        // Note: This is a simplified version - production would implement full SigV4
        // For real implementation, use @aws-sdk/signature-v4
        const credential = `${accessKeyId}/${headers["X-Amz-Date"]?.slice(0, 8)}/us-east-1/kms/aws4_request`;
        return `AWS4-HMAC-SHA256 Credential=${credential}, SignedHeaders=content-type;host;x-amz-date;x-amz-target, Signature=PLACEHOLDER`;
    }
}
// ============================================================================
// GCP KMS Client
// ============================================================================
/**
 * GCP KMS signing client
 */
export class GCPKMSClient {
    config;
    accessToken = null;
    constructor(config) {
        if (config.provider !== "gcp") {
            throw new Error("GCPKMSClient requires provider: 'gcp'");
        }
        this.config = config;
    }
    /**
     * Sign content using GCP KMS
     */
    async sign(content) {
        const digest = createHash("sha256").update(content).digest("base64");
        const { projectId, locationId, keyRingId } = this.config.gcp || {};
        const keyName = `projects/${projectId}/locations/${locationId}/keyRings/${keyRingId}/cryptoKeys/${this.config.keyId}/cryptoKeyVersions/1`;
        const response = await this.kmsRequest(`${keyName}:asymmetricSign`, {
            digest: { sha256: digest },
        });
        const data = (await response.json());
        return {
            content,
            digest: createHash("sha256").update(content).digest("hex"),
            signature: data.signature,
            provider: "gcp",
            keyId: keyName,
            signedAt: new Date().toISOString(),
            algorithm: "RSA_SIGN_PKCS1_256",
        };
    }
    /**
     * Verify signature using GCP KMS
     */
    async verify(artifact) {
        const digest = createHash("sha256").update(artifact.content).digest("base64");
        try {
            const response = await this.kmsRequest(`${artifact.keyId}:asymmetricVerify`, {
                digest: { sha256: digest },
                signature: artifact.signature,
            });
            const data = (await response.json());
            return {
                valid: data.success,
                keyId: artifact.keyId,
                verifiedAt: new Date().toISOString(),
            };
        }
        catch (error) {
            return {
                valid: false,
                keyId: artifact.keyId,
                error: error instanceof Error ? error.message : String(error),
                verifiedAt: new Date().toISOString(),
            };
        }
    }
    /**
     * Make GCP KMS API request
     */
    async kmsRequest(path, body) {
        const token = await this.getAccessToken();
        const response = await fetch(`https://cloudkms.googleapis.com/v1/${path}`, {
            method: "POST",
            headers: {
                Authorization: `Bearer ${token}`,
                "Content-Type": "application/json",
            },
            body: JSON.stringify(body),
        });
        if (!response.ok) {
            const error = await response.text();
            throw new Error(`GCP KMS error: ${error}`);
        }
        return response;
    }
    /**
     * Get GCP access token
     */
    async getAccessToken() {
        if (this.accessToken) {
            return this.accessToken;
        }
        // Try metadata server (for GCE/Cloud Run/etc.)
        try {
            const response = await fetch("http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token", {
                headers: { "Metadata-Flavor": "Google" },
            });
            if (response.ok) {
                const data = (await response.json());
                this.accessToken = data.access_token;
                return this.accessToken;
            }
        }
        catch {
            // Fall through to other methods
        }
        // Try application default credentials
        const gcloudToken = process.env.GOOGLE_APPLICATION_CREDENTIALS;
        if (gcloudToken) {
            // Would parse service account and generate JWT - simplified here
            throw new Error("Service account authentication not implemented - use metadata server");
        }
        throw new Error("No GCP credentials available");
    }
}
// ============================================================================
// HashiCorp Vault Client
// ============================================================================
/**
 * HashiCorp Vault signing client
 */
export class VaultClient {
    config;
    constructor(config) {
        if (config.provider !== "vault") {
            throw new Error("VaultClient requires provider: 'vault'");
        }
        this.config = config;
    }
    /**
     * Sign content using Vault Transit
     */
    async sign(content) {
        const { address, token, namespace, mountPath = "transit" } = this.config.vault || {};
        const digest = createHash("sha256").update(content).digest("base64");
        const response = await fetch(`${address}/v1/${mountPath}/sign/${this.config.keyId}/sha2-256`, {
            method: "POST",
            headers: {
                "X-Vault-Token": token,
                "X-Vault-Namespace": namespace,
                "Content-Type": "application/json",
            },
            body: JSON.stringify({ input: digest }),
        });
        if (!response.ok) {
            const error = await response.text();
            throw new Error(`Vault error: ${error}`);
        }
        const data = (await response.json());
        return {
            content,
            digest: createHash("sha256").update(content).digest("hex"),
            signature: data.data.signature,
            provider: "vault",
            keyId: this.config.keyId,
            signedAt: new Date().toISOString(),
            algorithm: "sha2-256",
            keyVersion: String(data.data.key_version),
        };
    }
    /**
     * Verify signature using Vault Transit
     */
    async verify(artifact) {
        const { address, token, namespace, mountPath = "transit" } = this.config.vault || {};
        const digest = createHash("sha256").update(artifact.content).digest("base64");
        try {
            const response = await fetch(`${address}/v1/${mountPath}/verify/${artifact.keyId}/sha2-256`, {
                method: "POST",
                headers: {
                    "X-Vault-Token": token,
                    "X-Vault-Namespace": namespace,
                    "Content-Type": "application/json",
                },
                body: JSON.stringify({
                    input: digest,
                    signature: artifact.signature,
                }),
            });
            if (!response.ok) {
                throw new Error("Verification failed");
            }
            const data = (await response.json());
            return {
                valid: data.data.valid,
                keyId: artifact.keyId,
                verifiedAt: new Date().toISOString(),
            };
        }
        catch (error) {
            return {
                valid: false,
                keyId: artifact.keyId,
                error: error instanceof Error ? error.message : String(error),
                verifiedAt: new Date().toISOString(),
            };
        }
    }
}
// ============================================================================
// Local Key Client (for testing)
// ============================================================================
/**
 * Local key signing client (for testing/development)
 */
export class LocalKeyClient {
    config;
    constructor(config) {
        if (config.provider !== "local") {
            throw new Error("LocalKeyClient requires provider: 'local'");
        }
        if (!config.local?.privateKeyPem || !config.local?.publicKeyPem) {
            throw new Error("LocalKeyClient requires privateKeyPem and publicKeyPem");
        }
        this.config = config;
    }
    /**
     * Sign content using local private key
     */
    async sign(content) {
        const sign = createSign("SHA256");
        sign.update(content);
        sign.end();
        const signature = sign.sign(this.config.local.privateKeyPem, "base64");
        return {
            content,
            digest: createHash("sha256").update(content).digest("hex"),
            signature,
            provider: "local",
            keyId: this.config.keyId,
            signedAt: new Date().toISOString(),
            algorithm: "RSA-SHA256",
        };
    }
    /**
     * Verify signature using local public key
     */
    async verify(artifact) {
        try {
            const verify = createVerify("SHA256");
            verify.update(artifact.content);
            verify.end();
            const valid = verify.verify(this.config.local.publicKeyPem, artifact.signature, "base64");
            return {
                valid,
                keyId: artifact.keyId,
                verifiedAt: new Date().toISOString(),
            };
        }
        catch (error) {
            return {
                valid: false,
                keyId: artifact.keyId,
                error: error instanceof Error ? error.message : String(error),
                verifiedAt: new Date().toISOString(),
            };
        }
    }
}
// ============================================================================
// Unified KMS Client
// ============================================================================
/**
 * Unified KMS client
 */
export class KMSClient {
    client;
    provider;
    constructor(config) {
        this.provider = config.provider;
        switch (config.provider) {
            case "aws":
                this.client = new AWSKMSClient(config);
                break;
            case "gcp":
                this.client = new GCPKMSClient(config);
                break;
            case "vault":
                this.client = new VaultClient(config);
                break;
            case "local":
                this.client = new LocalKeyClient(config);
                break;
            default:
                throw new Error(`Unsupported KMS provider: ${config.provider}`);
        }
    }
    /**
     * Sign content
     */
    async sign(content) {
        return this.client.sign(content);
    }
    /**
     * Verify signature
     */
    async verify(artifact) {
        return this.client.verify(artifact);
    }
    /**
     * Get provider name
     */
    getProvider() {
        return this.provider;
    }
}
// ============================================================================
// Factory Functions
// ============================================================================
/**
 * Create KMS client
 */
export function createKMSClient(config) {
    return new KMSClient(config);
}
/**
 * Create AWS KMS client
 */
export function createAWSKMSClient(keyId, options) {
    return new AWSKMSClient({
        provider: "aws",
        keyId,
        aws: options,
    });
}
/**
 * Create GCP KMS client
 */
export function createGCPKMSClient(keyId, options) {
    return new GCPKMSClient({
        provider: "gcp",
        keyId,
        gcp: options,
    });
}
/**
 * Create Vault client
 */
export function createVaultClient(keyId, options) {
    return new VaultClient({
        provider: "vault",
        keyId,
        vault: options,
    });
}
/**
 * Create local key client (for testing)
 */
export function createLocalKeyClient(keyId, privateKeyPem, publicKeyPem) {
    return new LocalKeyClient({
        provider: "local",
        keyId,
        local: { privateKeyPem, publicKeyPem },
    });
}
//# sourceMappingURL=kms.js.map