browsec/trustlab/test/der-explorer.test.js

52 lines
2.3 KiB
JavaScript

import assert from "node:assert/strict";
import test from "node:test";
import { exploreCertificateDer } from "../src/der-explorer.js";
test("DER explorer extracts Basic Constraints and Key Usage with offsets", () => {
const basicConstraints = extension("551d13", "30030101ff");
const keyUsage = extension("551d0f", "03020106", true);
const extensions = tlv("30", basicConstraints + keyUsage);
const tbs = tlv("30", tlv("a3", extensions));
const certificate = bytes(tlv("30", tbs));
const result = exploreCertificateDer(certificate);
assert.equal(result.byteLength, certificate.length);
assert.equal(result.derived.isCa, true);
assert.deepEqual(result.derived.keyUsages, ["keyCertSign", "crlSign"]);
assert.equal(result.extensions[1].critical, true);
assert.deepEqual(result.derived.unsupportedCriticalExtensions, []);
assert.ok(result.extensions.every((item) => item.offset < item.valueOffset));
});
test("DER explorer rejects indefinite, truncated, and excessively nested input", () => {
assert.throws(() => exploreCertificateDer(bytes("30800000")), /Indefinite length/);
assert.throws(() => exploreCertificateDer(bytes("300301")), /exceeds its container/);
let nested = "0500";
for (let index = 0; index < 34; index++) nested = tlv("30", nested);
assert.throws(() => exploreCertificateDer(bytes(nested)), /nesting limit/);
});
test("an understood name does not make an unsupported critical extension safe", () => {
const policies = extension("551d20", "3000", true);
const certificate = bytes(tlv("30", tlv("30", tlv("a3", tlv("30", policies)))));
const result = exploreCertificateDer(certificate);
assert.equal(result.extensions[0].name, "Certificate Policies");
assert.equal(result.extensions[0].known, true);
assert.equal(result.extensions[0].supported, false);
assert.deepEqual(result.derived.unsupportedCriticalExtensions, ["2.5.29.32"]);
});
function extension(oidHex, valueHex, critical = false) {
return tlv("30", tlv("06", oidHex) + (critical ? "0101ff" : "") + tlv("04", valueHex));
}
function tlv(tag, value) {
const length = value.length / 2;
if (length >= 128) throw new Error("test helper supports short lengths only");
return `${tag}${length.toString(16).padStart(2, "0")}${value}`;
}
function bytes(hex) { return Uint8Array.from(hex.match(/../g).map((pair) => Number.parseInt(pair, 16))); }