import assert from "node:assert";
import { describe, it } from "node:test";
import { isValidationError, parseAndValidateCaCertificate, validateName, } from "./validation.js";
const CA_PEM = `-----BEGIN CERTIFICATE-----
MIIC5jCCAc6gAwIBAgIUB4s5BPjuGshWHSZKkNIJJ7W7alkwDQYJKoZIhvcNAQEL
BQAwEjEQMA4GA1UEAwwHVGVzdCBjYTAgFw0yNjA1MTMwMDA1NDFaGA8yMTI2MDQx
OTAwMDU0MVowEjEQMA4GA1UEAwwHVGVzdCBjYTCCASIwDQYJKoZIhvcNAQEBBQAD
ggEPADCCAQoCggEBAK+8kcIOYXC5SKCnnEmddLKiVSon8NoLn8RABel0op+5i3J2
pnDBBWOy2nT5qWRI2N0tTK4tQn/jaGeiBP0BUu4z+Y/pcglveexyFWhtFstHyyUr
yiwhBhX3NEWHZGr/VShriKxojnTwWONpgQwq7On7k+We3JK7IEASvKLxhC1+hcch
CwP67zGDF6qJrfjBfdPSRoW8OomioTRyb7MyrWvRpKm/0rj9NYc7MxMYbgVffE6y
IVQ4UCsVw74DdebfdzBSJOwNa+2Fe8AwQ3QMVbzfE3qs6+nviQ1EJA/h0kWgIrCI
3JvGpJinI0kDXEYx/4BTHVNfg1UdCOqPxxdrS18CAwEAAaMyMDAwDwYDVR0TAQH/
BAUwAwEB/zAdBgNVHQ4EFgQUuku+yW29ASY8vCZ7fBVA6L3r28YwDQYJKoZIhvcN
AQELBQADggEBAFaYAde91xdpST+LlokhbWanr8xiUr7jdHemjxGvBi/Zxs2VQIj2
+1Bh0dpxGk670nSc/Bq8jcivoiGoaRxT5rFVhtQOpYLgo+wKqNoYfEoEPrIrT4PO
seBrdMa9cduhs/Nx11Vgf5N56KomRO1a4AaIcvh6uGxrf1jfaCjaAKWTNNd9luzo
/IsRikl4QN0pZ1lIxdOdVMFhCp8V/+oEO6aw2FhFZlZKA+XLELHQzPBpuubQocuT
9dLovPbpFD2UwgvpjXQYjpr5btZx+iupHfiXq7WI6EI3eG5UgTuOpK8g9rLDiX9f
ArcSyj6/ZV+MDtaEHyEJBdsp//aT6Kfpoek=
-----END CERTIFICATE-----
`;
const LEAF_PEM = `-----BEGIN CERTIFICATE-----
MIIC5zCCAc+gAwIBAgIUFG0P6P6J4YoBLyRH2pjt7RdV9sAwDQYJKoZIhvcNAQEL
BQAwFDESMBAGA1UEAwwJVGVzdCBsZWFmMCAXDTI2MDUxMzAwMDU0MVoYDzIxMjYw
NDE5MDAwNTQxWjAUMRIwEAYDVQQDDAlUZXN0IGxlYWYwggEiMA0GCSqGSIb3DQEB
AQUAA4IBDwAwggEKAoIBAQDc1H+Z9qbmSsTR1tDVEvMN94ayec1UZ/17eIDY55ho
N5UA3Blho2xLeXvWWpKpo6wTXONzpNak8qhccIGsuIogpparkYYPBG+86cofnGDC
m/T9wa8eLTvyrIyPfUjkYVU7Gfmsq08pF/GZHIHcJg/xdTOLKE8WgJi15zwi1ZOE
z/OtpGKlX2pnM7aq6mzUqamWo2WBPpFdtdLfCBtnUkoNtxWmn98Xj/AaoiBR0UAI
C8UQAEAv3yaZ8pBZoLLn68kFgkOdNAPnX2zi6B6uk7LWA90JUneL+fPb/89muxl+
uQ4NGgWINtG23OtELLtUIuNiZxEFEO0mxf+0pIYa/1VTAgMBAAGjLzAtMAwGA1Ud
EwEB/wQCMAAwHQYDVR0OBBYEFP5YdepOBrpmYPdem5awTb3ByLZ7MA0GCSqGSIb3
DQEBCwUAA4IBAQBZ9Bl8IcQ9VYxTQgO1U9wB+LcHJ2WXqVSQTlz+qwd+tyfnv0PM
O5/ouSYiCj3IBQ42N3z+QhLgZgvfGcC6qFvG67A1WV7n7ZV5D7Yb9CqE+NPUbx3V
3GFBkIAv7U+4TKYPSK2YPXCb/D3rtel2j31tcMtODoT0LrHbwaOCGd8G+15rxBjP
dfHuC/nYYeKsplDhcdfemel73WbNzuqGNliQhEqhtlpGOhciHpd1Zlm7OgUINmCr
rfRfSGvBGDkuNRQIEhnFZXYhD0iCM/6D56/VykaqaQz+bPr04d0e0KvusFGsmapN
zC0Ztm1aNp0wB0vPNoEJrpQEmkB80cR1DXVR
-----END CERTIFICATE-----
`;
describe("validateName", () => {
    it("accepts valid names", () => {
        assert.strictEqual(validateName("my_ca"), null);
        assert.strictEqual(validateName("CA1"), null);
        assert.strictEqual(validateName("$abc"), null);
        assert.strictEqual(validateName("_underscore"), null);
    });
    it("rejects empty names", () => {
        const result = validateName("");
        assert.ok(result);
        assert.match(result.message, /empty/i);
    });
    it("rejects names over 120 characters", () => {
        const result = validateName("a".repeat(121));
        assert.ok(result);
        assert.match(result.message, /120 characters/);
    });
    it("rejects names starting with a digit", () => {
        const result = validateName("1ca");
        assert.ok(result);
        assert.match(result.message, /JavaScript variable name/);
    });
    it("rejects names with hyphens or spaces", () => {
        assert.ok(validateName("my-ca"));
        assert.ok(validateName("my ca"));
        assert.ok(validateName("ca.example"));
    });
    it("rejects JavaScript reserved keywords", () => {
        for (const keyword of ["class", "delete", "import", "return", "await"]) {
            const result = validateName(keyword);
            assert.ok(result, `expected ${keyword} to be rejected`);
            assert.match(result.message, /reserved keyword/);
        }
    });
    it("rejects reserved keywords case-insensitively", () => {
        assert.ok(validateName("CLASS"));
        assert.ok(validateName("Delete"));
    });
});
describe("parseAndValidateCaCertificate", () => {
    it("rejects garbage input", () => {
        const result = parseAndValidateCaCertificate("not a certificate");
        assert.ok(isValidationError(result));
        assert.match(result.message, /PEM-encoded/);
        assert.match(result.hint ?? "", /openssl x509.*-inform der/);
    });
    it("rejects a PKCS#8 private key with a key-specific hint", () => {
        const pem = `-----BEGIN PRIVATE KEY-----\nfoo\n-----END PRIVATE KEY-----`;
        const result = parseAndValidateCaCertificate(pem);
        assert.ok(isValidationError(result));
        assert.match(result.message, /private key/i);
        assert.match(result.hint ?? "", /public CA certificate/);
    });
    it("rejects an RSA private key with a key-specific hint", () => {
        const pem = `-----BEGIN RSA PRIVATE KEY-----\nfoo\n-----END RSA PRIVATE KEY-----`;
        const result = parseAndValidateCaCertificate(pem);
        assert.ok(isValidationError(result));
        assert.match(result.message, /private key/i);
    });
    it("rejects a CSR with a CSR-specific hint", () => {
        const pem = `-----BEGIN CERTIFICATE REQUEST-----\nfoo\n-----END CERTIFICATE REQUEST-----`;
        const result = parseAndValidateCaCertificate(pem);
        assert.ok(isValidationError(result));
        assert.match(result.message, /CSR|signing request/i);
    });
    it("rejects a PEM-shaped but corrupt certificate", () => {
        const pem = `-----BEGIN CERTIFICATE-----\nnot-real-base64\n-----END CERTIFICATE-----`;
        const result = parseAndValidateCaCertificate(pem);
        assert.ok(isValidationError(result));
        assert.match(result.message, /Failed to parse/);
    });
    it("accepts a valid CA certificate", () => {
        const result = parseAndValidateCaCertificate(CA_PEM);
        assert.ok(!isValidationError(result), JSON.stringify(result));
        assert.strictEqual(result.isCa, true);
        assert.match(result.subject, /Test ca/i);
    });
    it("rejects a leaf (non-CA) certificate", () => {
        const result = parseAndValidateCaCertificate(LEAF_PEM);
        assert.ok(isValidationError(result));
        assert.match(result.message, /not a CA certificate/);
    });
    it("rejects a CA certificate that is expired relative to `now`", () => {
        const farFuture = new Date("2200-01-01T00:00:00Z");
        const result = parseAndValidateCaCertificate(CA_PEM, farFuture);
        assert.ok(isValidationError(result));
        assert.match(result.message, /expired/);
    });
});
//# sourceMappingURL=validation.test.js.map