summaryrefslogtreecommitdiffhomepage
path: root/packages/server/src
diff options
context:
space:
mode:
authorMatthew Miller <matthew@millerti.me>2022-12-15 23:29:31 -0800
committerMatthew Miller <matthew@millerti.me>2022-12-15 23:29:31 -0800
commitd9c4b65d785ceb5358e3a145b0ff860b19ab3937 (patch)
treef582cc2d945fe91c7ba3a6cdc230d39b80758a7d /packages/server/src
parent6f3cb6e6aae30b65c4d4e789b3b8aeae9c2b3173 (diff)
Reduce use of jsrsasign in isCertRevoked()
Diffstat (limited to 'packages/server/src')
-rw-r--r--packages/server/src/helpers/isCertRevoked.ts86
1 files changed, 51 insertions, 35 deletions
diff --git a/packages/server/src/helpers/isCertRevoked.ts b/packages/server/src/helpers/isCertRevoked.ts
index 2d7f5d6..bac8356 100644
--- a/packages/server/src/helpers/isCertRevoked.ts
+++ b/packages/server/src/helpers/isCertRevoked.ts
@@ -1,9 +1,16 @@
-import { X509 } from 'jsrsasign';
import fetch from 'cross-fetch';
import { AsnParser } from '@peculiar/asn1-schema';
-import { CertificateList } from '@peculiar/asn1-x509';
+import {
+ CertificateList,
+ Certificate,
+ AuthorityKeyIdentifier,
+ id_ce_authorityKeyIdentifier,
+ SubjectKeyIdentifier,
+ id_ce_subjectKeyIdentifier,
+ id_ce_cRLDistributionPoints,
+ CRLDistributionPoints,
+} from '@peculiar/asn1-x509';
-import { convertCertBufferToPEM } from './convertCertBufferToPEM';
import { isoUint8Array } from './iso';
/**
@@ -23,31 +30,48 @@ const cacheRevokedCerts: { [certAuthorityKeyID: string]: CAAuthorityInfo } = {};
*
* CRL certificate structure referenced from https://tools.ietf.org/html/rfc5280#page-117
*/
-export async function isCertRevoked(cert: X509): Promise<boolean> {
- const certSerialHex = cert.getSerialNumberHex();
+export async function isCertRevoked(cert: Certificate): Promise<boolean> {
+ const { extensions } = cert.tbsCertificate;
- // Check to see if we've got cached info for the cert's CA
- let keyIdentifier: jsrsasign.AuthorityKeyIdentifierResult | jsrsasign.ExtSubjectKeyIdentifier | undefined = undefined;
- try {
- keyIdentifier = cert.getExtAuthorityKeyIdentifier();
- } catch (err) {
- // pass
+ if (!extensions) {
+ throw new Error('Certificate had no extensions needed to check for revocation');
}
- /**
- * We might be dealing with a self-signed root certificate. Check the
- * Subject key Identifier extension next.
- */
- if (!keyIdentifier) {
- try {
- keyIdentifier = cert.getExtSubjectKeyIdentifier();
- } catch (err) {
- // pass
+ let extAuthorityKeyID: AuthorityKeyIdentifier | undefined;
+ let extSubjectKeyID: SubjectKeyIdentifier | undefined;
+ let extCRLDistributionPoints: CRLDistributionPoints | undefined;
+
+ extensions.forEach((ext) => {
+ if (ext.extnID === id_ce_authorityKeyIdentifier) {
+ extAuthorityKeyID = AsnParser.parse(ext.extnValue, AuthorityKeyIdentifier);
+ } else if (ext.extnID === id_ce_subjectKeyIdentifier) {
+ extSubjectKeyID = AsnParser.parse(ext.extnValue, SubjectKeyIdentifier);
+ } else if (ext.extnID === id_ce_cRLDistributionPoints) {
+ extCRLDistributionPoints = AsnParser.parse(ext.extnValue, CRLDistributionPoints);
}
+ });
+
+ // Check to see if we've got cached info for the cert's CA
+ let keyIdentifier: string | undefined = undefined;
+
+ if (extAuthorityKeyID && extAuthorityKeyID.keyIdentifier) {
+ keyIdentifier = isoUint8Array.toHex(
+ new Uint8Array(extAuthorityKeyID.keyIdentifier.buffer),
+ );
+ } else if (extSubjectKeyID) {
+ /**
+ * We might be dealing with a self-signed root certificate. Check the
+ * Subject key Identifier extension next.
+ */
+ keyIdentifier = isoUint8Array.toHex(
+ new Uint8Array(extSubjectKeyID.buffer),
+ );
}
+ const certSerialHex = isoUint8Array.toHex(new Uint8Array(cert.tbsCertificate.serialNumber));
+
if (keyIdentifier) {
- const cached = cacheRevokedCerts[keyIdentifier.kid.hex];
+ const cached = cacheRevokedCerts[keyIdentifier];
if (cached) {
const now = new Date();
// If there's a nextUpdate then make sure we're before it
@@ -57,13 +81,7 @@ export async function isCertRevoked(cert: X509): Promise<boolean> {
}
}
- let crlURL = undefined;
- try {
- crlURL = cert.getExtCRLDistributionPointsURI();
- } catch (err) {
- // Cert probably didn't include any CDP URIs
- return false;
- }
+ const crlURL = extCRLDistributionPoints?.[0].distributionPoint?.fullName?.[0].uniformResourceIdentifier;
// If no URL is provided then we have nothing to check
if (!crlURL) {
@@ -71,17 +89,15 @@ export async function isCertRevoked(cert: X509): Promise<boolean> {
}
// Download and read the CRL
- const crlCert = new X509();
+ let certListBytes: ArrayBuffer;
try {
- const respCRL = await fetch(crlURL[0]);
- const dataCRL = await respCRL.arrayBuffer();
- const dataPEM = convertCertBufferToPEM(new Uint8Array(dataCRL));
- crlCert.readCertPEM(dataPEM);
+ const respCRL = await fetch(crlURL);
+ certListBytes = await respCRL.arrayBuffer();
} catch (err) {
return false;
}
- const data = AsnParser.parse(isoUint8Array.fromHex(crlCert.hex), CertificateList);
+ const data = AsnParser.parse(certListBytes, CertificateList);
const newCached: CAAuthorityInfo = {
revokedCerts: [],
@@ -104,7 +120,7 @@ export async function isCertRevoked(cert: X509): Promise<boolean> {
// Cache the results
if (keyIdentifier) {
- cacheRevokedCerts[keyIdentifier.kid.hex] = newCached;
+ cacheRevokedCerts[keyIdentifier] = newCached;
}
return newCached.revokedCerts.indexOf(certSerialHex) >= 0;