diff --git a/.gitignore b/.gitignore index e1cfb91..e0b3772 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ /node_modules /.idea /lib +/tmp /coverage .DS_Store diff --git a/package-lock.json b/package-lock.json index c70affb..e771a42 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3199,10 +3199,11 @@ ] }, "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -10545,9 +10546,9 @@ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" }, "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "requires": { "balanced-match": "^1.0.0", diff --git a/src/mdoc/model/Document.ts b/src/mdoc/model/Document.ts index 27f9647..4ad7d3d 100644 --- a/src/mdoc/model/Document.ts +++ b/src/mdoc/model/Document.ts @@ -163,14 +163,14 @@ export class Document { * * @param {Object} params - The parameters object * @param {jose.JWK | Uint8Array} params.issuerPrivateKey - The issuer's private key either in JWK format or COSE_KEY format as buffer. - * @param {string | Uint8Array} params.issuerCertificate - The issuer's certificate in pem format or as a buffer. + * @param {string | Uint8Array | Array} params.issuerCertificate - The issuer's certificate in pem format, as a buffer, or an array. * @param {SupportedAlgs} params.alg - The algorhitm used for the MSO signature. * @param {string | Uint8Array} [params.kid] - The key id of the issuer's private key. default: issuerPrivateKey.kid * @returns {Promise} - The signed document */ async sign(params: { issuerPrivateKey: jose.JWK | Uint8Array, - issuerCertificate: string | Uint8Array, + issuerCertificate: string | Uint8Array | Array, alg: SupportedAlgs, kid?: string | Uint8Array, }): Promise { @@ -178,9 +178,15 @@ export class Document { throw new Error('No namespaces added'); } - const issuerPublicKeyBuffer = typeof params.issuerCertificate === 'string' ? - fromPEM(params.issuerCertificate) : - params.issuerCertificate; + let issuerCertificateChain: Uint8Array[]; + + if (Array.isArray(params.issuerCertificate)) { + issuerCertificateChain = params.issuerCertificate.flatMap((cert) => (typeof cert === 'string' ? fromPEM(cert) : [cert])); + } else if (typeof params.issuerCertificate === 'string') { + issuerCertificateChain = fromPEM(params.issuerCertificate); + } else { + issuerCertificateChain = [params.issuerCertificate]; + } const issuerPrivateKeyJWK = params.issuerPrivateKey instanceof Uint8Array ? COSEKeyToJWK(params.issuerPrivateKey) : @@ -210,7 +216,7 @@ export class Document { const protectedHeader: ProtectedHeaders = { alg: params.alg }; const unprotectedHeader: UnprotectedHeaders = { kid: params.kid ?? issuerPrivateKeyJWK.kid, - x5chain: [issuerPublicKeyBuffer], + x5chain: issuerCertificateChain.length === 1 ? issuerCertificateChain[0] : issuerCertificateChain, }; const issuerAuth = await IssuerAuth.sign( diff --git a/src/mdoc/utils.ts b/src/mdoc/utils.ts index cf395f0..440043c 100644 --- a/src/mdoc/utils.ts +++ b/src/mdoc/utils.ts @@ -120,7 +120,19 @@ export function getRandomBytes(len: number) { return webcrypto.getRandomValues(new Uint8Array(len)); } -export function fromPEM(pem: string): Uint8Array { - const base64 = pem.replace(/-{5}(BEGIN|END) .*-{5}/gm, '').replace(/\s/gm, ''); - return Buffer.from(base64, 'base64'); +export function fromPEM(pem: string): Uint8Array[] { + const certs = pem + .split(/-----END CERTIFICATE-----/) + .map((block) => block.trim()) + .filter((block) => block.length > 0) + .map((block) => { + const fullBlock = `${block}\n-----END CERTIFICATE-----`; + const base64 = fullBlock + .replace(/-----BEGIN CERTIFICATE-----/, '') + .replace(/-----END CERTIFICATE-----/, '') + .replace(/\s+/g, ''); + return Buffer.from(base64, 'base64'); + }); + + return certs; } diff --git a/tmp/device-response.mdl b/tmp/device-response.mdl deleted file mode 100644 index add8202..0000000 Binary files a/tmp/device-response.mdl and /dev/null differ diff --git a/tmp/ephemeral-reader-key b/tmp/ephemeral-reader-key deleted file mode 100644 index cce6899..0000000 --- a/tmp/ephemeral-reader-key +++ /dev/null @@ -1 +0,0 @@ -Þ;Kž_rÝ›X@jã 4ÚH¦ùý ˆü°•Ž,ëì”| \ No newline at end of file diff --git a/tmp/session-transcript b/tmp/session-transcript deleted file mode 100644 index fdd4947..0000000 Binary files a/tmp/session-transcript and /dev/null differ