1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
import { AsnParser, BasicConstraints, Certificate, id_ce_basicConstraints } from '../deps.ts';
export type CertificateInfo = {
issuer: Issuer;
subject: Subject;
version: number;
basicConstraintsCA: boolean;
notBefore: Date;
notAfter: Date;
parsedCertificate: Certificate;
};
type Issuer = {
C?: string;
O?: string;
OU?: string;
CN?: string;
combined: string;
};
type Subject = {
C?: string;
O?: string;
OU?: string;
CN?: string;
combined: string;
};
const issuerSubjectIDKey: { [key: string]: 'C' | 'O' | 'OU' | 'CN' } = {
'2.5.4.6': 'C',
'2.5.4.10': 'O',
'2.5.4.11': 'OU',
'2.5.4.3': 'CN',
};
/**
* Extract PEM certificate info
*
* @param pemCertificate Result from call to `convertASN1toPEM(x5c[0])`
*/
export function getCertificateInfo(
leafCertBuffer: Uint8Array,
): CertificateInfo {
const x509 = AsnParser.parse(leafCertBuffer, Certificate);
const parsedCert = x509.tbsCertificate;
// Issuer
const issuer: Issuer = { combined: '' };
parsedCert.issuer.forEach(([iss]) => {
const key = issuerSubjectIDKey[iss.type];
if (key) {
issuer[key] = iss.value.toString();
}
});
issuer.combined = issuerSubjectToString(issuer);
// Subject
const subject: Subject = { combined: '' };
parsedCert.subject.forEach(([iss]) => {
const key = issuerSubjectIDKey[iss.type];
if (key) {
subject[key] = iss.value.toString();
}
});
subject.combined = issuerSubjectToString(subject);
let basicConstraintsCA = false;
if (parsedCert.extensions) {
// console.log(parsedCert.extensions);
for (const ext of parsedCert.extensions) {
if (ext.extnID === id_ce_basicConstraints) {
const basicConstraints = AsnParser.parse(
ext.extnValue,
BasicConstraints,
);
basicConstraintsCA = basicConstraints.cA;
}
}
}
return {
issuer,
subject,
version: parsedCert.version,
basicConstraintsCA,
notBefore: parsedCert.validity.notBefore.getTime(),
notAfter: parsedCert.validity.notAfter.getTime(),
parsedCertificate: x509,
};
}
/**
* Stringify the parts of Issuer or Subject info for easier comparison of subject issuers with
* issuer subjects.
*
* The order might seem arbitrary, because it is. It should be enough that the two are stringified
* in the same order.
*/
function issuerSubjectToString(input: Issuer | Subject): string {
const parts: string[] = [];
if (input.C) {
parts.push(input.C);
}
if (input.O) {
parts.push(input.O);
}
if (input.OU) {
parts.push(input.OU);
}
if (input.CN) {
parts.push(input.CN);
}
return parts.join(' : ');
}
|