summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--packages/server/src/helpers/getCertificateInfo.ts116
1 files changed, 47 insertions, 69 deletions
diff --git a/packages/server/src/helpers/getCertificateInfo.ts b/packages/server/src/helpers/getCertificateInfo.ts
index c70ec6b..021ad77 100644
--- a/packages/server/src/helpers/getCertificateInfo.ts
+++ b/packages/server/src/helpers/getCertificateInfo.ts
@@ -1,102 +1,80 @@
-/* eslint-disable @typescript-eslint/ban-ts-comment */
-// `ASN1HEX` exists in the lib but not in its typings
-// @ts-ignore 2305
-import { X509, zulutodate, ASN1HEX } from 'jsrsasign';
+import { AsnParser } from '@peculiar/asn1-schema';
+import { Certificate, BasicConstraints, id_ce_basicConstraints } from '@peculiar/asn1-x509';
export type CertificateInfo = {
- issuer: { [key: string]: string };
- subject: { [key: string]: string };
+ issuer: Issuer;
+ subject: Subject;
version: number;
basicConstraintsCA: boolean;
notBefore: Date;
notAfter: Date;
};
-type ExtInfo = {
- critical: boolean;
- oid: string;
- vidx: number;
+type Issuer = {
+ C?: string;
+ O?: string;
+ OU?: string;
+ CN?: string;
};
-interface x5cCertificate extends jsrsasign.X509 {
- version: number;
- foffset: number;
- aExtInfo: ExtInfo[];
-}
+type Subject = {
+ C?: string;
+ O?: string;
+ OU?: string;
+ CN?: 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 default function getCertificateInfo(pemCertificate: string): CertificateInfo {
- const subjectCert = new X509();
- subjectCert.readCertPEM(pemCertificate);
-
- // Break apart the Issuer
- const issuerString = subjectCert.getIssuerString();
- const issuerParts = issuerString.slice(1).split('/');
+export default function getCertificateInfo(leafCertBuffer: Buffer): CertificateInfo {
+ const asnx509 = AsnParser.parse(leafCertBuffer, Certificate);
+ const parsedCert = asnx509.tbsCertificate;
- const issuer: { [key: string]: string } = {};
- issuerParts.forEach(field => {
- const [key, val] = field.split('=');
- issuer[key] = val;
- });
-
- // Break apart the Subject
- let subjectRaw = '/';
- try {
- subjectRaw = subjectCert.getSubjectString();
- } catch (err) {
- // Don't throw on an error that indicates an empty subject
- if (err !== 'malformed RDN') {
- throw err;
+ // Issuer
+ const issuer: Issuer = {};
+ parsedCert.issuer.forEach(([iss]) => {
+ const key = issuerSubjectIDKey[iss.type];
+ if (key) {
+ issuer[key] = iss.value.toString();
}
- }
- const subjectParts = subjectRaw.slice(1).split('/');
+ });
- const subject: { [key: string]: string } = {};
- subjectParts.forEach(field => {
- if (field) {
- const [key, val] = field.split('=');
- subject[key] = val;
+ // Subject
+ const subject: Subject = {};
+ parsedCert.subject.forEach(([iss]) => {
+ const key = issuerSubjectIDKey[iss.type];
+ if (key) {
+ subject[key] = iss.value.toString();
}
});
- const { version } = subjectCert as x5cCertificate;
let basicConstraintsCA = false;
- try {
- // TODO: Simplify this when jsrsasign gets updated (see note below). Ideally this is all the
- // logic we need to determine `basicConstraintsCA`
- basicConstraintsCA = !!subjectCert.getExtBasicConstraints()?.cA;
- } catch (err) {
- /**
- * This is a workaround till jsrsasign's X509.getExtBasicConstraints() can recognize this
- * legitimate value. See verifyPacked.test.ts for more context.
- */
- // Example error message: "hExtV parse error: 3003010100"
- if (`${err.message}`.indexOf('3003010100') >= 0) {
- const basicConstraintsInfo = subjectCert.getExtInfo('basicConstraints');
-
- if (typeof basicConstraintsInfo === 'object' && basicConstraintsInfo.vidx) {
- const hExtV = ASN1HEX.getTLV(subjectCert.hex, basicConstraintsInfo.vidx);
- if (hExtV === '3003010100') {
- basicConstraintsCA = false;
- } else {
- throw err;
- }
+ 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;
}
- } else {
- throw err;
}
}
return {
issuer,
subject,
- version,
+ version: parsedCert.version,
basicConstraintsCA,
- notBefore: zulutodate(subjectCert.getNotBefore()),
- notAfter: zulutodate(subjectCert.getNotAfter()),
+ notBefore: parsedCert.validity.notBefore.getTime(),
+ notAfter: parsedCert.validity.notAfter.getTime(),
};
}