browsec/trustlab/test/path-analysis.test.js

56 lines
2.7 KiB
JavaScript

import assert from "node:assert/strict";
import test from "node:test";
import { analyzeCertificatePaths } from "../src/path-analysis.js";
test("path analysis enumerates two valid issuer alternatives with attributed trust", () => {
const certificates = [cert("leaf", false), cert("intermediate-a"), cert("intermediate-b"), cert("root-a", true), cert("root-b", true)];
const relationships = [
link("leaf", "intermediate-a"), link("leaf", "intermediate-b"),
link("intermediate-a", "root-a"), link("intermediate-b", "root-b"),
];
const result = analyzeCertificatePaths(certificates, relationships, {
trustedCertificateSha256: ["root-a"],
});
assert.equal(result.paths.length, 2);
assert.equal(result.paths.find((path) => path.certificateSha256.includes("root-a")).status, "trusted");
assert.equal(result.paths.find((path) => path.certificateSha256.includes("root-b")).status, "untrusted");
});
test("path analysis explains rejected and missing issuer paths", () => {
const certificates = [cert("leaf", false), cert("wrong-issuer")];
const relationships = [{ ...link("leaf", "wrong-issuer"), signatureValid: false }];
const result = analyzeCertificatePaths(certificates, relationships);
assert.equal(result.paths[0].status, "incomplete");
assert.equal(result.paths[0].terminalReason, "no-acceptable-issuer");
assert.deepEqual(result.edges[0].reasons, ["signature-invalid"]);
});
test("path analysis rejects issuer certificates that cannot sign certificates", () => {
const issuer = { ...cert("issuer"), keyUsages: ["digitalSignature"] };
const result = analyzeCertificatePaths([cert("leaf", false), issuer], [link("leaf", "issuer")]);
assert.equal(result.edges[0].accepted, false);
assert.match(result.edges[0].reasons.join(" "), /key-usage/);
});
test("path validation explains an exceeded CA path-length constraint", () => {
const intermediate = cert("intermediate");
const root = { ...cert("root", true), pathLengthConstraint: 0 };
const result = analyzeCertificatePaths(
[cert("leaf", false), intermediate, root],
[link("leaf", "intermediate"), link("intermediate", "root")],
{ trustedCertificateSha256: ["root"] },
);
assert.equal(result.paths[0].status, "invalid");
assert.deepEqual(result.paths[0].validationFailures.map((failure) => failure.code), ["path-length-constraint-exceeded"]);
});
function cert(sha256, selfSigned = false) {
return { sha256, subject: sha256, isCa: sha256 !== "leaf", keyUsages: ["keyCertSign"], selfSigned, unsupportedCriticalExtensions: [] };
}
function link(childSha256, issuerSha256) {
return { childSha256, issuerSha256, issuerNameMatches: true, signatureValid: true, authorityKeyMatches: true };
}