summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--packages/server/src/helpers/convertPEMToBytes.test.ts37
-rw-r--r--packages/server/src/helpers/convertPEMToBytes.ts2
-rw-r--r--packages/server/src/metadata/verifyJWT.ts20
-rw-r--r--packages/server/src/services/metadataService.e2e.test.ts19
4 files changed, 71 insertions, 7 deletions
diff --git a/packages/server/src/helpers/convertPEMToBytes.test.ts b/packages/server/src/helpers/convertPEMToBytes.test.ts
new file mode 100644
index 0000000..9a7a517
--- /dev/null
+++ b/packages/server/src/helpers/convertPEMToBytes.test.ts
@@ -0,0 +1,37 @@
+import { isoBase64URL } from './iso';
+
+import { convertPEMToBytes } from './convertPEMToBytes';
+
+test('should handle malformed cert with leading whitespaces', () => {
+ const output = convertPEMToBytes(malformedLeadingWhitespace);
+
+ expect(
+ isoBase64URL.fromBuffer(output)
+ ).toEqual(
+ 'MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4GA1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie_QV2EcWtiHL8RgJDx7KKnQRfJMsuS-FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsTgHeMCOFJ0mpiLx9e-pZo34knlTifBtc-ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmmKPZpO_bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c-9C7v_U9AOEGM-iCK65TpjoWc4zdQQ4gOsC0p6Hpsk-QLjJg6VfLuQSSaGjlOCZgdbKfd_-RFO-uIEn8rUAVSNECMWEZXriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAwDgYDVR0PAQH_BAQDAgEGMA8GA1UdEwEB_wQFMAMBAf8wHQYDVR0OBBYEFI_wS3-oLkUkrk1Q-mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr-yAzv95ZURUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q_c2dKg8dEe3jgr25sbwMpjjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj-9xTaGdWPoO4zzUhw8lo_s7awlOqzJCK6fBdRoyV3XpYKBovHd7NADdBj-1EbddTKJd-82cEHhXXipa0095MJ6RMG3NzdvQXmcIfeg7jLQitChws_zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecsMx86OyXShkDOOyyGeMlhLxS67ttVb9-E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpHWD9f'
+ );
+});
+
+// Each line of this PEM cert should have a space in front of it
+const malformedLeadingWhitespace = `-----BEGIN CERTIFICATE-----
+ MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G
+ A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp
+ Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4
+ MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG
+ A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI
+ hvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8
+ RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT
+ gHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm
+ KPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd
+ QQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ
+ XriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw
+ DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o
+ LkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU
+ RUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp
+ jjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK
+ 6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX
+ mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs
+ Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH
+ WD9f
+ -----END CERTIFICATE-----
+`;
diff --git a/packages/server/src/helpers/convertPEMToBytes.ts b/packages/server/src/helpers/convertPEMToBytes.ts
index 8749d03..7958635 100644
--- a/packages/server/src/helpers/convertPEMToBytes.ts
+++ b/packages/server/src/helpers/convertPEMToBytes.ts
@@ -7,7 +7,7 @@ export function convertPEMToBytes(pem: string): Uint8Array {
const certBase64 = pem
.replace('-----BEGIN CERTIFICATE-----', '')
.replace('-----END CERTIFICATE-----', '')
- .replace(/\n/g, '');
+ .replace(/[\n ]/g, '');
return isoBase64URL.toBuffer(certBase64, 'base64');
}
diff --git a/packages/server/src/metadata/verifyJWT.ts b/packages/server/src/metadata/verifyJWT.ts
index d7e64ec..d9c933a 100644
--- a/packages/server/src/metadata/verifyJWT.ts
+++ b/packages/server/src/metadata/verifyJWT.ts
@@ -1,13 +1,13 @@
import { convertX509PublicKeyToCOSE } from '../helpers/convertX509PublicKeyToCOSE';
import { isoBase64URL, isoUint8Array } from '../helpers/iso';
-import { COSEALG, COSEKEYS, isCOSEPublicKeyEC2 } from '../helpers/cose';
+import { COSEALG, COSEKEYS, isCOSEPublicKeyEC2, isCOSEPublicKeyRSA } from '../helpers/cose';
import { verifyEC2 } from '../helpers/iso/isoCrypto/verifyEC2';
+import { verifyRSA } from '../helpers/iso/isoCrypto/verifyRSA';
/**
- * Lightweight verification for FIDO MDS JWTs.
+ * Lightweight verification for FIDO MDS JWTs. Supports use of EC2 and RSA.
*
- * Currently assumes `"alg": "ES256"` in the JWT header, it's what FIDO MDS uses. If this ever
- * needs to support more JWS algorithms, here's the list of them:
+ * If this ever needs to support more JWS algorithms, here's the list of them:
*
* https://www.rfc-editor.org/rfc/rfc7518.html#section-3.1
*
@@ -17,14 +17,22 @@ export async function verifyJWT(jwt: string, leafCert: Uint8Array): Promise<bool
const [header, payload, signature] = jwt.split('.');
const certCOSE = convertX509PublicKeyToCOSE(leafCert);
+ const data = isoUint8Array.fromUTF8String(`${header}.${payload}`);
+ const signatureBytes = isoBase64URL.toBuffer(signature);
if (isCOSEPublicKeyEC2(certCOSE)) {
return verifyEC2({
- data: isoUint8Array.fromUTF8String(`${header}.${payload}`),
- signature: isoBase64URL.toBuffer(signature),
+ data,
+ signature: signatureBytes,
cosePublicKey: certCOSE,
shaHashOverride: COSEALG.ES256,
});
+ } else if (isCOSEPublicKeyRSA(certCOSE)) {
+ return verifyRSA({
+ data,
+ signature: signatureBytes,
+ cosePublicKey: certCOSE,
+ })
}
const kty = certCOSE.get(COSEKEYS.kty);
diff --git a/packages/server/src/services/metadataService.e2e.test.ts b/packages/server/src/services/metadataService.e2e.test.ts
new file mode 100644
index 0000000..e2d8d5b
--- /dev/null
+++ b/packages/server/src/services/metadataService.e2e.test.ts
@@ -0,0 +1,19 @@
+import { BaseMetadataService } from './metadataService';
+
+describe('end-to-end MetadataService tests', () => {
+ test('should be able to load from FIDO MDS and get statement for YubiKey 5', async () => {
+ const service = new BaseMetadataService();
+
+ await service.initialize();
+
+ /**
+ * From Yubico's list of AAGUIDs
+ *
+ * See https://support.yubico.com/hc/en-us/articles/360016648959-YubiKey-Hardware-FIDO2-AAGUIDs
+ */
+ const aaguidYubiKey5 = 'ee882879-721c-4913-9775-3dfcce97072a';
+ const statement = await service.getStatement(aaguidYubiKey5);
+
+ expect(statement).toBeDefined();
+ });
+});