Initial Commit
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
import { describe, expect, it } from "@suaveplan/testing/runner";
|
||||
import { UNIVERSAL_TAGS } from "./asn1.types.js";
|
||||
import { decodeAsn1 } from "./decoder.js";
|
||||
import { encodeAsn1, makeConstructed, makePrimitive } from "./encoder.js";
|
||||
|
||||
describe("encodeAsn1", () => {
|
||||
it("round-trips a primitive INTEGER", { timeout: 5000 }, () => {
|
||||
const bytes = new Uint8Array([0x02, 0x01, 0x05]);
|
||||
const back = encodeAsn1(decodeAsn1(bytes));
|
||||
expect(Array.from(back)).toEqual(Array.from(bytes));
|
||||
});
|
||||
|
||||
it("round-trips a nested SEQUENCE OF SET Name structure", {
|
||||
timeout: 5000,
|
||||
}, () => {
|
||||
// SEQUENCE { SET { SEQUENCE { OID 2.5.4.3, PrintableString "CN" } } }
|
||||
const oidBody = new Uint8Array([0x55, 0x04, 0x03]);
|
||||
const atv = makeConstructed("universal", UNIVERSAL_TAGS.SEQUENCE, [
|
||||
makePrimitive(
|
||||
"universal",
|
||||
UNIVERSAL_TAGS.OBJECT_IDENTIFIER,
|
||||
oidBody
|
||||
),
|
||||
makePrimitive(
|
||||
"universal",
|
||||
UNIVERSAL_TAGS.PRINTABLE_STRING,
|
||||
new Uint8Array([0x43, 0x4e])
|
||||
),
|
||||
]);
|
||||
const rdn = makeConstructed("universal", UNIVERSAL_TAGS.SET, [atv]);
|
||||
const name = makeConstructed("universal", UNIVERSAL_TAGS.SEQUENCE, [
|
||||
rdn,
|
||||
]);
|
||||
const enc = encodeAsn1(name);
|
||||
const dec = decodeAsn1(enc);
|
||||
const reenc = encodeAsn1(dec);
|
||||
expect(Array.from(reenc)).toEqual(Array.from(enc));
|
||||
});
|
||||
|
||||
it("encodes a long-form length envelope for >=128 byte body", {
|
||||
timeout: 5000,
|
||||
}, () => {
|
||||
const content = new Uint8Array(300).fill(0x42);
|
||||
const node = makePrimitive(
|
||||
"universal",
|
||||
UNIVERSAL_TAGS.OCTET_STRING,
|
||||
content
|
||||
);
|
||||
const enc = encodeAsn1(node);
|
||||
// Expect leading 0x04 (OCTET_STRING), then 0x82 (long-form, 2 length bytes), then 0x01, 0x2c (300).
|
||||
expect(enc[0]).toBe(0x04);
|
||||
expect(enc[1]).toBe(0x82);
|
||||
expect(enc[2]).toBe(0x01);
|
||||
expect(enc[3]).toBe(0x2c);
|
||||
});
|
||||
|
||||
it("encodes high tag numbers via long-form tag encoding", {
|
||||
timeout: 5000,
|
||||
}, () => {
|
||||
const node = makePrimitive("context", 31, new Uint8Array());
|
||||
const enc = encodeAsn1(node);
|
||||
expect(enc[0]).toBe(0x9f);
|
||||
expect(enc[1]).toBe(0x1f);
|
||||
});
|
||||
|
||||
it("encodes context-class constructed nodes", { timeout: 5000 }, () => {
|
||||
const inner = makePrimitive(
|
||||
"universal",
|
||||
UNIVERSAL_TAGS.INTEGER,
|
||||
new Uint8Array([0x01])
|
||||
);
|
||||
const node = makeConstructed("context", 0, [inner]);
|
||||
const enc = encodeAsn1(node);
|
||||
expect(enc[0]).toBe(0xa0);
|
||||
});
|
||||
|
||||
it("rejects negative tag numbers", { timeout: 5000 }, () => {
|
||||
const bad = makePrimitive(
|
||||
"universal" as const,
|
||||
-1 as unknown as number,
|
||||
new Uint8Array()
|
||||
);
|
||||
expect(() => encodeAsn1(bad)).toThrow();
|
||||
});
|
||||
|
||||
it("encodes a long-form tag number that requires multiple sub-bytes", {
|
||||
timeout: 5000,
|
||||
}, () => {
|
||||
// Tag number 200 needs two sub-id bytes (200 = 0x01 0x48 in
|
||||
// base-128), exercising the `last ? 0x00 : 0x80` ternary's
|
||||
// false branch.
|
||||
const bytes = encodeAsn1(
|
||||
makePrimitive("context", 200, new Uint8Array([0x05]))
|
||||
);
|
||||
const back = decodeAsn1(bytes);
|
||||
expect(back.tag.tagNumber).toBe(200);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user