import { describe, expect, it } from "@suaveplan/testing/runner"; import { UNIVERSAL_TAGS } from "../asn1/asn1.types.js"; import { encodeAsn1, makeConstructed, makePrimitive } from "../asn1/encoder.js"; import { encodeOid } from "../asn1/oid.js"; import { X509Error } from "../errors/error-codes.js"; import { decodeExtendedKeyUsage, EKU_OID_TO_NAME, } from "./extended-key-usage.js"; function ekuDer(oids: string[]): Uint8Array { return encodeAsn1( makeConstructed( "universal", UNIVERSAL_TAGS.SEQUENCE, oids.map((o) => makePrimitive( "universal", UNIVERSAL_TAGS.OBJECT_IDENTIFIER, encodeOid(o) ) ) ) ); } describe("decodeExtendedKeyUsage", () => { it("recognises anyExtendedKeyUsage as wildcard", { timeout: 5000 }, () => { const eku = decodeExtendedKeyUsage(ekuDer(["2.5.29.37.0"])); expect(eku.purposes).toContain("anyExtendedKeyUsage"); }); it("maps server/client/code/email/timestamp/OCSP OIDs to friendly names", { timeout: 5000, }, () => { const eku = decodeExtendedKeyUsage( ekuDer([ "1.3.6.1.5.5.7.3.1", "1.3.6.1.5.5.7.3.2", "1.3.6.1.5.5.7.3.3", "1.3.6.1.5.5.7.3.4", "1.3.6.1.5.5.7.3.8", "1.3.6.1.5.5.7.3.9", ]) ); expect(eku.purposes).toEqual([ "serverAuth", "clientAuth", "codeSigning", "emailProtection", "timeStamping", "OCSPSigning", ]); }); it("preserves an unrecognised OID verbatim", { timeout: 5000 }, () => { const eku = decodeExtendedKeyUsage(ekuDer(["1.2.3.4.5"])); expect(eku.purposes).toEqual(["1.2.3.4.5"]); }); it("rejects non-SEQUENCE input", { timeout: 5000 }, () => { expect(() => decodeExtendedKeyUsage(new Uint8Array([0x02, 0x01, 0x00])) ).toThrowError(X509Error); }); it("rejects non-OID children", { timeout: 5000 }, () => { const bad = encodeAsn1( makeConstructed("universal", UNIVERSAL_TAGS.SEQUENCE, [ makePrimitive( "universal", UNIVERSAL_TAGS.INTEGER, new Uint8Array([1]) ), ]) ); expect(() => decodeExtendedKeyUsage(bad)).toThrow(); }); it("exposes the static EKU OID → name map", { timeout: 5000 }, () => { expect(EKU_OID_TO_NAME["2.5.29.37.0"]).toBe("anyExtendedKeyUsage"); }); });