Add bounded DER certificate explorer
This commit is contained in:
1 parent
be751f4b51
commit
216afb6c18
10 files changed
+384
-12
No files matched your search
@@ -0,0 +1,51 @@
|
||||
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))); }
|
||||
Reference in new issue
Block a user