Skip to content

Commit 4b3afda

Browse files
tests: migrate tests for x590 (#62)
Signed-off-by: Carlos Feria <[email protected]>
1 parent 474d962 commit 4b3afda

File tree

2 files changed

+201
-0
lines changed

2 files changed

+201
-0
lines changed
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import { vi, type Mock } from "vitest";
2+
3+
import { decodex509 } from "./decode";
4+
import { X509Certificate } from "@peculiar/x509";
5+
import { toRelativeDateString } from "../../utils/date";
6+
import { EXTENSIONS_CONFIG } from "./extensions";
7+
8+
vi.mock("@peculiar/x509", () => ({
9+
X509Certificate: vi.fn(),
10+
}));
11+
12+
vi.mock("../../utils/date", () => ({
13+
toRelativeDateString: vi.fn(),
14+
}));
15+
16+
vi.mock("./extensions", () => ({
17+
EXTENSIONS_CONFIG: {
18+
"1.2.3.4.5": {
19+
name: "Mock Extension",
20+
toJSON: vi.fn().mockReturnValue({ mockKey: "mockValue" }),
21+
},
22+
},
23+
}));
24+
25+
describe("decodex509", () => {
26+
beforeEach(() => {
27+
vi.clearAllMocks();
28+
29+
(toRelativeDateString as Mock).mockImplementation((date) => `Relative date for ${date}`);
30+
(X509Certificate as unknown as Mock).mockImplementation(() => ({
31+
serialNumber: "123456",
32+
issuer: "Issuer Name",
33+
notBefore: new Date("2020-01-01"),
34+
notAfter: new Date("2022-01-01"),
35+
publicKey: {
36+
algorithm: "rsaEncryption",
37+
},
38+
subjectName: "Subject Name",
39+
extensions: [
40+
{
41+
type: "1.2.3.4.5",
42+
critical: false,
43+
value: new ArrayBuffer(8),
44+
},
45+
],
46+
}));
47+
});
48+
49+
it("should decode a raw X.509 certificate", () => {
50+
const rawCertificate = "rawCertificateString";
51+
const decoded = decodex509(rawCertificate);
52+
expect(decoded).toBeDefined();
53+
expect(decoded.Signature.Issuer).toBe("Issuer Name");
54+
});
55+
56+
// simulate an extension not found
57+
// @ts-expect-error allowed
58+
EXTENSIONS_CONFIG.unknownExtensionType = undefined;
59+
60+
it("converts ArrayBuffer to hex string for unknown extension types", () => {
61+
(X509Certificate as unknown as Mock).mockImplementation(() => ({
62+
// mock certificate fields as above, adjusting for this specific test
63+
serialNumber: "654321",
64+
issuer: "New Issuer",
65+
notBefore: new Date("2021-01-01"),
66+
notAfter: new Date("2023-01-01"),
67+
publicKey: {
68+
algorithm: "ecdsa",
69+
},
70+
subjectName: "New Subject",
71+
extensions: [
72+
{
73+
type: "unknownExtensionType",
74+
critical: true,
75+
value: new Uint8Array([1, 2, 3, 4]).buffer, // tests bufferToHex
76+
},
77+
],
78+
}));
79+
80+
const rawCertificate = "anotherRawCertificateString";
81+
const decoded = decodex509(rawCertificate);
82+
83+
// asserts the hex string format of the ArrayBuffer
84+
expect(decoded["X509v3 extensions"]["unknownExtensionType (critical)"]).toBe("01:02:03:04");
85+
});
86+
});
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-argument */
2+
3+
import { EXTENSIONS_CONFIG } from "./extensions";
4+
5+
vi.mock("@peculiar/asn1-schema", () => ({
6+
AsnUtf8StringConverter: {
7+
fromASN: vi.fn().mockReturnValue("mockedString"),
8+
},
9+
AsnAnyConverter: {
10+
toASN: vi.fn().mockReturnValue(new ArrayBuffer(0)),
11+
},
12+
}));
13+
14+
vi.mock("@peculiar/x509", () => ({
15+
AuthorityKeyIdentifierExtension: vi.fn().mockImplementation(() => ({
16+
keyId: "01020304",
17+
certId: undefined,
18+
})),
19+
BasicConstraintsExtension: vi.fn().mockImplementation(() => ({
20+
ca: false,
21+
})),
22+
ExtendedKeyUsageExtension: vi.fn().mockImplementation(() => ({
23+
usages: ["1.3.6.1.5.5.7.3.3"],
24+
})),
25+
KeyUsagesExtension: vi.fn().mockImplementation(() => ({
26+
usages: 3,
27+
})),
28+
SubjectAlternativeNameExtension: vi.fn().mockImplementation(() => ({
29+
names: [],
30+
})),
31+
SubjectKeyIdentifierExtension: vi.fn().mockImplementation(() => ({
32+
keyId: "01020304",
33+
})),
34+
}));
35+
36+
vi.mock("./constants", () => ({
37+
KEY_USAGE_NAMES: {
38+
1: "Digital Signature",
39+
2: "Non Repudiation",
40+
4: "Key Encipherment",
41+
8: "Data Encipherment",
42+
},
43+
}));
44+
45+
describe("EXTENSIONS_CONFIG", () => {
46+
beforeEach(() => {
47+
vi.clearAllMocks();
48+
});
49+
50+
it("should map '2.5.29.14' to Subject Key Identifier", () => {
51+
const rawExtension = {
52+
rawData: new Uint8Array([1, 2, 3, 4]),
53+
value: new Uint8Array([5, 6, 7, 8]),
54+
};
55+
const result = EXTENSIONS_CONFIG["2.5.29.14"].toJSON(rawExtension as any);
56+
expect(result).toEqual(["01:02:03:04"]);
57+
});
58+
59+
it("should map '2.5.29.15' to Key Usage", () => {
60+
const rawExtension = {
61+
rawData: new Uint8Array([1, 2, 3, 4]),
62+
value: new Uint8Array([5, 6, 7, 8]),
63+
};
64+
const result = EXTENSIONS_CONFIG["2.5.29.15"].toJSON(rawExtension as any);
65+
expect(result).toEqual(["Digital Signature", "Non Repudiation"]);
66+
});
67+
68+
it.skip("should map '2.5.29.17' to Subject Alternative Name", () => {
69+
const rawExtension = {
70+
rawData: new Uint8Array([1, 2, 3, 4]),
71+
value: new Uint8Array([5, 6, 7, 8]),
72+
};
73+
const result = EXTENSIONS_CONFIG["2.5.29.17"].toJSON(rawExtension as any);
74+
expect(result).toEqual({ names: [] });
75+
});
76+
77+
it("should map '2.5.29.19' to Basic Constraints", () => {
78+
const rawExtension = {
79+
rawData: new Uint8Array([1, 2, 3, 4]),
80+
value: new Uint8Array([5, 6, 7, 8]),
81+
};
82+
const result = EXTENSIONS_CONFIG["2.5.29.19"].toJSON(rawExtension as any);
83+
expect(result).toEqual({ CA: false });
84+
});
85+
86+
it("should map '2.5.29.35' to Authority Key Identifier", () => {
87+
const rawExtension = {
88+
rawData: new Uint8Array([1, 2, 3, 4]),
89+
value: new Uint8Array([5, 6, 7, 8]),
90+
};
91+
const result = EXTENSIONS_CONFIG["2.5.29.35"].toJSON(rawExtension as any);
92+
expect(result).toEqual({ keyid: "01:02:03:04", certid: undefined });
93+
});
94+
95+
it("should map '2.5.29.37' to Extended Key Usage", () => {
96+
const rawExtension = {
97+
rawData: new Uint8Array([1, 2, 3, 4]),
98+
value: new Uint8Array([5, 6, 7, 8]),
99+
};
100+
const result = EXTENSIONS_CONFIG["2.5.29.37"].toJSON(rawExtension as any);
101+
expect(result).toEqual(["Code Signing"]);
102+
});
103+
104+
it("should decode text using textDecoder", () => {
105+
const rawExtension = { value: new TextEncoder().encode("test") };
106+
const result = EXTENSIONS_CONFIG["1.3.6.1.4.1.57264.1.1"].toJSON(rawExtension as any);
107+
expect(result).toBe("test");
108+
});
109+
110+
it("should decode UTF-8 string using utf8StringDecoder", () => {
111+
const rawExtension = { value: new TextEncoder().encode("test") };
112+
const result = EXTENSIONS_CONFIG["1.3.6.1.4.1.57264.1.8"].toJSON(rawExtension as any);
113+
expect(result).toBe("mockedString");
114+
});
115+
});

0 commit comments

Comments
 (0)