@simplewebauthn/server 13.3.1 → 13.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,8 @@
1
+ import { COSEALG } from './cose.js';
2
+ /**
3
+ * Map JWS algorithms to COSE algorithm IDs
4
+ *
5
+ * See https://www.rfc-editor.org/rfc/rfc7518.html#section-3.1 for possible values
6
+ */
7
+ export declare function mapJWSAlgToCOSEAlg(alg: string): COSEALG;
8
+ //# sourceMappingURL=mapJWSAlgToCOSEAlg.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mapJWSAlgToCOSEAlg.d.ts","sourceRoot":"","sources":["../../src/helpers/mapJWSAlgToCOSEAlg.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAoBvD"}
@@ -0,0 +1,31 @@
1
+ import { COSEALG } from './cose.js';
2
+ /**
3
+ * Map JWS algorithms to COSE algorithm IDs
4
+ *
5
+ * See https://www.rfc-editor.org/rfc/rfc7518.html#section-3.1 for possible values
6
+ */
7
+ export function mapJWSAlgToCOSEAlg(alg) {
8
+ let algCOSE;
9
+ if (alg === 'ES256') {
10
+ algCOSE = COSEALG.ES256;
11
+ }
12
+ else if (alg === 'ES384') {
13
+ algCOSE = COSEALG.ES384;
14
+ }
15
+ else if (alg === 'ES512') {
16
+ algCOSE = COSEALG.ES512;
17
+ }
18
+ else if (alg === 'RS256') {
19
+ algCOSE = COSEALG.RS256;
20
+ }
21
+ else if (alg === 'RS384') {
22
+ algCOSE = COSEALG.RS384;
23
+ }
24
+ else if (alg === 'RS512') {
25
+ algCOSE = COSEALG.RS512;
26
+ }
27
+ else {
28
+ throw new Error(`Unable to map JWS algorithm "${alg}" to a COSE algorithm`);
29
+ }
30
+ return algCOSE;
31
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"validateCertificatePath.d.ts","sourceRoot":"","sources":["../../src/helpers/validateCertificatePath.ts"],"names":[],"mappings":"AAKA;;;;GAIG;AACH,wBAAsB,uBAAuB,CAC3C,WAAW,EAAE,MAAM,EAAE,EACrB,eAAe,GAAE,MAAM,EAAO,GAC7B,OAAO,CAAC,OAAO,CAAC,CA6HlB"}
1
+ {"version":3,"file":"validateCertificatePath.d.ts","sourceRoot":"","sources":["../../src/helpers/validateCertificatePath.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,wBAAsB,uBAAuB,CAC3C,WAAW,EAAE,MAAM,EAAE,EACrB,eAAe,GAAE,MAAM,EAAO,GAC7B,OAAO,CAAC,OAAO,CAAC,CAiHlB"}
@@ -1,6 +1,5 @@
1
- import { X509Certificate } from '@peculiar/x509';
1
+ import { X509Certificate, X509ChainBuilder } from '@peculiar/x509';
2
2
  import { isCertRevoked } from './isCertRevoked.js';
3
- import { getWebCrypto } from './iso/isoCrypto/getWebCrypto.js';
4
3
  /**
5
4
  * Traverse an array of PEM certificates and ensure they form a proper chain
6
5
  * @param x5cCertsPEM Typically the result of `x5c.map(convertASN1toPEM)`
@@ -11,7 +10,6 @@ export async function validateCertificatePath(x5cCertsPEM, trustAnchorsPEM = [])
11
10
  // We have no trust anchors to chain back to, so skip path validation
12
11
  return true;
13
12
  }
14
- const WebCrypto = await getWebCrypto();
15
13
  // Prepare to work with x5c certs
16
14
  const x5cCertsParsed = x5cCertsPEM.map((certPEM) => new X509Certificate(certPEM));
17
15
  // Check for any expired or temporally invalid certs in x5c
@@ -64,50 +62,47 @@ export async function validateCertificatePath(x5cCertsPEM, trustAnchorsPEM = [])
64
62
  if (validTrustAnchors.length === 0) {
65
63
  throw new Error('No specified trust anchor was valid for verifying x5c');
66
64
  }
67
- // Try to verify x5c with each trust anchor
68
- let invalidSubjectAndIssuerError = false;
69
- for (const anchor of trustAnchorsParsed) {
65
+ // Try to verify x5c with each valid trust anchor
66
+ let invalidCertificateChain = true;
67
+ for (const anchor of validTrustAnchors) {
70
68
  try {
71
69
  const x5cWithTrustAnchor = x5cCertsParsed.concat([anchor]);
72
- if (new Set(x5cWithTrustAnchor).size !== x5cWithTrustAnchor.length) {
70
+ const numUniqueCerts = new Set(x5cWithTrustAnchor.map((cert) => cert.toString('pem'))).size;
71
+ if (numUniqueCerts !== x5cWithTrustAnchor.length) {
73
72
  throw new Error('Invalid certificate path: found duplicate certificates');
74
73
  }
75
- // Check signatures, and notBefore and notAfter
76
- for (let i = 0; i < x5cWithTrustAnchor.length - 1; i++) {
77
- const subject = x5cWithTrustAnchor[i];
78
- const issuer = x5cWithTrustAnchor[i + 1];
79
- // Leaf or intermediate cert, make sure the next cert in the chain signed it
80
- const issuerSignedSubject = await subject.verify({ publicKey: issuer.publicKey, signatureOnly: true }, WebCrypto);
81
- if (!issuerSignedSubject) {
82
- throw new InvalidSubjectAndIssuer();
83
- }
84
- if (issuer.subject === issuer.issuer) {
85
- // Root cert detected, make sure it signed itself
86
- const issuerSignedIssuer = await issuer.verify({ publicKey: issuer.publicKey, signatureOnly: true }, WebCrypto);
87
- if (!issuerSignedIssuer) {
88
- throw new InvalidSubjectAndIssuer();
89
- }
90
- // Don't process anything else after a root cert
91
- break;
92
- }
74
+ // Break apart x5c to try and build a valid cert chain
75
+ const x5cLeafCert = x5cCertsParsed[0];
76
+ let x5cIntermediates = [];
77
+ if (x5cCertsParsed.length > 1) {
78
+ x5cIntermediates = x5cCertsParsed.slice(1);
79
+ }
80
+ // Order of certs doesn't matter here but for readability
81
+ const chainBuilder = new X509ChainBuilder({ certificates: [...x5cIntermediates, anchor] });
82
+ // Cert chain should be, from index 0: leaf cert -> ...intermediates -> trust anchor
83
+ const chain = await chainBuilder.build(x5cLeafCert);
84
+ // Check if the chain contains (all of the certs in x5c) + (the trust anchor)
85
+ if (chain.length < numUniqueCerts) {
86
+ // Invalid cert chain, try the next trust anchor
87
+ continue;
88
+ }
89
+ // Check if the chain is to the trust anchor
90
+ if (chain[chain.length - 1].subject !== anchor.subject) {
91
+ // Invalid cert chain, try the next trust anchor
92
+ continue;
93
93
  }
94
94
  // If we successfully validated a path then there's no need to continue. Reset any existing
95
95
  // errors that were thrown by earlier trust anchors
96
- invalidSubjectAndIssuerError = false;
96
+ invalidCertificateChain = false;
97
97
  break;
98
98
  }
99
99
  catch (err) {
100
- if (err instanceof InvalidSubjectAndIssuer) {
101
- invalidSubjectAndIssuerError = true;
102
- }
103
- else {
104
- throw new Error('Unexpected error while validating certificate path', { cause: err });
105
- }
100
+ throw new Error('Unexpected error while validating certificate path', { cause: err });
106
101
  }
107
102
  }
108
103
  // We tried multiple trust anchors and none of them worked
109
- if (invalidSubjectAndIssuerError) {
110
- throw new InvalidSubjectAndIssuer();
104
+ if (invalidCertificateChain) {
105
+ throw new InvalidCertificatePath();
111
106
  }
112
107
  return true;
113
108
  }
@@ -130,11 +125,10 @@ function assertCertIsWithinValidTimeWindow(certNotBefore, certNotAfter) {
130
125
  throw new Error('Certificate is not yet valid or expired');
131
126
  }
132
127
  }
133
- // Custom errors to help pass on certain errors
134
- class InvalidSubjectAndIssuer extends Error {
128
+ class InvalidCertificatePath extends Error {
135
129
  constructor() {
136
- const message = 'Subject issuer did not match issuer subject';
130
+ const message = 'x5c could not be chained to any specified trust anchor';
137
131
  super(message);
138
- this.name = 'InvalidSubjectAndIssuer';
132
+ this.name = 'InvalidX5CChain';
139
133
  }
140
134
  }
@@ -1 +1 @@
1
- {"version":3,"file":"verifyJWT.d.ts","sourceRoot":"","sources":["../../src/metadata/verifyJWT.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CA0B9E"}
1
+ {"version":3,"file":"verifyJWT.d.ts","sourceRoot":"","sources":["../../src/metadata/verifyJWT.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CAgC9E"}
@@ -1,6 +1,7 @@
1
1
  import { convertX509PublicKeyToCOSE } from '../helpers/convertX509PublicKeyToCOSE.js';
2
2
  import { isoBase64URL, isoUint8Array } from '../helpers/iso/index.js';
3
- import { COSEALG, COSEKEYS, isCOSEPublicKeyEC2, isCOSEPublicKeyRSA } from '../helpers/cose.js';
3
+ import { COSEKEYS, isCOSEPublicKeyEC2, isCOSEPublicKeyRSA } from '../helpers/cose.js';
4
+ import { mapJWSAlgToCOSEAlg } from '../helpers/mapJWSAlgToCOSEAlg.js';
4
5
  import { verifyEC2 } from '../helpers/iso/isoCrypto/verifyEC2.js';
5
6
  import { verifyRSA } from '../helpers/iso/isoCrypto/verifyRSA.js';
6
7
  /**
@@ -17,12 +18,15 @@ export function verifyJWT(jwt, leafCert) {
17
18
  const certCOSE = convertX509PublicKeyToCOSE(leafCert);
18
19
  const data = isoUint8Array.fromUTF8String(`${header}.${payload}`);
19
20
  const signatureBytes = isoBase64URL.toBuffer(signature);
21
+ // We just need the `alg` from the header, so only partially define the shape of it
22
+ const headerJSON = JSON.parse(isoBase64URL.toUTF8String(header));
23
+ const jwtHeaderHashAlgCOSE = mapJWSAlgToCOSEAlg(headerJSON.alg);
20
24
  if (isCOSEPublicKeyEC2(certCOSE)) {
21
25
  return verifyEC2({
22
26
  data,
23
27
  signature: signatureBytes,
24
28
  cosePublicKey: certCOSE,
25
- shaHashOverride: COSEALG.ES256,
29
+ shaHashOverride: jwtHeaderHashAlgCOSE,
26
30
  });
27
31
  }
28
32
  else if (isCOSEPublicKeyRSA(certCOSE)) {
@@ -30,6 +34,7 @@ export function verifyJWT(jwt, leafCert) {
30
34
  data,
31
35
  signature: signatureBytes,
32
36
  cosePublicKey: certCOSE,
37
+ shaHashOverride: jwtHeaderHashAlgCOSE,
33
38
  });
34
39
  }
35
40
  const kty = certCOSE.get(COSEKEYS.kty);
@@ -9,4 +9,15 @@
9
9
  * CB:B5:22:D7:B7:F1:27:AD:6A:01:13:86:5B:DF:1C:D4:10:2E:7D:07:59:AF:63:5A:7C:F4:72:0D:C9:63:C5:3B
10
10
  */
11
11
  export declare const GlobalSign_Root_CA_R3 = "-----BEGIN CERTIFICATE-----\nMIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G\nA1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp\nZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4\nMTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG\nA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI\nhvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8\nRgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT\ngHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm\nKPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd\nQQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ\nXriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw\nDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o\nLkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU\nRUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp\njjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK\n6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX\nmcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs\nMx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH\nWD9f\n-----END CERTIFICATE-----\n ";
12
+ /**
13
+ * GlobalSign Root R46
14
+ *
15
+ * Downloaded from https://valid.r46.roots.globalsign.com/
16
+ *
17
+ * Valid until 2046-03-20 @ 00:00 PST
18
+ *
19
+ * SHA256 Fingerprint
20
+ * 4F:A3:12:6D:8D:3A:11:D1:C4:85:5A:4F:80:7C:BA:D6:CF:91:9D:3A:5A:88:B0:3B:EA:2C:63:72:D9:3C:40:C9
21
+ */
22
+ export declare const GlobalSign_Root_R46 = "-----BEGIN CERTIFICATE-----\nMIIFWjCCA0KgAwIBAgISEdK7udcjGJ5AXwqdLdDfJWfRMA0GCSqGSIb3DQEBDAUA\nMEYxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRwwGgYD\nVQQDExNHbG9iYWxTaWduIFJvb3QgUjQ2MB4XDTE5MDMyMDAwMDAwMFoXDTQ2MDMy\nMDAwMDAwMFowRjELMAkGA1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYt\nc2ExHDAaBgNVBAMTE0dsb2JhbFNpZ24gUm9vdCBSNDYwggIiMA0GCSqGSIb3DQEB\nAQUAA4ICDwAwggIKAoICAQCsrHQy6LNl5brtQyYdpokNRbopiLKkHWPd08EsCVeJ\nOaFV6Wc0dwxu5FUdUiXSE2te4R2pt32JMl8Nnp8semNgQB+msLZ4j5lUlghYruQG\nvGIFAha/r6gjA7aUD7xubMLL1aa7DOn2wQL7Id5m3RerdELv8HQvJfTqa1VbkNud\n316HCkD7rRlr+/fKYIje2sGP1q7Vf9Q8g+7XFkyDRTNrJ9CG0Bwta/OrffGFqfUo\n0q3v84RLHIf8E6M6cqJaESvWJ3En7YEtbWaBkoe0G1h6zD8K+kZPTXhc+CtI4wSE\ny132tGqzZfxCnlEmIyDLPRT5ge1lFgBPGmSXZgjPjHvjK8Cd+RTyG/FWaha/LIWF\nzXg4mutCagI0GIMXTpRW+LaCtfOW3T3zvn8gdz57GSNrLNRyc0NXfeD412lPFzYE\n+cCQYDdF3uYM2HSNrpyibXRdQr4G9dlkbgIQrImwTDsHTUB+JMWKmIJ5jqSngiCN\nI/onccnfxkF0oE32kRbcRoxfKWMxWXEM2G/CtjJ9++ZdU6Z+Ffy7dXxd7Pj2Fxzs\nx2sZy/N78CsHpdlseVR2bJ0cpm4O6XkMqCNqo98bMDGfsVR7/mrLZqrcZdCinkqa\nByFrgY/bxFn63iLABJzjqls2k+g9vXqhnQt2sQvHnf3PmKgGwvgqo6GDoLclcqUC\n4wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV\nHQ4EFgQUA1yrc4GHqMywptWU4jaWSf8FmSwwDQYJKoZIhvcNAQEMBQADggIBAHx4\n7PYCLLtbfpIrXTncvtgdokIzTfnvpCo7RGkerNlFo048p9gkUbJUHJNOxO97k4Vg\nJuoJSOD1u8fpaNK7ajFxzHmuEajwmf3lH7wvqMxX63bEIaZHU1VNaL8FpO7XJqti\n2kM3S+LGteWygxk6x9PbTZ4IevPuzz5i+6zoYMzRx6Fcg0XERczzF2sUyQQCPtIk\npnnpHs6i58FZFZ8d4kuaPp92CC1r2LpXFNqD6v6MVenQTqnMdzGxRBF6XLE+0xRF\nFRhiJBPSy03OXIPBNvIQtQ6IbbjhVp+J3pZmOUdkLG5NrmJ7v2B0GbhWrJKsFjLt\nrWhV/pi60zTe9Mlhww6G9kuEYO4Ne7UyWHmRVSyBQ7N0H3qqJZ4d16GLuc1CLgSk\nZoNNiTW2bKg2SnkheCLQQrzRQDGQob4Ez8pn7fXwgNNgyYMqIgXQBztSvwyeqiv5\nu+YfjyW6hY0XHgL+XVAEV8/+LbzvXMAaq7afJMbfc2hIkCwU9D9SGuTSyxTDYWnP\n4vkYxboznxSjBF25cfe1lNj2M8FawTSLfJvdkzrnE6JwYZ+vj+vYxXX4M2bUdGc6\nN3ec592kD3ZDZopD8p/7DEJ4Y9HiD2971KE9dJeFt0g5QdYg/NA6s/rob8SKunE3\nvouXsXgxT7PntgMTzlSdriVZzH81Xwj3QEUxeCp6\n-----END CERTIFICATE-----\n";
12
23
  //# sourceMappingURL=mds.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"mds.d.ts","sourceRoot":"","sources":["../../../src/services/defaultRootCerts/mds.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,eAAO,MAAM,qBAAqB,wuCAqBhC,CAAC"}
1
+ {"version":3,"file":"mds.d.ts","sourceRoot":"","sources":["../../../src/services/defaultRootCerts/mds.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,eAAO,MAAM,qBAAqB,wuCAqBhC,CAAC;AAEH;;;;;;;;;GASG;AACH,eAAO,MAAM,mBAAmB,+5DA+B/B,CAAC"}
@@ -30,3 +30,45 @@ Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH
30
30
  WD9f
31
31
  -----END CERTIFICATE-----
32
32
  `;
33
+ /**
34
+ * GlobalSign Root R46
35
+ *
36
+ * Downloaded from https://valid.r46.roots.globalsign.com/
37
+ *
38
+ * Valid until 2046-03-20 @ 00:00 PST
39
+ *
40
+ * SHA256 Fingerprint
41
+ * 4F:A3:12:6D:8D:3A:11:D1:C4:85:5A:4F:80:7C:BA:D6:CF:91:9D:3A:5A:88:B0:3B:EA:2C:63:72:D9:3C:40:C9
42
+ */
43
+ export const GlobalSign_Root_R46 = `-----BEGIN CERTIFICATE-----
44
+ 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
73
+ -----END CERTIFICATE-----
74
+ `;
@@ -2,7 +2,7 @@ import { convertCertBufferToPEM } from '../helpers/convertCertBufferToPEM.js';
2
2
  import { GlobalSign_Root_CA } from './defaultRootCerts/android-safetynet.js';
3
3
  import { Google_Hardware_Attestation_Root_1, Google_Hardware_Attestation_Root_2, Google_Hardware_Attestation_Root_3, Google_Hardware_Attestation_Root_4, } from './defaultRootCerts/android-key.js';
4
4
  import { Apple_WebAuthn_Root_CA } from './defaultRootCerts/apple.js';
5
- import { GlobalSign_Root_CA_R3 } from './defaultRootCerts/mds.js';
5
+ import { GlobalSign_Root_CA_R3, GlobalSign_Root_R46 } from './defaultRootCerts/mds.js';
6
6
  class BaseSettingsService {
7
7
  constructor() {
8
8
  // Certificates are stored as PEM-formatted strings
@@ -67,5 +67,8 @@ SettingsService.setRootCertificates({
67
67
  });
68
68
  SettingsService.setRootCertificates({
69
69
  identifier: 'mds',
70
- certificates: [GlobalSign_Root_CA_R3],
70
+ certificates: [
71
+ GlobalSign_Root_CA_R3,
72
+ GlobalSign_Root_R46,
73
+ ],
71
74
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@simplewebauthn/server",
3
- "version": "13.3.1",
3
+ "version": "13.3.3",
4
4
  "description": "SimpleWebAuthn for Servers",
5
5
  "keywords": [
6
6
  "typescript",
@@ -0,0 +1,8 @@
1
+ import { COSEALG } from './cose.js';
2
+ /**
3
+ * Map JWS algorithms to COSE algorithm IDs
4
+ *
5
+ * See https://www.rfc-editor.org/rfc/rfc7518.html#section-3.1 for possible values
6
+ */
7
+ export declare function mapJWSAlgToCOSEAlg(alg: string): COSEALG;
8
+ //# sourceMappingURL=mapJWSAlgToCOSEAlg.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mapJWSAlgToCOSEAlg.d.ts","sourceRoot":"","sources":["../../src/helpers/mapJWSAlgToCOSEAlg.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAoBvD"}
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.mapJWSAlgToCOSEAlg = mapJWSAlgToCOSEAlg;
4
+ const cose_js_1 = require("./cose.js");
5
+ /**
6
+ * Map JWS algorithms to COSE algorithm IDs
7
+ *
8
+ * See https://www.rfc-editor.org/rfc/rfc7518.html#section-3.1 for possible values
9
+ */
10
+ function mapJWSAlgToCOSEAlg(alg) {
11
+ let algCOSE;
12
+ if (alg === 'ES256') {
13
+ algCOSE = cose_js_1.COSEALG.ES256;
14
+ }
15
+ else if (alg === 'ES384') {
16
+ algCOSE = cose_js_1.COSEALG.ES384;
17
+ }
18
+ else if (alg === 'ES512') {
19
+ algCOSE = cose_js_1.COSEALG.ES512;
20
+ }
21
+ else if (alg === 'RS256') {
22
+ algCOSE = cose_js_1.COSEALG.RS256;
23
+ }
24
+ else if (alg === 'RS384') {
25
+ algCOSE = cose_js_1.COSEALG.RS384;
26
+ }
27
+ else if (alg === 'RS512') {
28
+ algCOSE = cose_js_1.COSEALG.RS512;
29
+ }
30
+ else {
31
+ throw new Error(`Unable to map JWS algorithm "${alg}" to a COSE algorithm`);
32
+ }
33
+ return algCOSE;
34
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"validateCertificatePath.d.ts","sourceRoot":"","sources":["../../src/helpers/validateCertificatePath.ts"],"names":[],"mappings":"AAKA;;;;GAIG;AACH,wBAAsB,uBAAuB,CAC3C,WAAW,EAAE,MAAM,EAAE,EACrB,eAAe,GAAE,MAAM,EAAO,GAC7B,OAAO,CAAC,OAAO,CAAC,CA6HlB"}
1
+ {"version":3,"file":"validateCertificatePath.d.ts","sourceRoot":"","sources":["../../src/helpers/validateCertificatePath.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,wBAAsB,uBAAuB,CAC3C,WAAW,EAAE,MAAM,EAAE,EACrB,eAAe,GAAE,MAAM,EAAO,GAC7B,OAAO,CAAC,OAAO,CAAC,CAiHlB"}
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.validateCertificatePath = validateCertificatePath;
4
4
  const x509_1 = require("@peculiar/x509");
5
5
  const isCertRevoked_js_1 = require("./isCertRevoked.js");
6
- const getWebCrypto_js_1 = require("./iso/isoCrypto/getWebCrypto.js");
7
6
  /**
8
7
  * Traverse an array of PEM certificates and ensure they form a proper chain
9
8
  * @param x5cCertsPEM Typically the result of `x5c.map(convertASN1toPEM)`
@@ -14,7 +13,6 @@ async function validateCertificatePath(x5cCertsPEM, trustAnchorsPEM = []) {
14
13
  // We have no trust anchors to chain back to, so skip path validation
15
14
  return true;
16
15
  }
17
- const WebCrypto = await (0, getWebCrypto_js_1.getWebCrypto)();
18
16
  // Prepare to work with x5c certs
19
17
  const x5cCertsParsed = x5cCertsPEM.map((certPEM) => new x509_1.X509Certificate(certPEM));
20
18
  // Check for any expired or temporally invalid certs in x5c
@@ -67,50 +65,47 @@ async function validateCertificatePath(x5cCertsPEM, trustAnchorsPEM = []) {
67
65
  if (validTrustAnchors.length === 0) {
68
66
  throw new Error('No specified trust anchor was valid for verifying x5c');
69
67
  }
70
- // Try to verify x5c with each trust anchor
71
- let invalidSubjectAndIssuerError = false;
72
- for (const anchor of trustAnchorsParsed) {
68
+ // Try to verify x5c with each valid trust anchor
69
+ let invalidCertificateChain = true;
70
+ for (const anchor of validTrustAnchors) {
73
71
  try {
74
72
  const x5cWithTrustAnchor = x5cCertsParsed.concat([anchor]);
75
- if (new Set(x5cWithTrustAnchor).size !== x5cWithTrustAnchor.length) {
73
+ const numUniqueCerts = new Set(x5cWithTrustAnchor.map((cert) => cert.toString('pem'))).size;
74
+ if (numUniqueCerts !== x5cWithTrustAnchor.length) {
76
75
  throw new Error('Invalid certificate path: found duplicate certificates');
77
76
  }
78
- // Check signatures, and notBefore and notAfter
79
- for (let i = 0; i < x5cWithTrustAnchor.length - 1; i++) {
80
- const subject = x5cWithTrustAnchor[i];
81
- const issuer = x5cWithTrustAnchor[i + 1];
82
- // Leaf or intermediate cert, make sure the next cert in the chain signed it
83
- const issuerSignedSubject = await subject.verify({ publicKey: issuer.publicKey, signatureOnly: true }, WebCrypto);
84
- if (!issuerSignedSubject) {
85
- throw new InvalidSubjectAndIssuer();
86
- }
87
- if (issuer.subject === issuer.issuer) {
88
- // Root cert detected, make sure it signed itself
89
- const issuerSignedIssuer = await issuer.verify({ publicKey: issuer.publicKey, signatureOnly: true }, WebCrypto);
90
- if (!issuerSignedIssuer) {
91
- throw new InvalidSubjectAndIssuer();
92
- }
93
- // Don't process anything else after a root cert
94
- break;
95
- }
77
+ // Break apart x5c to try and build a valid cert chain
78
+ const x5cLeafCert = x5cCertsParsed[0];
79
+ let x5cIntermediates = [];
80
+ if (x5cCertsParsed.length > 1) {
81
+ x5cIntermediates = x5cCertsParsed.slice(1);
82
+ }
83
+ // Order of certs doesn't matter here but for readability
84
+ const chainBuilder = new x509_1.X509ChainBuilder({ certificates: [...x5cIntermediates, anchor] });
85
+ // Cert chain should be, from index 0: leaf cert -> ...intermediates -> trust anchor
86
+ const chain = await chainBuilder.build(x5cLeafCert);
87
+ // Check if the chain contains (all of the certs in x5c) + (the trust anchor)
88
+ if (chain.length < numUniqueCerts) {
89
+ // Invalid cert chain, try the next trust anchor
90
+ continue;
91
+ }
92
+ // Check if the chain is to the trust anchor
93
+ if (chain[chain.length - 1].subject !== anchor.subject) {
94
+ // Invalid cert chain, try the next trust anchor
95
+ continue;
96
96
  }
97
97
  // If we successfully validated a path then there's no need to continue. Reset any existing
98
98
  // errors that were thrown by earlier trust anchors
99
- invalidSubjectAndIssuerError = false;
99
+ invalidCertificateChain = false;
100
100
  break;
101
101
  }
102
102
  catch (err) {
103
- if (err instanceof InvalidSubjectAndIssuer) {
104
- invalidSubjectAndIssuerError = true;
105
- }
106
- else {
107
- throw new Error('Unexpected error while validating certificate path', { cause: err });
108
- }
103
+ throw new Error('Unexpected error while validating certificate path', { cause: err });
109
104
  }
110
105
  }
111
106
  // We tried multiple trust anchors and none of them worked
112
- if (invalidSubjectAndIssuerError) {
113
- throw new InvalidSubjectAndIssuer();
107
+ if (invalidCertificateChain) {
108
+ throw new InvalidCertificatePath();
114
109
  }
115
110
  return true;
116
111
  }
@@ -133,11 +128,10 @@ function assertCertIsWithinValidTimeWindow(certNotBefore, certNotAfter) {
133
128
  throw new Error('Certificate is not yet valid or expired');
134
129
  }
135
130
  }
136
- // Custom errors to help pass on certain errors
137
- class InvalidSubjectAndIssuer extends Error {
131
+ class InvalidCertificatePath extends Error {
138
132
  constructor() {
139
- const message = 'Subject issuer did not match issuer subject';
133
+ const message = 'x5c could not be chained to any specified trust anchor';
140
134
  super(message);
141
- this.name = 'InvalidSubjectAndIssuer';
135
+ this.name = 'InvalidX5CChain';
142
136
  }
143
137
  }
@@ -1 +1 @@
1
- {"version":3,"file":"verifyJWT.d.ts","sourceRoot":"","sources":["../../src/metadata/verifyJWT.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CA0B9E"}
1
+ {"version":3,"file":"verifyJWT.d.ts","sourceRoot":"","sources":["../../src/metadata/verifyJWT.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CAgC9E"}
@@ -4,6 +4,7 @@ exports.verifyJWT = verifyJWT;
4
4
  const convertX509PublicKeyToCOSE_js_1 = require("../helpers/convertX509PublicKeyToCOSE.js");
5
5
  const index_js_1 = require("../helpers/iso/index.js");
6
6
  const cose_js_1 = require("../helpers/cose.js");
7
+ const mapJWSAlgToCOSEAlg_js_1 = require("../helpers/mapJWSAlgToCOSEAlg.js");
7
8
  const verifyEC2_js_1 = require("../helpers/iso/isoCrypto/verifyEC2.js");
8
9
  const verifyRSA_js_1 = require("../helpers/iso/isoCrypto/verifyRSA.js");
9
10
  /**
@@ -20,12 +21,15 @@ function verifyJWT(jwt, leafCert) {
20
21
  const certCOSE = (0, convertX509PublicKeyToCOSE_js_1.convertX509PublicKeyToCOSE)(leafCert);
21
22
  const data = index_js_1.isoUint8Array.fromUTF8String(`${header}.${payload}`);
22
23
  const signatureBytes = index_js_1.isoBase64URL.toBuffer(signature);
24
+ // We just need the `alg` from the header, so only partially define the shape of it
25
+ const headerJSON = JSON.parse(index_js_1.isoBase64URL.toUTF8String(header));
26
+ const jwtHeaderHashAlgCOSE = (0, mapJWSAlgToCOSEAlg_js_1.mapJWSAlgToCOSEAlg)(headerJSON.alg);
23
27
  if ((0, cose_js_1.isCOSEPublicKeyEC2)(certCOSE)) {
24
28
  return (0, verifyEC2_js_1.verifyEC2)({
25
29
  data,
26
30
  signature: signatureBytes,
27
31
  cosePublicKey: certCOSE,
28
- shaHashOverride: cose_js_1.COSEALG.ES256,
32
+ shaHashOverride: jwtHeaderHashAlgCOSE,
29
33
  });
30
34
  }
31
35
  else if ((0, cose_js_1.isCOSEPublicKeyRSA)(certCOSE)) {
@@ -33,6 +37,7 @@ function verifyJWT(jwt, leafCert) {
33
37
  data,
34
38
  signature: signatureBytes,
35
39
  cosePublicKey: certCOSE,
40
+ shaHashOverride: jwtHeaderHashAlgCOSE,
36
41
  });
37
42
  }
38
43
  const kty = certCOSE.get(cose_js_1.COSEKEYS.kty);
@@ -9,4 +9,15 @@
9
9
  * CB:B5:22:D7:B7:F1:27:AD:6A:01:13:86:5B:DF:1C:D4:10:2E:7D:07:59:AF:63:5A:7C:F4:72:0D:C9:63:C5:3B
10
10
  */
11
11
  export declare const GlobalSign_Root_CA_R3 = "-----BEGIN CERTIFICATE-----\nMIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G\nA1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp\nZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4\nMTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG\nA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI\nhvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8\nRgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT\ngHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm\nKPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd\nQQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ\nXriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw\nDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o\nLkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU\nRUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp\njjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK\n6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX\nmcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs\nMx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH\nWD9f\n-----END CERTIFICATE-----\n ";
12
+ /**
13
+ * GlobalSign Root R46
14
+ *
15
+ * Downloaded from https://valid.r46.roots.globalsign.com/
16
+ *
17
+ * Valid until 2046-03-20 @ 00:00 PST
18
+ *
19
+ * SHA256 Fingerprint
20
+ * 4F:A3:12:6D:8D:3A:11:D1:C4:85:5A:4F:80:7C:BA:D6:CF:91:9D:3A:5A:88:B0:3B:EA:2C:63:72:D9:3C:40:C9
21
+ */
22
+ export declare const GlobalSign_Root_R46 = "-----BEGIN CERTIFICATE-----\nMIIFWjCCA0KgAwIBAgISEdK7udcjGJ5AXwqdLdDfJWfRMA0GCSqGSIb3DQEBDAUA\nMEYxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRwwGgYD\nVQQDExNHbG9iYWxTaWduIFJvb3QgUjQ2MB4XDTE5MDMyMDAwMDAwMFoXDTQ2MDMy\nMDAwMDAwMFowRjELMAkGA1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYt\nc2ExHDAaBgNVBAMTE0dsb2JhbFNpZ24gUm9vdCBSNDYwggIiMA0GCSqGSIb3DQEB\nAQUAA4ICDwAwggIKAoICAQCsrHQy6LNl5brtQyYdpokNRbopiLKkHWPd08EsCVeJ\nOaFV6Wc0dwxu5FUdUiXSE2te4R2pt32JMl8Nnp8semNgQB+msLZ4j5lUlghYruQG\nvGIFAha/r6gjA7aUD7xubMLL1aa7DOn2wQL7Id5m3RerdELv8HQvJfTqa1VbkNud\n316HCkD7rRlr+/fKYIje2sGP1q7Vf9Q8g+7XFkyDRTNrJ9CG0Bwta/OrffGFqfUo\n0q3v84RLHIf8E6M6cqJaESvWJ3En7YEtbWaBkoe0G1h6zD8K+kZPTXhc+CtI4wSE\ny132tGqzZfxCnlEmIyDLPRT5ge1lFgBPGmSXZgjPjHvjK8Cd+RTyG/FWaha/LIWF\nzXg4mutCagI0GIMXTpRW+LaCtfOW3T3zvn8gdz57GSNrLNRyc0NXfeD412lPFzYE\n+cCQYDdF3uYM2HSNrpyibXRdQr4G9dlkbgIQrImwTDsHTUB+JMWKmIJ5jqSngiCN\nI/onccnfxkF0oE32kRbcRoxfKWMxWXEM2G/CtjJ9++ZdU6Z+Ffy7dXxd7Pj2Fxzs\nx2sZy/N78CsHpdlseVR2bJ0cpm4O6XkMqCNqo98bMDGfsVR7/mrLZqrcZdCinkqa\nByFrgY/bxFn63iLABJzjqls2k+g9vXqhnQt2sQvHnf3PmKgGwvgqo6GDoLclcqUC\n4wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV\nHQ4EFgQUA1yrc4GHqMywptWU4jaWSf8FmSwwDQYJKoZIhvcNAQEMBQADggIBAHx4\n7PYCLLtbfpIrXTncvtgdokIzTfnvpCo7RGkerNlFo048p9gkUbJUHJNOxO97k4Vg\nJuoJSOD1u8fpaNK7ajFxzHmuEajwmf3lH7wvqMxX63bEIaZHU1VNaL8FpO7XJqti\n2kM3S+LGteWygxk6x9PbTZ4IevPuzz5i+6zoYMzRx6Fcg0XERczzF2sUyQQCPtIk\npnnpHs6i58FZFZ8d4kuaPp92CC1r2LpXFNqD6v6MVenQTqnMdzGxRBF6XLE+0xRF\nFRhiJBPSy03OXIPBNvIQtQ6IbbjhVp+J3pZmOUdkLG5NrmJ7v2B0GbhWrJKsFjLt\nrWhV/pi60zTe9Mlhww6G9kuEYO4Ne7UyWHmRVSyBQ7N0H3qqJZ4d16GLuc1CLgSk\nZoNNiTW2bKg2SnkheCLQQrzRQDGQob4Ez8pn7fXwgNNgyYMqIgXQBztSvwyeqiv5\nu+YfjyW6hY0XHgL+XVAEV8/+LbzvXMAaq7afJMbfc2hIkCwU9D9SGuTSyxTDYWnP\n4vkYxboznxSjBF25cfe1lNj2M8FawTSLfJvdkzrnE6JwYZ+vj+vYxXX4M2bUdGc6\nN3ec592kD3ZDZopD8p/7DEJ4Y9HiD2971KE9dJeFt0g5QdYg/NA6s/rob8SKunE3\nvouXsXgxT7PntgMTzlSdriVZzH81Xwj3QEUxeCp6\n-----END CERTIFICATE-----\n";
12
23
  //# sourceMappingURL=mds.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"mds.d.ts","sourceRoot":"","sources":["../../../src/services/defaultRootCerts/mds.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,eAAO,MAAM,qBAAqB,wuCAqBhC,CAAC"}
1
+ {"version":3,"file":"mds.d.ts","sourceRoot":"","sources":["../../../src/services/defaultRootCerts/mds.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,eAAO,MAAM,qBAAqB,wuCAqBhC,CAAC;AAEH;;;;;;;;;GASG;AACH,eAAO,MAAM,mBAAmB,+5DA+B/B,CAAC"}
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.GlobalSign_Root_CA_R3 = void 0;
3
+ exports.GlobalSign_Root_R46 = exports.GlobalSign_Root_CA_R3 = void 0;
4
4
  /**
5
5
  * GlobalSign Root CA - R3
6
6
  *
@@ -33,3 +33,45 @@ Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH
33
33
  WD9f
34
34
  -----END CERTIFICATE-----
35
35
  `;
36
+ /**
37
+ * GlobalSign Root R46
38
+ *
39
+ * Downloaded from https://valid.r46.roots.globalsign.com/
40
+ *
41
+ * Valid until 2046-03-20 @ 00:00 PST
42
+ *
43
+ * SHA256 Fingerprint
44
+ * 4F:A3:12:6D:8D:3A:11:D1:C4:85:5A:4F:80:7C:BA:D6:CF:91:9D:3A:5A:88:B0:3B:EA:2C:63:72:D9:3C:40:C9
45
+ */
46
+ exports.GlobalSign_Root_R46 = `-----BEGIN CERTIFICATE-----
47
+ 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
76
+ -----END CERTIFICATE-----
77
+ `;
@@ -70,5 +70,8 @@ exports.SettingsService.setRootCertificates({
70
70
  });
71
71
  exports.SettingsService.setRootCertificates({
72
72
  identifier: 'mds',
73
- certificates: [mds_js_1.GlobalSign_Root_CA_R3],
73
+ certificates: [
74
+ mds_js_1.GlobalSign_Root_CA_R3,
75
+ mds_js_1.GlobalSign_Root_R46,
76
+ ],
74
77
  });