@credo-ts/core 0.6.2-alpha-20251211125344 → 0.6.2-alpha-20260108172346

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.
Files changed (80) hide show
  1. package/build/crypto/index.d.mts +1 -1
  2. package/build/crypto/index.mjs +1 -0
  3. package/build/crypto/webcrypto/index.d.mts +1 -1
  4. package/build/crypto/webcrypto/index.mjs +1 -0
  5. package/build/crypto/webcrypto/types.d.mts +16 -2
  6. package/build/crypto/webcrypto/types.d.mts.map +1 -1
  7. package/build/crypto/webcrypto/types.mjs +50 -1
  8. package/build/crypto/webcrypto/types.mjs.map +1 -1
  9. package/build/crypto/webcrypto/utils/keyAlgorithmConversion.mjs +1 -2
  10. package/build/crypto/webcrypto/utils/keyAlgorithmConversion.mjs.map +1 -1
  11. package/build/index.d.mts +5 -3
  12. package/build/index.d.mts.map +1 -1
  13. package/build/index.mjs +4 -1
  14. package/build/index.mjs.map +1 -1
  15. package/build/modules/dids/domain/keyDidDocument.mjs +2 -2
  16. package/build/modules/dids/domain/keyDidDocument.mjs.map +1 -1
  17. package/build/modules/dids/methods/jwk/DidJwk.mjs +1 -1
  18. package/build/modules/dids/methods/jwk/DidJwk.mjs.map +1 -1
  19. package/build/modules/kms/jwk/PublicJwk.d.mts +9 -2
  20. package/build/modules/kms/jwk/PublicJwk.d.mts.map +1 -1
  21. package/build/modules/kms/jwk/PublicJwk.mjs +19 -9
  22. package/build/modules/kms/jwk/PublicJwk.mjs.map +1 -1
  23. package/build/modules/kms/jwk/kty/PublicJwk.d.mts +1 -1
  24. package/build/modules/kms/jwk/kty/PublicJwk.d.mts.map +1 -1
  25. package/build/modules/kms/jwk/kty/ec/P256PublicJwk.d.mts +2 -2
  26. package/build/modules/kms/jwk/kty/ec/P256PublicJwk.d.mts.map +1 -1
  27. package/build/modules/kms/jwk/kty/ec/P256PublicJwk.mjs +2 -2
  28. package/build/modules/kms/jwk/kty/ec/P256PublicJwk.mjs.map +1 -1
  29. package/build/modules/kms/jwk/kty/ec/P384PublicJwk.d.mts +2 -2
  30. package/build/modules/kms/jwk/kty/ec/P384PublicJwk.d.mts.map +1 -1
  31. package/build/modules/kms/jwk/kty/ec/P384PublicJwk.mjs +2 -2
  32. package/build/modules/kms/jwk/kty/ec/P384PublicJwk.mjs.map +1 -1
  33. package/build/modules/kms/jwk/kty/ec/P521PublicJwk.d.mts +2 -2
  34. package/build/modules/kms/jwk/kty/ec/P521PublicJwk.d.mts.map +1 -1
  35. package/build/modules/kms/jwk/kty/ec/P521PublicJwk.mjs +2 -2
  36. package/build/modules/kms/jwk/kty/ec/P521PublicJwk.mjs.map +1 -1
  37. package/build/modules/kms/jwk/kty/ec/Secp256k1PublicJwk.d.mts +2 -2
  38. package/build/modules/kms/jwk/kty/ec/Secp256k1PublicJwk.d.mts.map +1 -1
  39. package/build/modules/kms/jwk/kty/ec/Secp256k1PublicJwk.mjs +2 -2
  40. package/build/modules/kms/jwk/kty/ec/Secp256k1PublicJwk.mjs.map +1 -1
  41. package/build/modules/kms/jwk/kty/okp/Ed25519PublicJwk.d.mts +2 -2
  42. package/build/modules/kms/jwk/kty/okp/Ed25519PublicJwk.d.mts.map +1 -1
  43. package/build/modules/kms/jwk/kty/okp/Ed25519PublicJwk.mjs +2 -2
  44. package/build/modules/kms/jwk/kty/okp/Ed25519PublicJwk.mjs.map +1 -1
  45. package/build/modules/kms/jwk/kty/okp/X25519PublicJwk.d.mts +2 -2
  46. package/build/modules/kms/jwk/kty/okp/X25519PublicJwk.d.mts.map +1 -1
  47. package/build/modules/kms/jwk/kty/okp/X25519PublicJwk.mjs +2 -2
  48. package/build/modules/kms/jwk/kty/okp/X25519PublicJwk.mjs.map +1 -1
  49. package/build/modules/kms/jwk/kty/rsa/RsaPublicJwk.d.mts +3 -3
  50. package/build/modules/kms/jwk/kty/rsa/RsaPublicJwk.d.mts.map +1 -1
  51. package/build/modules/kms/jwk/kty/rsa/RsaPublicJwk.mjs +2 -2
  52. package/build/modules/kms/jwk/kty/rsa/RsaPublicJwk.mjs.map +1 -1
  53. package/build/modules/mdoc/MdocContext.mjs +1 -1
  54. package/build/modules/mdoc/MdocContext.mjs.map +1 -1
  55. package/build/modules/x509/CertificateSigningRequest.d.mts +58 -0
  56. package/build/modules/x509/CertificateSigningRequest.d.mts.map +1 -0
  57. package/build/modules/x509/CertificateSigningRequest.mjs +148 -0
  58. package/build/modules/x509/CertificateSigningRequest.mjs.map +1 -0
  59. package/build/modules/x509/X509Api.d.mts +4 -1
  60. package/build/modules/x509/X509Api.d.mts.map +1 -1
  61. package/build/modules/x509/X509Api.mjs +6 -0
  62. package/build/modules/x509/X509Api.mjs.map +1 -1
  63. package/build/modules/x509/X509Certificate.d.mts +4 -4
  64. package/build/modules/x509/X509Certificate.d.mts.map +1 -1
  65. package/build/modules/x509/X509Certificate.mjs +3 -3
  66. package/build/modules/x509/X509Certificate.mjs.map +1 -1
  67. package/build/modules/x509/X509Service.d.mts +8 -3
  68. package/build/modules/x509/X509Service.d.mts.map +1 -1
  69. package/build/modules/x509/X509Service.mjs +10 -2
  70. package/build/modules/x509/X509Service.mjs.map +1 -1
  71. package/build/modules/x509/X509ServiceOptions.d.mts +22 -1
  72. package/build/modules/x509/X509ServiceOptions.d.mts.map +1 -1
  73. package/build/modules/x509/index.d.mts +2 -1
  74. package/build/modules/x509/index.mjs +1 -0
  75. package/build/modules/x509/utils/nameConversion.mjs +1 -1
  76. package/build/modules/x509/utils/nameConversion.mjs.map +1 -1
  77. package/build/utils/IntegrityVerifier.d.mts +44 -0
  78. package/build/utils/IntegrityVerifier.d.mts.map +1 -0
  79. package/build/utils/index.d.mts +1 -0
  80. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"MdocContext.mjs","names":[],"sources":["../../../src/modules/mdoc/MdocContext.ts"],"sourcesContent":["import type { MdocContext, X509Context } from '@animo-id/mdoc'\nimport { p256 } from '@noble/curves/nist.js'\nimport { hkdf } from '@noble/hashes/hkdf.js'\nimport { sha256 } from '@noble/hashes/sha2.js'\nimport type { AgentContext } from '../../agent'\nimport { CredoWebCrypto, Hasher } from '../../crypto'\nimport { TypedArrayEncoder } from '../../utils'\nimport { KeyManagementApi, type KmsJwkPublicAsymmetric, type KnownJwaSignatureAlgorithm, PublicJwk } from '../kms'\nimport { X509Certificate, X509Service } from '../x509'\n\nexport const getMdocContext = (agentContext: AgentContext): MdocContext => {\n const crypto = new CredoWebCrypto(agentContext)\n const kms = agentContext.resolve(KeyManagementApi)\n\n return {\n crypto: {\n digest: async (input) => {\n const { bytes, digestAlgorithm } = input\n\n return new Uint8Array(\n crypto.digest(\n digestAlgorithm,\n // NOTE: extra Uint8Array wrapping is needed here, somehow if we use `bytes.buffer` directly\n // it's not working. Maybe due to Uint8array lengt\n new Uint8Array(bytes).buffer\n )\n )\n },\n random: (length) => {\n return crypto.getRandomValues(new Uint8Array(length))\n },\n calculateEphemeralMacKeyJwk: async (input) => {\n const { privateKey, publicKey, sessionTranscriptBytes } = input\n const ikm = p256.getSharedSecret(privateKey, publicKey, true).slice(1)\n const salt = Hasher.hash(sessionTranscriptBytes, 'sha-256')\n const info = TypedArrayEncoder.fromString('EMacKey')\n const hk1 = hkdf(sha256, ikm, salt, info, 32)\n\n return {\n key_ops: ['sign', 'verify'],\n ext: true,\n kty: 'oct',\n k: TypedArrayEncoder.toBase64URL(hk1),\n alg: 'HS256',\n }\n },\n },\n\n cose: {\n mac0: {\n sign: async (input) => {\n const { jwk, mac0 } = input\n const { data } = mac0.getRawSigningData()\n\n const publicJwk = PublicJwk.fromUnknown(jwk)\n const algorithm = mac0.algName ?? publicJwk.signatureAlgorithm\n\n const { signature } = await kms.sign({\n data,\n algorithm,\n keyId: publicJwk.keyId,\n })\n\n return signature\n },\n verify: async (input) => {\n const { mac0, jwk, options } = input\n const { data, signature } = mac0.getRawVerificationData(options)\n\n const publicJwk = PublicJwk.fromUnknown(jwk)\n const algorithm = mac0.algName ?? publicJwk.signatureAlgorithm\n\n const { verified } = await kms.verify({\n key: {\n publicJwk: jwk as KmsJwkPublicAsymmetric,\n },\n data,\n algorithm,\n signature,\n })\n\n return verified\n },\n },\n sign1: {\n sign: async (input) => {\n const { jwk, sign1 } = input\n const { data } = sign1.getRawSigningData()\n\n const publicJwk = PublicJwk.fromUnknown(jwk)\n const algorithm = sign1.algName ?? publicJwk.signatureAlgorithm\n\n const { signature } = await kms.sign({\n data,\n algorithm: algorithm as KnownJwaSignatureAlgorithm,\n keyId: publicJwk.keyId,\n })\n\n return signature\n },\n verify: async (input) => {\n const { sign1, jwk, options } = input\n const { data, signature } = sign1.getRawVerificationData(options)\n\n const publicJwk = PublicJwk.fromUnknown(jwk)\n const algorithm = sign1.algName ?? publicJwk.signatureAlgorithm\n\n const { verified } = await kms.verify({\n key: {\n publicJwk: jwk as KmsJwkPublicAsymmetric,\n },\n data,\n algorithm: algorithm as KnownJwaSignatureAlgorithm,\n signature,\n })\n\n return verified\n },\n },\n },\n\n x509: {\n getIssuerNameField: (input) => {\n const { certificate, field } = input\n const x509Certificate = X509Certificate.fromRawCertificate(certificate)\n return x509Certificate.getIssuerNameField(field)\n },\n getPublicKey: async (input) => {\n const certificate = X509Certificate.fromRawCertificate(input.certificate)\n return certificate.publicJwk.toJson()\n },\n validateCertificateChain: async (input) => {\n const certificateChain = input.x5chain.map((cert) => X509Certificate.fromRawCertificate(cert).toString('pem'))\n const trustedCertificates = input.trustedCertificates.map((cert) =>\n X509Certificate.fromRawCertificate(cert).toString('pem')\n ) as [string, ...string[]]\n\n await X509Service.validateCertificateChain(agentContext, {\n certificateChain,\n trustedCertificates,\n })\n },\n getCertificateData: async (input) => {\n const { certificate } = input\n const x509Certificate = X509Certificate.fromRawCertificate(certificate)\n return {\n ...x509Certificate.data,\n thumbprint: await x509Certificate.getThumprintInHex(agentContext),\n }\n },\n } satisfies X509Context,\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"MdocContext.mjs","names":[],"sources":["../../../src/modules/mdoc/MdocContext.ts"],"sourcesContent":["import type { MdocContext, X509Context } from '@animo-id/mdoc'\nimport { p256 } from '@noble/curves/nist.js'\nimport { hkdf } from '@noble/hashes/hkdf.js'\nimport { sha256 } from '@noble/hashes/sha2.js'\nimport type { AgentContext } from '../../agent'\nimport { CredoWebCrypto, Hasher } from '../../crypto'\nimport { TypedArrayEncoder } from '../../utils'\nimport { KeyManagementApi, type KmsJwkPublicAsymmetric, type KnownJwaSignatureAlgorithm, PublicJwk } from '../kms'\nimport { X509Certificate, X509Service } from '../x509'\n\nexport const getMdocContext = (agentContext: AgentContext): MdocContext => {\n const crypto = new CredoWebCrypto(agentContext)\n const kms = agentContext.resolve(KeyManagementApi)\n\n return {\n crypto: {\n digest: async (input) => {\n const { bytes, digestAlgorithm } = input\n\n return new Uint8Array(\n crypto.digest(\n digestAlgorithm,\n // NOTE: extra Uint8Array wrapping is needed here, somehow if we use `bytes.buffer` directly\n // it's not working. Maybe due to Uint8array lengt\n new Uint8Array(bytes).buffer\n )\n )\n },\n random: (length) => {\n return crypto.getRandomValues(new Uint8Array(length))\n },\n calculateEphemeralMacKeyJwk: async (input) => {\n const { privateKey, publicKey, sessionTranscriptBytes } = input\n const ikm = p256.getSharedSecret(privateKey, publicKey, true).slice(1)\n const salt = Hasher.hash(sessionTranscriptBytes, 'sha-256')\n const info = TypedArrayEncoder.fromString('EMacKey')\n const hk1 = hkdf(sha256, ikm, salt, info, 32)\n\n return {\n key_ops: ['sign', 'verify'],\n ext: true,\n kty: 'oct',\n k: TypedArrayEncoder.toBase64URL(hk1),\n alg: 'HS256',\n }\n },\n },\n\n cose: {\n mac0: {\n sign: async (input) => {\n const { jwk, mac0 } = input\n const { data } = mac0.getRawSigningData()\n\n const publicJwk = PublicJwk.fromUnknown(jwk)\n const algorithm = mac0.algName ?? publicJwk.signatureAlgorithm\n\n const { signature } = await kms.sign({\n data,\n algorithm,\n keyId: publicJwk.keyId,\n })\n\n return signature\n },\n verify: async (input) => {\n const { mac0, jwk, options } = input\n const { data, signature } = mac0.getRawVerificationData(options)\n\n const publicJwk = PublicJwk.fromUnknown(jwk)\n const algorithm = mac0.algName ?? publicJwk.signatureAlgorithm\n\n const { verified } = await kms.verify({\n key: {\n publicJwk: jwk as KmsJwkPublicAsymmetric,\n },\n data,\n algorithm,\n signature,\n })\n\n return verified\n },\n },\n sign1: {\n sign: async (input) => {\n const { jwk, sign1 } = input\n const { data } = sign1.getRawSigningData()\n\n const publicJwk = PublicJwk.fromUnknown(jwk)\n const algorithm = sign1.algName ?? publicJwk.signatureAlgorithm\n\n const { signature } = await kms.sign({\n data,\n algorithm: algorithm as KnownJwaSignatureAlgorithm,\n keyId: publicJwk.keyId,\n })\n\n return signature\n },\n verify: async (input) => {\n const { sign1, jwk, options } = input\n const { data, signature } = sign1.getRawVerificationData(options)\n\n const publicJwk = PublicJwk.fromUnknown(jwk)\n const algorithm = sign1.algName ?? publicJwk.signatureAlgorithm\n\n const { verified } = await kms.verify({\n key: {\n publicJwk: jwk as KmsJwkPublicAsymmetric,\n },\n data,\n algorithm: algorithm as KnownJwaSignatureAlgorithm,\n signature,\n })\n\n return verified\n },\n },\n },\n\n x509: {\n getIssuerNameField: (input) => {\n const { certificate, field } = input\n const x509Certificate = X509Certificate.fromRawCertificate(certificate)\n return x509Certificate.getIssuerNameField(field)\n },\n getPublicKey: async (input) => {\n const certificate = X509Certificate.fromRawCertificate(input.certificate)\n return certificate.publicJwk.toJson()\n },\n validateCertificateChain: async (input) => {\n const certificateChain = input.x5chain.map((cert) => X509Certificate.fromRawCertificate(cert).toString('pem'))\n const trustedCertificates = input.trustedCertificates.map((cert) =>\n X509Certificate.fromRawCertificate(cert).toString('pem')\n ) as [string, ...string[]]\n\n await X509Service.validateCertificateChain(agentContext, {\n certificateChain,\n trustedCertificates,\n })\n },\n getCertificateData: async (input) => {\n const { certificate } = input\n const x509Certificate = X509Certificate.fromRawCertificate(certificate)\n return {\n ...x509Certificate.data,\n thumbprint: await x509Certificate.getThumbprintInHex(agentContext),\n }\n },\n } satisfies X509Context,\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,58 @@
1
+ import { AnyUint8Array } from "../../types.mjs";
2
+ import { CredoWebCrypto } from "../../crypto/webcrypto/CredoWebCrypto.mjs";
3
+ import "../../crypto/webcrypto/index.mjs";
4
+ import { X509CreateCertificateSigningRequestOptions } from "./X509ServiceOptions.mjs";
5
+ import { X509ExtendedKeyUsage, X509KeyUsage } from "./X509Certificate.mjs";
6
+ import { PublicJwk } from "../kms/jwk/PublicJwk.mjs";
7
+ import "../kms/index.mjs";
8
+ import * as x509 from "@peculiar/x509";
9
+
10
+ //#region src/modules/x509/CertificateSigningRequest.d.ts
11
+ type CertificateSigningRequestOptions = {
12
+ publicJwk: PublicJwk;
13
+ certificateRequest: x509.Pkcs10CertificateRequest;
14
+ };
15
+ declare class CertificateSigningRequest {
16
+ publicJwk: PublicJwk;
17
+ private certificateRequest;
18
+ private constructor();
19
+ set keyId(keyId: string);
20
+ get keyId(): string;
21
+ get hasKeyId(): boolean;
22
+ static fromRawCertificateRequest(rawCertificateRequest: AnyUint8Array): CertificateSigningRequest;
23
+ static fromEncodedCertificateRequest(encodedCertificateRequest: string): CertificateSigningRequest;
24
+ private static parseCertificateRequest;
25
+ private getMatchingExtensions;
26
+ get rawCertificateRequest(): Uint8Array<ArrayBuffer>;
27
+ get subjectAlternativeNames(): {
28
+ type: x509.GeneralNameType;
29
+ value: string;
30
+ }[];
31
+ get sanDnsNames(): string[];
32
+ get sanUriNames(): string[];
33
+ get subjectKeyIdentifier(): string | undefined;
34
+ get keyUsage(): X509KeyUsage[];
35
+ get extendedKeyUsage(): X509ExtendedKeyUsage[];
36
+ isExtensionCritical(id: string): boolean;
37
+ static create(options: X509CreateCertificateSigningRequestOptions, webCrypto: CredoWebCrypto): Promise<CertificateSigningRequest>;
38
+ get subject(): string;
39
+ get subjectName(): string;
40
+ verify(webCrypto: CredoWebCrypto): Promise<void>;
41
+ /**
42
+ * Get the data elements of the certificate signing request
43
+ */
44
+ get data(): {
45
+ subjectName: string;
46
+ subject: string;
47
+ pem: string;
48
+ };
49
+ getSubjectNameField(field: string): string[];
50
+ /**
51
+ * @param format the format to export to, defaults to `pem`
52
+ */
53
+ toString(format?: 'asn' | 'pem' | 'hex' | 'base64' | 'text' | 'base64url'): string;
54
+ equal(certificateRequest: CertificateSigningRequest): boolean;
55
+ }
56
+ //#endregion
57
+ export { CertificateSigningRequest, CertificateSigningRequestOptions };
58
+ //# sourceMappingURL=CertificateSigningRequest.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CertificateSigningRequest.d.mts","names":[],"sources":["../../../src/modules/x509/CertificateSigningRequest.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;KA6BY,gCAAA;aACC;sBACS,IAAA,CAAK;;cAGd,yBAAA;aACO;EANR,QAAA,kBAAA;EAKC,QAAA,WAAA,CAAA;EACO,IAAA,KAAA,CAAA,KAAA,EAAA,MAAA;EAoB6C,IAAA,KAAA,CAAA,CAAA,EAAA,MAAA;EAAgB,IAAA,QAAA,CAAA,CAAA,EAAA,OAAA;EAKC,OAAA,yBAAA,CAAA,qBAAA,EALjB,aAKiB,CAAA,EALD,yBAKC;EAqBhD,OAAA,6BAAA,CAAA,yBAAA,EAAA,MAAA,CAAA,EArBgD,yBAqBhD;EAAA,eAAA,uBAAA;;EA6Bb,IAAA,qBAAA,CAAA,CAAA,EA7Ba,UA6Bb,CA7Ba,WA6Bb,CAAA;EAiBQ,IAAA,uBAAA,CAAA,CAAA,EAAA;IAqBS,IAAA,sBAAA;IAAuD,KAAA,EAAA,MAAA;EAAc,CAAA,EAAA;EAAA,IAAA,WAAA,CAAA,CAAA,EAAA,MAAA,EAAA;EAuD1E,IAAA,WAAA,CAAA,CAAA,EAAA,MAAA,EAAA;EAAc,IAAA,oBAAA,CAAA,CAAA,EAAA,MAAA,GAAA,SAAA;EAgCZ,IAAA,QAAA,CAAA,CAAA,EA7Hd,YA6Hc,EAAA;EAAyB,IAAA,gBAAA,CAAA,CAAA,EA5G/B,oBA4G+B,EAAA;;yBAvFtB,uDAAuD,iBAAc,QAAA;;;oBAuD1E,iBAAc;;;;;;;;;;;;;;4BAgCZ"}
@@ -0,0 +1,148 @@
1
+
2
+
3
+ import "../kms/index.mjs";
4
+ import { CredoWebCryptoKey } from "../../crypto/webcrypto/CredoWebCryptoKey.mjs";
5
+ import { jwaAlgorithmToKeySignParams } from "../../crypto/webcrypto/types.mjs";
6
+ import { publicJwkToCryptoKeyAlgorithm, spkiToPublicJwk } from "../../crypto/webcrypto/utils/keyAlgorithmConversion.mjs";
7
+ import "../../crypto/webcrypto/utils/index.mjs";
8
+ import "../../crypto/webcrypto/index.mjs";
9
+ import { createExtendedKeyUsagesExtension, createKeyUsagesExtension, createSubjectAlternativeNameExtension, createSubjectKeyIdentifierExtension } from "./utils/extensions.mjs";
10
+ import { X509Error } from "./X509Error.mjs";
11
+ import { convertName } from "./utils/nameConversion.mjs";
12
+ import "./utils/index.mjs";
13
+ import { X509KeyUsage } from "./X509Certificate.mjs";
14
+ import { AsnParser } from "@peculiar/asn1-schema";
15
+ import { SubjectPublicKeyInfo, id_ce_extKeyUsage, id_ce_keyUsage, id_ce_subjectAltName, id_ce_subjectKeyIdentifier } from "@peculiar/asn1-x509";
16
+ import * as x509 from "@peculiar/x509";
17
+
18
+ //#region src/modules/x509/CertificateSigningRequest.ts
19
+ var CertificateSigningRequest = class CertificateSigningRequest {
20
+ constructor(options) {
21
+ this.publicJwk = options.publicJwk;
22
+ this.certificateRequest = options.certificateRequest;
23
+ }
24
+ set keyId(keyId) {
25
+ this.publicJwk.keyId = keyId;
26
+ }
27
+ get keyId() {
28
+ return this.publicJwk.keyId;
29
+ }
30
+ get hasKeyId() {
31
+ return this.publicJwk.hasKeyId;
32
+ }
33
+ static fromRawCertificateRequest(rawCertificateRequest) {
34
+ const certificateRequest = new x509.Pkcs10CertificateRequest(rawCertificateRequest);
35
+ return CertificateSigningRequest.parseCertificateRequest(certificateRequest);
36
+ }
37
+ static fromEncodedCertificateRequest(encodedCertificateRequest) {
38
+ const certificateRequest = new x509.Pkcs10CertificateRequest(encodedCertificateRequest);
39
+ return CertificateSigningRequest.parseCertificateRequest(certificateRequest);
40
+ }
41
+ static parseCertificateRequest(certificateRequest) {
42
+ return new CertificateSigningRequest({
43
+ publicJwk: spkiToPublicJwk(AsnParser.parse(certificateRequest.publicKey.rawData, SubjectPublicKeyInfo)),
44
+ certificateRequest
45
+ });
46
+ }
47
+ getMatchingExtensions(objectIdentifier) {
48
+ const matchingExtensions = this.certificateRequest.extensions.filter((e) => e.type === objectIdentifier);
49
+ if (matchingExtensions.length === 0) return void 0;
50
+ return matchingExtensions;
51
+ }
52
+ get rawCertificateRequest() {
53
+ return new Uint8Array(this.certificateRequest.rawData);
54
+ }
55
+ get subjectAlternativeNames() {
56
+ return this.getMatchingExtensions(id_ce_subjectAltName)?.flatMap((s) => s.names.items ?? []).map((i) => ({
57
+ type: i.type,
58
+ value: i.value
59
+ })) ?? [];
60
+ }
61
+ get sanDnsNames() {
62
+ return this.subjectAlternativeNames.filter((san) => san.type === "dns").map((san) => san.value);
63
+ }
64
+ get sanUriNames() {
65
+ return this.subjectAlternativeNames.filter((san) => san.type === "url").map((san) => san.value);
66
+ }
67
+ get subjectKeyIdentifier() {
68
+ const keyIds = this.getMatchingExtensions(id_ce_subjectKeyIdentifier)?.map((e) => e.keyId);
69
+ if (keyIds && keyIds.length > 1) throw new X509Error("Multiple Subject Key Identifiers are not allowed");
70
+ return keyIds?.[0];
71
+ }
72
+ get keyUsage() {
73
+ const keyUsages = this.getMatchingExtensions(id_ce_keyUsage)?.map((e) => e.usages);
74
+ if (keyUsages && keyUsages.length > 1) throw new X509Error("Multiple Key Usages are not allowed");
75
+ if (keyUsages && keyUsages.length > 0) return Object.values(X509KeyUsage).filter((key) => typeof key === "number").filter((flagValue) => (keyUsages[0] & flagValue) === flagValue).map((flagValue) => flagValue);
76
+ return [];
77
+ }
78
+ get extendedKeyUsage() {
79
+ const extendedKeyUsages = this.getMatchingExtensions(id_ce_extKeyUsage)?.map((e) => e.usages);
80
+ if (extendedKeyUsages && extendedKeyUsages.length > 1) throw new X509Error("Multiple Extended Key Usages are not allowed");
81
+ return extendedKeyUsages?.[0] ?? [];
82
+ }
83
+ isExtensionCritical(id) {
84
+ const extension = this.getMatchingExtensions(id);
85
+ if (!extension) throw new X509Error(`extension with id '${id}' is not found`);
86
+ return !!extension[0].critical;
87
+ }
88
+ static async create(options, webCrypto) {
89
+ const signingKey = new CredoWebCryptoKey(options.subjectPublicKey, publicJwkToCryptoKeyAlgorithm(options.subjectPublicKey), false, "private", ["sign"]);
90
+ const publicKey = new CredoWebCryptoKey(options.subjectPublicKey, publicJwkToCryptoKeyAlgorithm(options.subjectPublicKey), true, "public", ["verify"]);
91
+ const extensions = [];
92
+ extensions.push(createSubjectKeyIdentifierExtension(options.extensions?.subjectKeyIdentifier, { publicJwk: options.subjectPublicKey }));
93
+ extensions.push(createKeyUsagesExtension(options.extensions?.keyUsage));
94
+ extensions.push(createExtendedKeyUsagesExtension(options.extensions?.extendedKeyUsage));
95
+ extensions.push(createSubjectAlternativeNameExtension(options.extensions?.subjectAlternativeName));
96
+ const subjectName = convertName(options.subject);
97
+ const jwaAlgorithm = options.subjectPublicKey.signatureAlgorithm;
98
+ const signingAlgorithm = jwaAlgorithmToKeySignParams(jwaAlgorithm);
99
+ const csr = await x509.Pkcs10CertificateRequestGenerator.create({
100
+ keys: {
101
+ publicKey,
102
+ privateKey: signingKey
103
+ },
104
+ name: subjectName,
105
+ signingAlgorithm,
106
+ extensions: extensions.filter((e) => e !== void 0)
107
+ }, webCrypto);
108
+ const csrInstance = CertificateSigningRequest.parseCertificateRequest(csr);
109
+ if (options.subjectPublicKey.hasKeyId) csrInstance.publicJwk.keyId = options.subjectPublicKey.keyId;
110
+ return csrInstance;
111
+ }
112
+ get subject() {
113
+ return this.certificateRequest.subject;
114
+ }
115
+ get subjectName() {
116
+ return this.certificateRequest.subjectName.toString();
117
+ }
118
+ async verify(webCrypto) {
119
+ if (!await this.certificateRequest.verify(webCrypto)) throw new X509Error(`Certificate Signing Request for '${this.certificateRequest.subject}' has an invalid signature`);
120
+ }
121
+ /**
122
+ * Get the data elements of the certificate signing request
123
+ */
124
+ get data() {
125
+ return {
126
+ subjectName: this.certificateRequest.subjectName.toString(),
127
+ subject: this.certificateRequest.subject,
128
+ pem: this.certificateRequest.toString()
129
+ };
130
+ }
131
+ getSubjectNameField(field) {
132
+ return this.certificateRequest.subjectName.getField(field);
133
+ }
134
+ /**
135
+ * @param format the format to export to, defaults to `pem`
136
+ */
137
+ toString(format) {
138
+ return this.certificateRequest.toString(format ?? "pem");
139
+ }
140
+ equal(certificateRequest) {
141
+ const parsedOther = new x509.Pkcs10CertificateRequest(certificateRequest.rawCertificateRequest);
142
+ return this.certificateRequest.equal(parsedOther);
143
+ }
144
+ };
145
+
146
+ //#endregion
147
+ export { CertificateSigningRequest };
148
+ //# sourceMappingURL=CertificateSigningRequest.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CertificateSigningRequest.mjs","names":["extensions: Array<x509.Extension | undefined>"],"sources":["../../../src/modules/x509/CertificateSigningRequest.ts"],"sourcesContent":["import { AsnParser } from '@peculiar/asn1-schema'\nimport {\n id_ce_extKeyUsage,\n id_ce_keyUsage,\n id_ce_subjectAltName,\n id_ce_subjectKeyIdentifier,\n SubjectPublicKeyInfo,\n} from '@peculiar/asn1-x509'\nimport * as x509 from '@peculiar/x509'\nimport {\n CredoWebCrypto,\n CredoWebCryptoKey,\n jwaAlgorithmToKeySignParams,\n publicJwkToCryptoKeyAlgorithm,\n} from '../../crypto/webcrypto'\nimport { spkiToPublicJwk } from '../../crypto/webcrypto/utils'\nimport type { AnyUint8Array } from '../../types'\nimport { PublicJwk } from '../kms'\nimport {\n convertName,\n createExtendedKeyUsagesExtension,\n createKeyUsagesExtension,\n createSubjectAlternativeNameExtension,\n createSubjectKeyIdentifierExtension,\n} from './utils'\nimport { X509ExtendedKeyUsage, X509KeyUsage } from './X509Certificate'\nimport { X509Error } from './X509Error'\nimport type { X509CreateCertificateSigningRequestOptions } from './X509ServiceOptions'\n\nexport type CertificateSigningRequestOptions = {\n publicJwk: PublicJwk\n certificateRequest: x509.Pkcs10CertificateRequest\n}\n\nexport class CertificateSigningRequest {\n public publicJwk: PublicJwk\n private certificateRequest: x509.Pkcs10CertificateRequest\n\n private constructor(options: CertificateSigningRequestOptions) {\n this.publicJwk = options.publicJwk\n this.certificateRequest = options.certificateRequest\n }\n\n public set keyId(keyId: string) {\n this.publicJwk.keyId = keyId\n }\n\n public get keyId(): string {\n return this.publicJwk.keyId\n }\n\n public get hasKeyId(): boolean {\n return this.publicJwk.hasKeyId\n }\n\n public static fromRawCertificateRequest(rawCertificateRequest: AnyUint8Array): CertificateSigningRequest {\n const certificateRequest = new x509.Pkcs10CertificateRequest(rawCertificateRequest)\n return CertificateSigningRequest.parseCertificateRequest(certificateRequest)\n }\n\n public static fromEncodedCertificateRequest(encodedCertificateRequest: string): CertificateSigningRequest {\n const certificateRequest = new x509.Pkcs10CertificateRequest(encodedCertificateRequest)\n return CertificateSigningRequest.parseCertificateRequest(certificateRequest)\n }\n\n private static parseCertificateRequest(certificateRequest: x509.Pkcs10CertificateRequest): CertificateSigningRequest {\n const spki = AsnParser.parse(certificateRequest.publicKey.rawData, SubjectPublicKeyInfo)\n const publicJwk = spkiToPublicJwk(spki)\n\n return new CertificateSigningRequest({\n publicJwk,\n certificateRequest,\n })\n }\n\n private getMatchingExtensions<T = { critical: boolean }>(objectIdentifier: string): Array<T> | undefined {\n const matchingExtensions = this.certificateRequest.extensions.filter((e) => e.type === objectIdentifier)\n if (matchingExtensions.length === 0) return undefined\n return matchingExtensions as Array<T>\n }\n\n public get rawCertificateRequest() {\n return new Uint8Array(this.certificateRequest.rawData)\n }\n\n public get subjectAlternativeNames() {\n const san = this.getMatchingExtensions<x509.SubjectAlternativeNameExtension>(id_ce_subjectAltName)\n return san?.flatMap((s) => s.names.items ?? []).map((i) => ({ type: i.type, value: i.value })) ?? []\n }\n\n public get sanDnsNames() {\n return this.subjectAlternativeNames.filter((san) => san.type === 'dns').map((san) => san.value)\n }\n\n public get sanUriNames() {\n return this.subjectAlternativeNames.filter((san) => san.type === 'url').map((san) => san.value)\n }\n\n public get subjectKeyIdentifier() {\n const keyIds = this.getMatchingExtensions<x509.SubjectKeyIdentifierExtension>(id_ce_subjectKeyIdentifier)?.map(\n (e) => e.keyId\n )\n\n if (keyIds && keyIds.length > 1) {\n throw new X509Error('Multiple Subject Key Identifiers are not allowed')\n }\n\n return keyIds?.[0]\n }\n\n public get keyUsage() {\n const keyUsages = this.getMatchingExtensions<x509.KeyUsagesExtension>(id_ce_keyUsage)?.map((e) => e.usages)\n\n if (keyUsages && keyUsages.length > 1) {\n throw new X509Error('Multiple Key Usages are not allowed')\n }\n\n if (keyUsages && keyUsages.length > 0) {\n return Object.values(X509KeyUsage)\n .filter((key): key is number => typeof key === 'number')\n .filter((flagValue) => (keyUsages[0] & flagValue) === flagValue)\n .map((flagValue) => flagValue as X509KeyUsage)\n }\n\n return []\n }\n\n public get extendedKeyUsage() {\n const extendedKeyUsages = this.getMatchingExtensions<x509.ExtendedKeyUsageExtension>(id_ce_extKeyUsage)?.map(\n (e) => e.usages\n )\n\n if (extendedKeyUsages && extendedKeyUsages.length > 1) {\n throw new X509Error('Multiple Extended Key Usages are not allowed')\n }\n\n return (extendedKeyUsages?.[0] as Array<X509ExtendedKeyUsage> | undefined) ?? []\n }\n\n public isExtensionCritical(id: string): boolean {\n const extension = this.getMatchingExtensions(id)\n if (!extension) {\n throw new X509Error(`extension with id '${id}' is not found`)\n }\n\n return !!extension[0].critical\n }\n\n public static async create(options: X509CreateCertificateSigningRequestOptions, webCrypto: CredoWebCrypto) {\n const signingKey = new CredoWebCryptoKey(\n options.subjectPublicKey,\n publicJwkToCryptoKeyAlgorithm(options.subjectPublicKey),\n false,\n 'private',\n ['sign']\n )\n const publicKey = new CredoWebCryptoKey(\n options.subjectPublicKey,\n publicJwkToCryptoKeyAlgorithm(options.subjectPublicKey),\n true,\n 'public',\n ['verify']\n )\n\n const extensions: Array<x509.Extension | undefined> = []\n extensions.push(\n createSubjectKeyIdentifierExtension(options.extensions?.subjectKeyIdentifier, {\n publicJwk: options.subjectPublicKey,\n })\n )\n extensions.push(createKeyUsagesExtension(options.extensions?.keyUsage))\n extensions.push(createExtendedKeyUsagesExtension(options.extensions?.extendedKeyUsage))\n extensions.push(createSubjectAlternativeNameExtension(options.extensions?.subjectAlternativeName))\n\n const subjectName = convertName(options.subject)\n\n // Get the JWA signature algorithm from the public key and convert to KeySignParams\n const jwaAlgorithm = options.subjectPublicKey.signatureAlgorithm\n const signingAlgorithm = jwaAlgorithmToKeySignParams(jwaAlgorithm)\n\n const csr = await x509.Pkcs10CertificateRequestGenerator.create(\n {\n keys: { publicKey, privateKey: signingKey },\n name: subjectName,\n signingAlgorithm,\n extensions: extensions.filter((e) => e !== undefined),\n },\n webCrypto\n )\n\n const csrInstance = CertificateSigningRequest.parseCertificateRequest(csr)\n if (options.subjectPublicKey.hasKeyId) csrInstance.publicJwk.keyId = options.subjectPublicKey.keyId\n return csrInstance\n }\n\n public get subject() {\n return this.certificateRequest.subject\n }\n\n public get subjectName() {\n return this.certificateRequest.subjectName.toString()\n }\n\n public async verify(webCrypto: CredoWebCrypto) {\n const isValid = await this.certificateRequest.verify(webCrypto)\n\n if (!isValid) {\n throw new X509Error(\n `Certificate Signing Request for '${this.certificateRequest.subject}' has an invalid signature`\n )\n }\n }\n\n /**\n * Get the data elements of the certificate signing request\n */\n public get data() {\n return {\n subjectName: this.certificateRequest.subjectName.toString(),\n subject: this.certificateRequest.subject,\n pem: this.certificateRequest.toString(),\n }\n }\n\n public getSubjectNameField(field: string) {\n return this.certificateRequest.subjectName.getField(field)\n }\n\n /**\n * @param format the format to export to, defaults to `pem`\n */\n public toString(format?: 'asn' | 'pem' | 'hex' | 'base64' | 'text' | 'base64url') {\n return this.certificateRequest.toString(format ?? 'pem')\n }\n\n public equal(certificateRequest: CertificateSigningRequest) {\n const parsedOther = new x509.Pkcs10CertificateRequest(certificateRequest.rawCertificateRequest)\n\n return this.certificateRequest.equal(parsedOther)\n }\n}\n"],"mappings":"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"}
@@ -1,5 +1,6 @@
1
- import { X509CreateCertificateOptions, X509ValidateCertificateChainOptions } from "./X509ServiceOptions.mjs";
1
+ import { X509CreateCertificateOptions, X509CreateCertificateSigningRequestOptions, X509ParseCertificateSigningRequestOptions, X509ValidateCertificateChainOptions } from "./X509ServiceOptions.mjs";
2
2
  import { X509Certificate } from "./X509Certificate.mjs";
3
+ import { CertificateSigningRequest } from "./CertificateSigningRequest.mjs";
3
4
  import { X509ModuleConfig } from "./X509ModuleConfig.mjs";
4
5
  import { AgentContext } from "../../agent/context/AgentContext.mjs";
5
6
  import "../../agent/index.mjs";
@@ -18,6 +19,8 @@ declare class X509Api {
18
19
  * @param options X509CreateCertificateOptions
19
20
  */
20
21
  createCertificate(options: X509CreateCertificateOptions): Promise<X509Certificate>;
22
+ createCertificateSigningRequest(options: X509CreateCertificateSigningRequestOptions): Promise<CertificateSigningRequest>;
23
+ parseCertificateSigningRequest(options: X509ParseCertificateSigningRequestOptions): CertificateSigningRequest;
21
24
  /**
22
25
  * Validate a certificate chain.
23
26
  *
@@ -1 +1 @@
1
- {"version":3,"file":"X509Api.d.mts","names":[],"sources":["../../../src/modules/x509/X509Api.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;cAWa,OAAA;;UAGM;EAHN,WAAO,CAAA,YAAA,EAEM,YAFN,EAAA,MAAA,EAGD,gBAHC;EAGD;;;;;EAQmD,iBAAA,CAAA,OAAA,EAA5B,4BAA4B,CAAA,EAAA,OAAA,CAAA,eAAA,CAAA;EASrB;;;;;oCAAA,sCAAmC,QAAA,eAAA"}
1
+ {"version":3,"file":"X509Api.d.mts","names":[],"sources":["../../../src/modules/x509/X509Api.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;cAgBa,OAAA;;UAGM;4BADO,sBACP;EAHN;;;;;EAWyD,iBAAA,CAAA,OAAA,EAA5B,4BAA4B,CAAA,EAAA,OAAA,CAAA,eAAA,CAAA;EAAA,+BAAA,CAAA,OAAA,EAId,0CAJc,CAAA,EAI4B,OAJ5B,CAI4B,yBAAA,CAJ5B;EAId,8BAAA,CAAA,OAAA,EAIP,yCAJO,CAAA,EAIkC,yBAJlC;EAA0C;;;;;EAad,wBAAA,CAAA,OAAA,EAAnC,mCAAmC,CAAA,EAAA,OAAA,CAAA,eAAA,EAAA,CAAA"}
@@ -23,6 +23,12 @@ let X509Api = class X509Api$1 {
23
23
  async createCertificate(options) {
24
24
  return await X509Service.createCertificate(this.agentContext, options);
25
25
  }
26
+ async createCertificateSigningRequest(options) {
27
+ return await X509Service.createCertificateSigningRequest(this.agentContext, options);
28
+ }
29
+ parseCertificateSigningRequest(options) {
30
+ return X509Service.parseCertificateSigningRequest(options);
31
+ }
26
32
  /**
27
33
  * Validate a certificate chain.
28
34
  *
@@ -1 +1 @@
1
- {"version":3,"file":"X509Api.mjs","names":["X509Api","agentContext: AgentContext","config: X509ModuleConfig"],"sources":["../../../src/modules/x509/X509Api.ts"],"sourcesContent":["import { AgentContext } from '../../agent'\nimport { injectable } from '../../plugins'\n\nimport { X509ModuleConfig } from './X509ModuleConfig'\nimport { X509Service } from './X509Service'\nimport type { X509CreateCertificateOptions, X509ValidateCertificateChainOptions } from './X509ServiceOptions'\n\n/**\n * @public\n */\n@injectable()\nexport class X509Api {\n public constructor(\n private agentContext: AgentContext,\n public config: X509ModuleConfig\n ) {}\n\n /**\n * Creates a X.509 certificate.\n *\n * @param options X509CreateCertificateOptions\n */\n public async createCertificate(options: X509CreateCertificateOptions) {\n return await X509Service.createCertificate(this.agentContext, options)\n }\n\n /**\n * Validate a certificate chain.\n *\n * @param options X509ValidateCertificateChainOptions\n */\n public async validateCertificateChain(options: X509ValidateCertificateChainOptions) {\n return await X509Service.validateCertificateChain(this.agentContext, options)\n }\n}\n"],"mappings":";;;;;;;;;;;;AAWO,oBAAMA,UAAQ;CACnB,AAAO,YACL,AAAQC,cACR,AAAOC,QACP;EAFQ;EACD;;;;;;;CAQT,MAAa,kBAAkB,SAAuC;AACpE,SAAO,MAAM,YAAY,kBAAkB,KAAK,cAAc,QAAQ;;;;;;;CAQxE,MAAa,yBAAyB,SAA8C;AAClF,SAAO,MAAM,YAAY,yBAAyB,KAAK,cAAc,QAAQ;;;sBAtBhF,YAAY"}
1
+ {"version":3,"file":"X509Api.mjs","names":["X509Api","agentContext: AgentContext","config: X509ModuleConfig"],"sources":["../../../src/modules/x509/X509Api.ts"],"sourcesContent":["import { AgentContext } from '../../agent'\nimport { injectable } from '../../plugins'\n\nimport { X509ModuleConfig } from './X509ModuleConfig'\nimport { X509Service } from './X509Service'\nimport type {\n X509CreateCertificateOptions,\n X509CreateCertificateSigningRequestOptions,\n X509ParseCertificateSigningRequestOptions,\n X509ValidateCertificateChainOptions,\n} from './X509ServiceOptions'\n\n/**\n * @public\n */\n@injectable()\nexport class X509Api {\n public constructor(\n private agentContext: AgentContext,\n public config: X509ModuleConfig\n ) {}\n\n /**\n * Creates a X.509 certificate.\n *\n * @param options X509CreateCertificateOptions\n */\n public async createCertificate(options: X509CreateCertificateOptions) {\n return await X509Service.createCertificate(this.agentContext, options)\n }\n\n public async createCertificateSigningRequest(options: X509CreateCertificateSigningRequestOptions) {\n return await X509Service.createCertificateSigningRequest(this.agentContext, options)\n }\n\n public parseCertificateSigningRequest(options: X509ParseCertificateSigningRequestOptions) {\n return X509Service.parseCertificateSigningRequest(options)\n }\n\n /**\n * Validate a certificate chain.\n *\n * @param options X509ValidateCertificateChainOptions\n */\n public async validateCertificateChain(options: X509ValidateCertificateChainOptions) {\n return await X509Service.validateCertificateChain(this.agentContext, options)\n }\n}\n"],"mappings":";;;;;;;;;;;;AAgBO,oBAAMA,UAAQ;CACnB,AAAO,YACL,AAAQC,cACR,AAAOC,QACP;EAFQ;EACD;;;;;;;CAQT,MAAa,kBAAkB,SAAuC;AACpE,SAAO,MAAM,YAAY,kBAAkB,KAAK,cAAc,QAAQ;;CAGxE,MAAa,gCAAgC,SAAqD;AAChG,SAAO,MAAM,YAAY,gCAAgC,KAAK,cAAc,QAAQ;;CAGtF,AAAO,+BAA+B,SAAoD;AACxF,SAAO,YAAY,+BAA+B,QAAQ;;;;;;;CAQ5D,MAAa,yBAAyB,SAA8C;AAClF,SAAO,MAAM,YAAY,yBAAyB,KAAK,cAAc,QAAQ;;;sBA9BhF,YAAY"}
@@ -62,7 +62,7 @@ declare class X509Certificate {
62
62
  get authorityKeyIdentifier(): string | undefined;
63
63
  get subjectKeyIdentifier(): string | undefined;
64
64
  get keyUsage(): X509KeyUsage[] | undefined;
65
- get extendedKeyUsage(): X509ExtendedKeyUsage | undefined;
65
+ get extendedKeyUsage(): X509ExtendedKeyUsage[];
66
66
  isExtensionCritical(id: string): boolean;
67
67
  static create(options: X509CreateCertificateOptions, webCrypto: CredoWebCrypto): Promise<X509Certificate>;
68
68
  get subject(): string;
@@ -79,7 +79,7 @@ declare class X509Certificate {
79
79
  * as whether the certificate is not expired).
80
80
  *
81
81
  * This can be useful when an non-self-signed certificate is directly trusted, and it may
82
- * not be possible to verify the certifcate as the root/intermediate certificate containing
82
+ * not be possible to verify the certificate as the root/intermediate certificate containing
83
83
  * the key of the signer/intermediate is not present.
84
84
  *
85
85
  * @default false
@@ -87,9 +87,9 @@ declare class X509Certificate {
87
87
  skipSignatureVerification?: boolean;
88
88
  }, webCrypto: CredoWebCrypto): Promise<void>;
89
89
  /**
90
- * Get the thumprint of the X509 certificate in hex format.
90
+ * Get the thumbprint of the X509 certificate in hex format.
91
91
  */
92
- getThumprintInHex(agentContext: AgentContext): Promise<string>;
92
+ getThumbprintInHex(agentContext: AgentContext): Promise<string>;
93
93
  /**
94
94
  * Get the data elements of the x509 certificate
95
95
  */
@@ -1 +1 @@
1
- {"version":3,"file":"X509Certificate.d.mts","names":[],"sources":["../../../src/modules/x509/X509Certificate.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;aA+BY,YAAA;;;;;;;EAAA,OAAA,GAAA,EAAA;EAYA,YAAA,GAAA,GAAA;EAUA,YAAA,GAAA,GAAA;;AAEG,aAZH,oBAAA;EAaO,UAAK,GAAA,mBAAA;EAAe,UAAA,GAAA,mBAAA;EAG1B,WAAA,GAAA,mBAAe;EACR,eAAA,GAAA,mBAAA;EACE,YAAA,GAAA,mBAAA;EAqB6B,WAAA,GAAA,mBAAA;EAAgB,KAAA,GAAA,iBAAA;;AA2BxC,KAxDf,sBAAA,GAwDe;EAAA,SAAA,EAvDd,SAuDc;eAtDZ;mBACI,IAAA,CAAK;CA4GH;AAwBgB,cAjIxB,eAAA,CAiIwB;EAYC,SAAA,EA5IlB,SA4IkB;EAAyC,UAAA,CAAA,EA3IzD,aA2IyD;EAAc,QAAA,eAAA;EAAA,QAAA,WAAA,CAAA;EA6FvF,IAAA,KAAA,CAAA,KAAA,EAAA,MAAA;EACA,IAAA,KAAA,CAAA,CAAA,EAAA,MAAA;EACA,IAAA,QAAA,CAAA,CAAA,EAAA,OAAA;EAEkB,OAAA,kBAAA,CAAA,cAAA,EAvN2B,aAuN3B,CAAA,EAvN2C,eAuN3C;EACN,OAAA,sBAAA,CAAA,kBAAA,EAAA,MAAA,CAAA,EAnNkD,eAmNlD;EAcH,eAAA,gBAAA;EAAc,QAAA,qBAAA;EAiCkB,IAAA,cAAA,CAAA,CAAA,EA5OpB,UA4OoB,CA5OpB,WA4OoB,CAAA;EAAY,IAAA,uBAAA,CAAA,CAAA,EAAA;;;EAkC/B,CAAA,EAAA;EAAe,IAAA,sBAAA,CAAA,CAAA,EAAA;;;;;;;;;;kBAvNtB;0BAwBgB;;yBAYC,yCAAyC,iBAAc,QAAA;;;;;;;;sBAiGrE;gBACN;;;;;;;;;;;;gBAcH,iBAAc;;;;kCAiCkB,eAAY;;;;;;;;;;;;;;;;;;;qBAkC/B"}
1
+ {"version":3,"file":"X509Certificate.d.mts","names":[],"sources":["../../../src/modules/x509/X509Certificate.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;aA+BY,YAAA;;;;;;;EAAA,OAAA,GAAA,EAAA;EAYA,YAAA,GAAA,GAAA;EAUA,YAAA,GAAA,GAAA;;AAEG,aAZH,oBAAA;EAaO,UAAK,GAAA,mBAAA;EAAe,UAAA,GAAA,mBAAA;EAG1B,WAAA,GAAA,mBAAe;EACR,eAAA,GAAA,mBAAA;EACE,YAAA,GAAA,mBAAA;EAqB6B,WAAA,GAAA,mBAAA;EAAgB,KAAA,GAAA,iBAAA;;AA2BxC,KAxDf,sBAAA,GAwDe;EAAA,SAAA,EAvDd,SAuDc;eAtDZ;mBACI,IAAA,CAAK;CA4GH;AAeQ,cAxHhB,eAAA,CAwHgB;EAqBS,SAAA,EA5IlB,SA4IkB;EAAyC,UAAA,CAAA,EA3IzD,aA2IyD;EAAc,QAAA,eAAA;EAAA,QAAA,WAAA,CAAA;EA6FvF,IAAA,KAAA,CAAA,KAAA,EAAA,MAAA;EACA,IAAA,KAAA,CAAA,CAAA,EAAA,MAAA;EACA,IAAA,QAAA,CAAA,CAAA,EAAA,OAAA;EAEkB,OAAA,kBAAA,CAAA,cAAA,EAvN2B,aAuN3B,CAAA,EAvN2C,eAuN3C;EACN,OAAA,sBAAA,CAAA,kBAAA,EAAA,MAAA,CAAA,EAnNkD,eAmNlD;EAcH,eAAA,gBAAA;EAAc,QAAA,qBAAA;EAiCmB,IAAA,cAAA,CAAA,CAAA,EA5OrB,UA4OqB,CA5OrB,WA4OqB,CAAA;EAAY,IAAA,uBAAA,CAAA,CAAA,EAAA;;;EAkChC,CAAA,EAAA;EAAe,IAAA,sBAAA,CAAA,CAAA,EAAA;;;;;;;;;;kBAvNtB;0BAeQ;;yBAqBS,yCAAyC,iBAAc,QAAA;;;;;;;;sBAiGrE;gBACN;;;;;;;;;;;;gBAcH,iBAAc;;;;mCAiCmB,eAAY;;;;;;;;;;;;;;;;;;;qBAkChC"}
@@ -120,7 +120,7 @@ var X509Certificate = class X509Certificate {
120
120
  get extendedKeyUsage() {
121
121
  const extendedKeyUsages = this.getMatchingExtensions(id_ce_extKeyUsage)?.map((e) => e.usages);
122
122
  if (extendedKeyUsages && extendedKeyUsages.length > 1) throw new X509Error("Multiple Key Usages are not allowed");
123
- return extendedKeyUsages?.[0];
123
+ return extendedKeyUsages?.[0] ?? [];
124
124
  }
125
125
  isExtensionCritical(id) {
126
126
  const extension = this.getMatchingExtensions(id);
@@ -195,9 +195,9 @@ var X509Certificate = class X509Certificate {
195
195
  if (!isNotAfterValid) throw new X509Error(`Certificate: '${this.x509Certificate.subject}' used after it is allowed`);
196
196
  }
197
197
  /**
198
- * Get the thumprint of the X509 certificate in hex format.
198
+ * Get the thumbprint of the X509 certificate in hex format.
199
199
  */
200
- async getThumprintInHex(agentContext) {
200
+ async getThumbprintInHex(agentContext) {
201
201
  const thumbprint = await this.x509Certificate.getThumbprint(new CredoWebCrypto(agentContext));
202
202
  return TypedArrayEncoder.toHex(new Uint8Array(thumbprint));
203
203
  }
@@ -1 +1 @@
1
- {"version":3,"file":"X509Certificate.mjs","names":["extensions: Array<x509.Extension | undefined>","certificate","certificateInstance","publicCryptoKey: CredoWebCryptoKey | undefined"],"sources":["../../../src/modules/x509/X509Certificate.ts"],"sourcesContent":["import { AsnParser } from '@peculiar/asn1-schema'\nimport {\n id_ce_authorityKeyIdentifier,\n id_ce_extKeyUsage,\n id_ce_issuerAltName,\n id_ce_keyUsage,\n id_ce_subjectAltName,\n id_ce_subjectKeyIdentifier,\n SubjectPublicKeyInfo,\n} from '@peculiar/asn1-x509'\nimport * as x509 from '@peculiar/x509'\nimport type { AgentContext } from '../../agent'\nimport { CredoWebCrypto, CredoWebCryptoKey } from '../../crypto/webcrypto'\nimport { publicJwkToCryptoKeyAlgorithm, spkiToPublicJwk } from '../../crypto/webcrypto/utils'\nimport type { AnyUint8Array } from '../../types'\nimport { TypedArrayEncoder } from '../../utils'\nimport { asymmetricPublicJwkMatches, PublicJwk } from '../kms'\nimport {\n convertName,\n createAuthorityKeyIdentifierExtension,\n createBasicConstraintsExtension,\n createCrlDistributionPointsExtension,\n createExtendedKeyUsagesExtension,\n createIssuerAlternativeNameExtension,\n createKeyUsagesExtension,\n createSubjectAlternativeNameExtension,\n createSubjectKeyIdentifierExtension,\n} from './utils'\nimport { X509Error } from './X509Error'\nimport type { X509CreateCertificateOptions } from './X509ServiceOptions'\n\nexport enum X509KeyUsage {\n DigitalSignature = 1,\n NonRepudiation = 2,\n KeyEncipherment = 4,\n DataEncipherment = 8,\n KeyAgreement = 16,\n KeyCertSign = 32,\n CrlSign = 64,\n EncipherOnly = 128,\n DecipherOnly = 256,\n}\n\nexport enum X509ExtendedKeyUsage {\n ServerAuth = '1.3.6.1.5.5.7.3.1',\n ClientAuth = '1.3.6.1.5.5.7.3.2',\n CodeSigning = '1.3.6.1.5.5.7.3.3',\n EmailProtection = '1.3.6.1.5.5.7.3.4',\n TimeStamping = '1.3.6.1.5.5.7.3.8',\n OcspSigning = '1.3.6.1.5.5.7.3.9',\n MdlDs = '1.0.18013.5.1.2',\n}\n\nexport type X509CertificateOptions = {\n publicJwk: PublicJwk\n privateKey?: AnyUint8Array\n x509Certificate: x509.X509Certificate\n}\n\nexport class X509Certificate {\n public publicJwk: PublicJwk\n public privateKey?: AnyUint8Array\n private x509Certificate: x509.X509Certificate\n\n private constructor(options: X509CertificateOptions) {\n this.publicJwk = options.publicJwk\n this.privateKey = options.privateKey\n this.x509Certificate = options.x509Certificate\n }\n\n public set keyId(keyId: string) {\n this.publicJwk.keyId = keyId\n }\n\n public get keyId(): string {\n return this.publicJwk.keyId\n }\n\n public get hasKeyId(): boolean {\n return this.publicJwk.hasKeyId\n }\n\n public static fromRawCertificate(rawCertificate: AnyUint8Array): X509Certificate {\n const certificate = new x509.X509Certificate(rawCertificate)\n return X509Certificate.parseCertificate(certificate)\n }\n\n public static fromEncodedCertificate(encodedCertificate: string): X509Certificate {\n const certificate = new x509.X509Certificate(encodedCertificate)\n return X509Certificate.parseCertificate(certificate)\n }\n\n private static parseCertificate(certificate: x509.X509Certificate): X509Certificate {\n const spki = AsnParser.parse(certificate.publicKey.rawData, SubjectPublicKeyInfo)\n const privateKey = certificate.privateKey ? new Uint8Array(certificate.privateKey.rawData) : undefined\n\n const publicJwk = spkiToPublicJwk(spki)\n\n return new X509Certificate({\n publicJwk,\n privateKey,\n x509Certificate: certificate,\n })\n }\n\n private getMatchingExtensions<T = { critical: boolean }>(objectIdentifier: string): Array<T> | undefined {\n return this.x509Certificate.extensions.filter((e) => e.type === objectIdentifier) as Array<T> | undefined\n }\n\n public get rawCertificate() {\n return new Uint8Array(this.x509Certificate.rawData)\n }\n\n public get subjectAlternativeNames() {\n const san = this.getMatchingExtensions<x509.SubjectAlternativeNameExtension>(id_ce_subjectAltName)\n return san?.flatMap((s) => s.names.items).map((i) => ({ type: i.type, value: i.value })) ?? []\n }\n\n public get issuerAlternativeNames() {\n const ian = this.getMatchingExtensions<x509.IssuerAlternativeNameExtension>(id_ce_issuerAltName)\n return ian?.flatMap((i) => i.names.items).map((i) => ({ type: i.type, value: i.value })) ?? []\n }\n\n public get sanDnsNames() {\n return this.subjectAlternativeNames.filter((san) => san.type === 'dns').map((san) => san.value)\n }\n\n public get sanUriNames() {\n return this.subjectAlternativeNames.filter((ian) => ian.type === 'url').map((ian) => ian.value)\n }\n\n public get ianDnsNames() {\n return this.issuerAlternativeNames.filter((san) => san.type === 'dns').map((san) => san.value)\n }\n\n public get ianUriNames() {\n return this.issuerAlternativeNames.filter((ian) => ian.type === 'url').map((ian) => ian.value)\n }\n\n public get authorityKeyIdentifier() {\n const keyIds = this.getMatchingExtensions<x509.AuthorityKeyIdentifierExtension>(id_ce_authorityKeyIdentifier)?.map(\n (e) => e.keyId\n )\n\n if (keyIds && keyIds.length > 1) {\n throw new X509Error('Multiple Authority Key Identifiers are not allowed')\n }\n\n return keyIds?.[0]\n }\n\n public get subjectKeyIdentifier() {\n const keyIds = this.getMatchingExtensions<x509.SubjectKeyIdentifierExtension>(id_ce_subjectKeyIdentifier)?.map(\n (e) => e.keyId\n )\n\n if (keyIds && keyIds.length > 1) {\n throw new X509Error('Multiple Subject Key Identifiers are not allowed')\n }\n\n return keyIds?.[0]\n }\n\n // biome-ignore lint/suspicious/useGetterReturn: no explanation\n public get keyUsage() {\n const keyUsages = this.getMatchingExtensions<x509.KeyUsagesExtension>(id_ce_keyUsage)?.map((e) => e.usages)\n\n if (keyUsages && keyUsages.length > 1) {\n throw new X509Error('Multiple Key Usages are not allowed')\n }\n\n if (keyUsages) {\n return Object.values(X509KeyUsage)\n .filter((key): key is number => typeof key === 'number')\n .filter((flagValue) => (keyUsages[0] & flagValue) === flagValue)\n .map((flagValue) => flagValue as X509KeyUsage)\n }\n }\n\n public get extendedKeyUsage() {\n const extendedKeyUsages = this.getMatchingExtensions<x509.ExtendedKeyUsageExtension>(id_ce_extKeyUsage)?.map(\n (e) => e.usages\n )\n\n if (extendedKeyUsages && extendedKeyUsages.length > 1) {\n throw new X509Error('Multiple Key Usages are not allowed')\n }\n\n return extendedKeyUsages?.[0] as X509ExtendedKeyUsage | undefined\n }\n\n public isExtensionCritical(id: string): boolean {\n const extension = this.getMatchingExtensions(id)\n if (!extension) {\n throw new X509Error(`extension with id '${id}' is not found`)\n }\n\n return !!extension[0].critical\n }\n\n public static async create(options: X509CreateCertificateOptions, webCrypto: CredoWebCrypto) {\n const subjectPublicKey = options.subjectPublicKey ?? options.authorityKey\n const isSelfSignedCertificate = asymmetricPublicJwkMatches(options.authorityKey.toJson(), subjectPublicKey.toJson())\n\n const signingKey = new CredoWebCryptoKey(\n options.authorityKey,\n publicJwkToCryptoKeyAlgorithm(options.authorityKey),\n false,\n 'private',\n ['sign']\n )\n const publicKey = new CredoWebCryptoKey(\n subjectPublicKey,\n publicJwkToCryptoKeyAlgorithm(options.authorityKey),\n true,\n 'public',\n ['verify']\n )\n\n const issuerName = convertName(options.issuer)\n\n const extensions: Array<x509.Extension | undefined> = []\n extensions.push(\n createSubjectKeyIdentifierExtension(options.extensions?.subjectKeyIdentifier, { publicJwk: subjectPublicKey })\n )\n extensions.push(createKeyUsagesExtension(options.extensions?.keyUsage))\n extensions.push(createExtendedKeyUsagesExtension(options.extensions?.extendedKeyUsage))\n extensions.push(\n createAuthorityKeyIdentifierExtension(options.extensions?.authorityKeyIdentifier, {\n publicJwk: options.authorityKey,\n })\n )\n extensions.push(createIssuerAlternativeNameExtension(options.extensions?.issuerAlternativeName))\n extensions.push(createSubjectAlternativeNameExtension(options.extensions?.subjectAlternativeName))\n extensions.push(createBasicConstraintsExtension(options.extensions?.basicConstraints))\n extensions.push(createCrlDistributionPointsExtension(options.extensions?.crlDistributionPoints))\n\n if (isSelfSignedCertificate) {\n if (options.subject) {\n throw new X509Error('Do not provide a subject name when the certificate is supposed to be self signed')\n }\n\n const certificate = await x509.X509CertificateGenerator.createSelfSigned(\n {\n keys: { publicKey, privateKey: signingKey },\n name: issuerName,\n notBefore: options.validity?.notBefore,\n notAfter: options.validity?.notAfter,\n extensions: extensions.filter((e) => e !== undefined),\n serialNumber: options.serialNumber,\n },\n webCrypto\n )\n\n const certificateInstance = X509Certificate.parseCertificate(certificate)\n if (subjectPublicKey.hasKeyId) certificateInstance.publicJwk.keyId = subjectPublicKey.keyId\n return certificateInstance\n }\n\n if (!options.subject) {\n throw new X509Error('Provide a subject name when the certificate is not supposed to be self signed')\n }\n\n const subjectName = convertName(options.subject)\n\n const certificate = await x509.X509CertificateGenerator.create(\n {\n signingKey,\n publicKey,\n issuer: issuerName,\n subject: subjectName,\n notBefore: options.validity?.notBefore,\n notAfter: options.validity?.notAfter,\n extensions: extensions.filter((e) => e !== undefined),\n },\n webCrypto\n )\n\n const certificateInstance = X509Certificate.parseCertificate(certificate)\n if (subjectPublicKey.hasKeyId) certificateInstance.publicJwk.keyId = subjectPublicKey.keyId\n return certificateInstance\n }\n\n public get subject() {\n return this.x509Certificate.subject\n }\n\n public get issuer() {\n return this.x509Certificate.issuer\n }\n\n public async verify(\n {\n verificationDate = new Date(),\n publicJwk,\n skipSignatureVerification = false,\n }: {\n verificationDate: Date\n publicJwk?: PublicJwk\n\n /**\n * Whether to skip the verification of the signature and only perform other checks (such\n * as whether the certificate is not expired).\n *\n * This can be useful when an non-self-signed certificate is directly trusted, and it may\n * not be possible to verify the certifcate as the root/intermediate certificate containing\n * the key of the signer/intermediate is not present.\n *\n * @default false\n */\n skipSignatureVerification?: boolean\n },\n webCrypto: CredoWebCrypto\n ) {\n let publicCryptoKey: CredoWebCryptoKey | undefined\n if (publicJwk) {\n const cryptoKeyAlgorithm = publicJwkToCryptoKeyAlgorithm(publicJwk)\n publicCryptoKey = new CredoWebCryptoKey(publicJwk, cryptoKeyAlgorithm, true, 'public', ['verify'])\n }\n\n // We use the library to validate the signature, but the date is manually verified\n const isSignatureValid = skipSignatureVerification\n ? true\n : await this.x509Certificate.verify({ signatureOnly: true, publicKey: publicCryptoKey }, webCrypto)\n const time = verificationDate.getTime()\n\n const isNotBeforeValid = this.x509Certificate.notBefore.getTime() <= time\n const isNotAfterValid = time <= this.x509Certificate.notAfter.getTime()\n\n if (!isSignatureValid) {\n throw new X509Error(`Certificate: '${this.x509Certificate.subject}' has an invalid signature`)\n }\n\n if (!isNotBeforeValid) {\n throw new X509Error(`Certificate: '${this.x509Certificate.subject}' used before it is allowed`)\n }\n\n if (!isNotAfterValid) {\n throw new X509Error(`Certificate: '${this.x509Certificate.subject}' used after it is allowed`)\n }\n }\n\n /**\n * Get the thumprint of the X509 certificate in hex format.\n */\n public async getThumprintInHex(agentContext: AgentContext) {\n const thumbprint = await this.x509Certificate.getThumbprint(new CredoWebCrypto(agentContext))\n const thumbprintHex = TypedArrayEncoder.toHex(new Uint8Array(thumbprint))\n\n return thumbprintHex\n }\n\n /**\n * Get the data elements of the x509 certificate\n */\n public get data() {\n return {\n issuerName: this.x509Certificate.issuerName.toString(),\n issuer: this.x509Certificate.issuer,\n subjectName: this.x509Certificate.subjectName.toString(),\n subject: this.x509Certificate.subject,\n serialNumber: this.x509Certificate.serialNumber,\n pem: this.x509Certificate.toString(),\n notBefore: this.x509Certificate.notBefore,\n notAfter: this.x509Certificate.notAfter,\n }\n }\n\n public getIssuerNameField(field: string) {\n return this.x509Certificate.issuerName.getField(field)\n }\n\n /**\n * @param format the format to export to, defaults to `pem`\n */\n public toString(format?: 'asn' | 'pem' | 'hex' | 'base64' | 'text' | 'base64url') {\n return this.x509Certificate.toString(format ?? 'pem')\n }\n\n public equal(certificate: X509Certificate) {\n const parsedOther = new x509.X509Certificate(certificate.rawCertificate)\n\n return this.x509Certificate.equal(parsedOther)\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"X509Certificate.mjs","names":["extensions: Array<x509.Extension | undefined>","certificate","certificateInstance","publicCryptoKey: CredoWebCryptoKey | undefined"],"sources":["../../../src/modules/x509/X509Certificate.ts"],"sourcesContent":["import { AsnParser } from '@peculiar/asn1-schema'\nimport {\n id_ce_authorityKeyIdentifier,\n id_ce_extKeyUsage,\n id_ce_issuerAltName,\n id_ce_keyUsage,\n id_ce_subjectAltName,\n id_ce_subjectKeyIdentifier,\n SubjectPublicKeyInfo,\n} from '@peculiar/asn1-x509'\nimport * as x509 from '@peculiar/x509'\nimport type { AgentContext } from '../../agent'\nimport { CredoWebCrypto, CredoWebCryptoKey } from '../../crypto/webcrypto'\nimport { publicJwkToCryptoKeyAlgorithm, spkiToPublicJwk } from '../../crypto/webcrypto/utils'\nimport type { AnyUint8Array } from '../../types'\nimport { TypedArrayEncoder } from '../../utils'\nimport { asymmetricPublicJwkMatches, PublicJwk } from '../kms'\nimport {\n convertName,\n createAuthorityKeyIdentifierExtension,\n createBasicConstraintsExtension,\n createCrlDistributionPointsExtension,\n createExtendedKeyUsagesExtension,\n createIssuerAlternativeNameExtension,\n createKeyUsagesExtension,\n createSubjectAlternativeNameExtension,\n createSubjectKeyIdentifierExtension,\n} from './utils'\nimport { X509Error } from './X509Error'\nimport type { X509CreateCertificateOptions } from './X509ServiceOptions'\n\nexport enum X509KeyUsage {\n DigitalSignature = 1,\n NonRepudiation = 2,\n KeyEncipherment = 4,\n DataEncipherment = 8,\n KeyAgreement = 16,\n KeyCertSign = 32,\n CrlSign = 64,\n EncipherOnly = 128,\n DecipherOnly = 256,\n}\n\nexport enum X509ExtendedKeyUsage {\n ServerAuth = '1.3.6.1.5.5.7.3.1',\n ClientAuth = '1.3.6.1.5.5.7.3.2',\n CodeSigning = '1.3.6.1.5.5.7.3.3',\n EmailProtection = '1.3.6.1.5.5.7.3.4',\n TimeStamping = '1.3.6.1.5.5.7.3.8',\n OcspSigning = '1.3.6.1.5.5.7.3.9',\n MdlDs = '1.0.18013.5.1.2',\n}\n\nexport type X509CertificateOptions = {\n publicJwk: PublicJwk\n privateKey?: AnyUint8Array\n x509Certificate: x509.X509Certificate\n}\n\nexport class X509Certificate {\n public publicJwk: PublicJwk\n public privateKey?: AnyUint8Array\n private x509Certificate: x509.X509Certificate\n\n private constructor(options: X509CertificateOptions) {\n this.publicJwk = options.publicJwk\n this.privateKey = options.privateKey\n this.x509Certificate = options.x509Certificate\n }\n\n public set keyId(keyId: string) {\n this.publicJwk.keyId = keyId\n }\n\n public get keyId(): string {\n return this.publicJwk.keyId\n }\n\n public get hasKeyId(): boolean {\n return this.publicJwk.hasKeyId\n }\n\n public static fromRawCertificate(rawCertificate: AnyUint8Array): X509Certificate {\n const certificate = new x509.X509Certificate(rawCertificate)\n return X509Certificate.parseCertificate(certificate)\n }\n\n public static fromEncodedCertificate(encodedCertificate: string): X509Certificate {\n const certificate = new x509.X509Certificate(encodedCertificate)\n return X509Certificate.parseCertificate(certificate)\n }\n\n private static parseCertificate(certificate: x509.X509Certificate): X509Certificate {\n const spki = AsnParser.parse(certificate.publicKey.rawData, SubjectPublicKeyInfo)\n const privateKey = certificate.privateKey ? new Uint8Array(certificate.privateKey.rawData) : undefined\n\n const publicJwk = spkiToPublicJwk(spki)\n\n return new X509Certificate({\n publicJwk,\n privateKey,\n x509Certificate: certificate,\n })\n }\n\n private getMatchingExtensions<T = { critical: boolean }>(objectIdentifier: string): Array<T> | undefined {\n return this.x509Certificate.extensions.filter((e) => e.type === objectIdentifier) as Array<T> | undefined\n }\n\n public get rawCertificate() {\n return new Uint8Array(this.x509Certificate.rawData)\n }\n\n public get subjectAlternativeNames() {\n const san = this.getMatchingExtensions<x509.SubjectAlternativeNameExtension>(id_ce_subjectAltName)\n return san?.flatMap((s) => s.names.items).map((i) => ({ type: i.type, value: i.value })) ?? []\n }\n\n public get issuerAlternativeNames() {\n const ian = this.getMatchingExtensions<x509.IssuerAlternativeNameExtension>(id_ce_issuerAltName)\n return ian?.flatMap((i) => i.names.items).map((i) => ({ type: i.type, value: i.value })) ?? []\n }\n\n public get sanDnsNames() {\n return this.subjectAlternativeNames.filter((san) => san.type === 'dns').map((san) => san.value)\n }\n\n public get sanUriNames() {\n return this.subjectAlternativeNames.filter((ian) => ian.type === 'url').map((ian) => ian.value)\n }\n\n public get ianDnsNames() {\n return this.issuerAlternativeNames.filter((san) => san.type === 'dns').map((san) => san.value)\n }\n\n public get ianUriNames() {\n return this.issuerAlternativeNames.filter((ian) => ian.type === 'url').map((ian) => ian.value)\n }\n\n public get authorityKeyIdentifier() {\n const keyIds = this.getMatchingExtensions<x509.AuthorityKeyIdentifierExtension>(id_ce_authorityKeyIdentifier)?.map(\n (e) => e.keyId\n )\n\n if (keyIds && keyIds.length > 1) {\n throw new X509Error('Multiple Authority Key Identifiers are not allowed')\n }\n\n return keyIds?.[0]\n }\n\n public get subjectKeyIdentifier() {\n const keyIds = this.getMatchingExtensions<x509.SubjectKeyIdentifierExtension>(id_ce_subjectKeyIdentifier)?.map(\n (e) => e.keyId\n )\n\n if (keyIds && keyIds.length > 1) {\n throw new X509Error('Multiple Subject Key Identifiers are not allowed')\n }\n\n return keyIds?.[0]\n }\n\n // biome-ignore lint/suspicious/useGetterReturn: no explanation\n public get keyUsage() {\n const keyUsages = this.getMatchingExtensions<x509.KeyUsagesExtension>(id_ce_keyUsage)?.map((e) => e.usages)\n\n if (keyUsages && keyUsages.length > 1) {\n throw new X509Error('Multiple Key Usages are not allowed')\n }\n\n if (keyUsages) {\n return Object.values(X509KeyUsage)\n .filter((key): key is number => typeof key === 'number')\n .filter((flagValue) => (keyUsages[0] & flagValue) === flagValue)\n .map((flagValue) => flagValue as X509KeyUsage)\n }\n }\n\n public get extendedKeyUsage() {\n const extendedKeyUsages = this.getMatchingExtensions<x509.ExtendedKeyUsageExtension>(id_ce_extKeyUsage)?.map(\n (e) => e.usages\n )\n\n if (extendedKeyUsages && extendedKeyUsages.length > 1) {\n throw new X509Error('Multiple Key Usages are not allowed')\n }\n\n return (extendedKeyUsages?.[0] as Array<X509ExtendedKeyUsage> | undefined) ?? []\n }\n\n public isExtensionCritical(id: string): boolean {\n const extension = this.getMatchingExtensions(id)\n if (!extension) {\n throw new X509Error(`extension with id '${id}' is not found`)\n }\n\n return !!extension[0].critical\n }\n\n public static async create(options: X509CreateCertificateOptions, webCrypto: CredoWebCrypto) {\n const subjectPublicKey = options.subjectPublicKey ?? options.authorityKey\n const isSelfSignedCertificate = asymmetricPublicJwkMatches(options.authorityKey.toJson(), subjectPublicKey.toJson())\n\n const signingKey = new CredoWebCryptoKey(\n options.authorityKey,\n publicJwkToCryptoKeyAlgorithm(options.authorityKey),\n false,\n 'private',\n ['sign']\n )\n const publicKey = new CredoWebCryptoKey(\n subjectPublicKey,\n publicJwkToCryptoKeyAlgorithm(options.authorityKey),\n true,\n 'public',\n ['verify']\n )\n\n const issuerName = convertName(options.issuer)\n\n const extensions: Array<x509.Extension | undefined> = []\n extensions.push(\n createSubjectKeyIdentifierExtension(options.extensions?.subjectKeyIdentifier, { publicJwk: subjectPublicKey })\n )\n extensions.push(createKeyUsagesExtension(options.extensions?.keyUsage))\n extensions.push(createExtendedKeyUsagesExtension(options.extensions?.extendedKeyUsage))\n extensions.push(\n createAuthorityKeyIdentifierExtension(options.extensions?.authorityKeyIdentifier, {\n publicJwk: options.authorityKey,\n })\n )\n extensions.push(createIssuerAlternativeNameExtension(options.extensions?.issuerAlternativeName))\n extensions.push(createSubjectAlternativeNameExtension(options.extensions?.subjectAlternativeName))\n extensions.push(createBasicConstraintsExtension(options.extensions?.basicConstraints))\n extensions.push(createCrlDistributionPointsExtension(options.extensions?.crlDistributionPoints))\n\n if (isSelfSignedCertificate) {\n if (options.subject) {\n throw new X509Error('Do not provide a subject name when the certificate is supposed to be self signed')\n }\n\n const certificate = await x509.X509CertificateGenerator.createSelfSigned(\n {\n keys: { publicKey, privateKey: signingKey },\n name: issuerName,\n notBefore: options.validity?.notBefore,\n notAfter: options.validity?.notAfter,\n extensions: extensions.filter((e) => e !== undefined),\n serialNumber: options.serialNumber,\n },\n webCrypto\n )\n\n const certificateInstance = X509Certificate.parseCertificate(certificate)\n if (subjectPublicKey.hasKeyId) certificateInstance.publicJwk.keyId = subjectPublicKey.keyId\n return certificateInstance\n }\n\n if (!options.subject) {\n throw new X509Error('Provide a subject name when the certificate is not supposed to be self signed')\n }\n\n const subjectName = convertName(options.subject)\n\n const certificate = await x509.X509CertificateGenerator.create(\n {\n signingKey,\n publicKey,\n issuer: issuerName,\n subject: subjectName,\n notBefore: options.validity?.notBefore,\n notAfter: options.validity?.notAfter,\n extensions: extensions.filter((e) => e !== undefined),\n },\n webCrypto\n )\n\n const certificateInstance = X509Certificate.parseCertificate(certificate)\n if (subjectPublicKey.hasKeyId) certificateInstance.publicJwk.keyId = subjectPublicKey.keyId\n return certificateInstance\n }\n\n public get subject() {\n return this.x509Certificate.subject\n }\n\n public get issuer() {\n return this.x509Certificate.issuer\n }\n\n public async verify(\n {\n verificationDate = new Date(),\n publicJwk,\n skipSignatureVerification = false,\n }: {\n verificationDate: Date\n publicJwk?: PublicJwk\n\n /**\n * Whether to skip the verification of the signature and only perform other checks (such\n * as whether the certificate is not expired).\n *\n * This can be useful when an non-self-signed certificate is directly trusted, and it may\n * not be possible to verify the certificate as the root/intermediate certificate containing\n * the key of the signer/intermediate is not present.\n *\n * @default false\n */\n skipSignatureVerification?: boolean\n },\n webCrypto: CredoWebCrypto\n ) {\n let publicCryptoKey: CredoWebCryptoKey | undefined\n if (publicJwk) {\n const cryptoKeyAlgorithm = publicJwkToCryptoKeyAlgorithm(publicJwk)\n publicCryptoKey = new CredoWebCryptoKey(publicJwk, cryptoKeyAlgorithm, true, 'public', ['verify'])\n }\n\n // We use the library to validate the signature, but the date is manually verified\n const isSignatureValid = skipSignatureVerification\n ? true\n : await this.x509Certificate.verify({ signatureOnly: true, publicKey: publicCryptoKey }, webCrypto)\n const time = verificationDate.getTime()\n\n const isNotBeforeValid = this.x509Certificate.notBefore.getTime() <= time\n const isNotAfterValid = time <= this.x509Certificate.notAfter.getTime()\n\n if (!isSignatureValid) {\n throw new X509Error(`Certificate: '${this.x509Certificate.subject}' has an invalid signature`)\n }\n\n if (!isNotBeforeValid) {\n throw new X509Error(`Certificate: '${this.x509Certificate.subject}' used before it is allowed`)\n }\n\n if (!isNotAfterValid) {\n throw new X509Error(`Certificate: '${this.x509Certificate.subject}' used after it is allowed`)\n }\n }\n\n /**\n * Get the thumbprint of the X509 certificate in hex format.\n */\n public async getThumbprintInHex(agentContext: AgentContext) {\n const thumbprint = await this.x509Certificate.getThumbprint(new CredoWebCrypto(agentContext))\n const thumbprintHex = TypedArrayEncoder.toHex(new Uint8Array(thumbprint))\n\n return thumbprintHex\n }\n\n /**\n * Get the data elements of the x509 certificate\n */\n public get data() {\n return {\n issuerName: this.x509Certificate.issuerName.toString(),\n issuer: this.x509Certificate.issuer,\n subjectName: this.x509Certificate.subjectName.toString(),\n subject: this.x509Certificate.subject,\n serialNumber: this.x509Certificate.serialNumber,\n pem: this.x509Certificate.toString(),\n notBefore: this.x509Certificate.notBefore,\n notAfter: this.x509Certificate.notAfter,\n }\n }\n\n public getIssuerNameField(field: string) {\n return this.x509Certificate.issuerName.getField(field)\n }\n\n /**\n * @param format the format to export to, defaults to `pem`\n */\n public toString(format?: 'asn' | 'pem' | 'hex' | 'base64' | 'text' | 'base64url') {\n return this.x509Certificate.toString(format ?? 'pem')\n }\n\n public equal(certificate: X509Certificate) {\n const parsedOther = new x509.X509Certificate(certificate.rawCertificate)\n\n return this.x509Certificate.equal(parsedOther)\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AA+BA,IAAY,wDAAL;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAGF,IAAY,wEAAL;AACL;AACA;AACA;AACA;AACA;AACA;AACA;;;AASF,IAAa,kBAAb,MAAa,gBAAgB;CAK3B,AAAQ,YAAY,SAAiC;AACnD,OAAK,YAAY,QAAQ;AACzB,OAAK,aAAa,QAAQ;AAC1B,OAAK,kBAAkB,QAAQ;;CAGjC,IAAW,MAAM,OAAe;AAC9B,OAAK,UAAU,QAAQ;;CAGzB,IAAW,QAAgB;AACzB,SAAO,KAAK,UAAU;;CAGxB,IAAW,WAAoB;AAC7B,SAAO,KAAK,UAAU;;CAGxB,OAAc,mBAAmB,gBAAgD;EAC/E,MAAM,cAAc,IAAI,KAAK,gBAAgB,eAAe;AAC5D,SAAO,gBAAgB,iBAAiB,YAAY;;CAGtD,OAAc,uBAAuB,oBAA6C;EAChF,MAAM,cAAc,IAAI,KAAK,gBAAgB,mBAAmB;AAChE,SAAO,gBAAgB,iBAAiB,YAAY;;CAGtD,OAAe,iBAAiB,aAAoD;EAClF,MAAM,OAAO,UAAU,MAAM,YAAY,UAAU,SAAS,qBAAqB;EACjF,MAAM,aAAa,YAAY,aAAa,IAAI,WAAW,YAAY,WAAW,QAAQ,GAAG;AAI7F,SAAO,IAAI,gBAAgB;GACzB,WAHgB,gBAAgB,KAAK;GAIrC;GACA,iBAAiB;GAClB,CAAC;;CAGJ,AAAQ,sBAAiD,kBAAgD;AACvG,SAAO,KAAK,gBAAgB,WAAW,QAAQ,MAAM,EAAE,SAAS,iBAAiB;;CAGnF,IAAW,iBAAiB;AAC1B,SAAO,IAAI,WAAW,KAAK,gBAAgB,QAAQ;;CAGrD,IAAW,0BAA0B;AAEnC,SADY,KAAK,sBAA4D,qBAAqB,EACtF,SAAS,MAAM,EAAE,MAAM,MAAM,CAAC,KAAK,OAAO;GAAE,MAAM,EAAE;GAAM,OAAO,EAAE;GAAO,EAAE,IAAI,EAAE;;CAGhG,IAAW,yBAAyB;AAElC,SADY,KAAK,sBAA2D,oBAAoB,EACpF,SAAS,MAAM,EAAE,MAAM,MAAM,CAAC,KAAK,OAAO;GAAE,MAAM,EAAE;GAAM,OAAO,EAAE;GAAO,EAAE,IAAI,EAAE;;CAGhG,IAAW,cAAc;AACvB,SAAO,KAAK,wBAAwB,QAAQ,QAAQ,IAAI,SAAS,MAAM,CAAC,KAAK,QAAQ,IAAI,MAAM;;CAGjG,IAAW,cAAc;AACvB,SAAO,KAAK,wBAAwB,QAAQ,QAAQ,IAAI,SAAS,MAAM,CAAC,KAAK,QAAQ,IAAI,MAAM;;CAGjG,IAAW,cAAc;AACvB,SAAO,KAAK,uBAAuB,QAAQ,QAAQ,IAAI,SAAS,MAAM,CAAC,KAAK,QAAQ,IAAI,MAAM;;CAGhG,IAAW,cAAc;AACvB,SAAO,KAAK,uBAAuB,QAAQ,QAAQ,IAAI,SAAS,MAAM,CAAC,KAAK,QAAQ,IAAI,MAAM;;CAGhG,IAAW,yBAAyB;EAClC,MAAM,SAAS,KAAK,sBAA4D,6BAA6B,EAAE,KAC5G,MAAM,EAAE,MACV;AAED,MAAI,UAAU,OAAO,SAAS,EAC5B,OAAM,IAAI,UAAU,qDAAqD;AAG3E,SAAO,SAAS;;CAGlB,IAAW,uBAAuB;EAChC,MAAM,SAAS,KAAK,sBAA0D,2BAA2B,EAAE,KACxG,MAAM,EAAE,MACV;AAED,MAAI,UAAU,OAAO,SAAS,EAC5B,OAAM,IAAI,UAAU,mDAAmD;AAGzE,SAAO,SAAS;;CAIlB,IAAW,WAAW;EACpB,MAAM,YAAY,KAAK,sBAA+C,eAAe,EAAE,KAAK,MAAM,EAAE,OAAO;AAE3G,MAAI,aAAa,UAAU,SAAS,EAClC,OAAM,IAAI,UAAU,sCAAsC;AAG5D,MAAI,UACF,QAAO,OAAO,OAAO,aAAa,CAC/B,QAAQ,QAAuB,OAAO,QAAQ,SAAS,CACvD,QAAQ,eAAe,UAAU,KAAK,eAAe,UAAU,CAC/D,KAAK,cAAc,UAA0B;;CAIpD,IAAW,mBAAmB;EAC5B,MAAM,oBAAoB,KAAK,sBAAsD,kBAAkB,EAAE,KACtG,MAAM,EAAE,OACV;AAED,MAAI,qBAAqB,kBAAkB,SAAS,EAClD,OAAM,IAAI,UAAU,sCAAsC;AAG5D,SAAQ,oBAAoB,MAAkD,EAAE;;CAGlF,AAAO,oBAAoB,IAAqB;EAC9C,MAAM,YAAY,KAAK,sBAAsB,GAAG;AAChD,MAAI,CAAC,UACH,OAAM,IAAI,UAAU,sBAAsB,GAAG,gBAAgB;AAG/D,SAAO,CAAC,CAAC,UAAU,GAAG;;CAGxB,aAAoB,OAAO,SAAuC,WAA2B;EAC3F,MAAM,mBAAmB,QAAQ,oBAAoB,QAAQ;EAC7D,MAAM,0BAA0B,2BAA2B,QAAQ,aAAa,QAAQ,EAAE,iBAAiB,QAAQ,CAAC;EAEpH,MAAM,aAAa,IAAI,kBACrB,QAAQ,cACR,8BAA8B,QAAQ,aAAa,EACnD,OACA,WACA,CAAC,OAAO,CACT;EACD,MAAM,YAAY,IAAI,kBACpB,kBACA,8BAA8B,QAAQ,aAAa,EACnD,MACA,UACA,CAAC,SAAS,CACX;EAED,MAAM,aAAa,YAAY,QAAQ,OAAO;EAE9C,MAAMA,aAAgD,EAAE;AACxD,aAAW,KACT,oCAAoC,QAAQ,YAAY,sBAAsB,EAAE,WAAW,kBAAkB,CAAC,CAC/G;AACD,aAAW,KAAK,yBAAyB,QAAQ,YAAY,SAAS,CAAC;AACvE,aAAW,KAAK,iCAAiC,QAAQ,YAAY,iBAAiB,CAAC;AACvF,aAAW,KACT,sCAAsC,QAAQ,YAAY,wBAAwB,EAChF,WAAW,QAAQ,cACpB,CAAC,CACH;AACD,aAAW,KAAK,qCAAqC,QAAQ,YAAY,sBAAsB,CAAC;AAChG,aAAW,KAAK,sCAAsC,QAAQ,YAAY,uBAAuB,CAAC;AAClG,aAAW,KAAK,gCAAgC,QAAQ,YAAY,iBAAiB,CAAC;AACtF,aAAW,KAAK,qCAAqC,QAAQ,YAAY,sBAAsB,CAAC;AAEhG,MAAI,yBAAyB;AAC3B,OAAI,QAAQ,QACV,OAAM,IAAI,UAAU,mFAAmF;GAGzG,MAAMC,gBAAc,MAAM,KAAK,yBAAyB,iBACtD;IACE,MAAM;KAAE;KAAW,YAAY;KAAY;IAC3C,MAAM;IACN,WAAW,QAAQ,UAAU;IAC7B,UAAU,QAAQ,UAAU;IAC5B,YAAY,WAAW,QAAQ,MAAM,MAAM,OAAU;IACrD,cAAc,QAAQ;IACvB,EACD,UACD;GAED,MAAMC,wBAAsB,gBAAgB,iBAAiBD,cAAY;AACzE,OAAI,iBAAiB,SAAU,uBAAoB,UAAU,QAAQ,iBAAiB;AACtF,UAAOC;;AAGT,MAAI,CAAC,QAAQ,QACX,OAAM,IAAI,UAAU,gFAAgF;EAGtG,MAAM,cAAc,YAAY,QAAQ,QAAQ;EAEhD,MAAM,cAAc,MAAM,KAAK,yBAAyB,OACtD;GACE;GACA;GACA,QAAQ;GACR,SAAS;GACT,WAAW,QAAQ,UAAU;GAC7B,UAAU,QAAQ,UAAU;GAC5B,YAAY,WAAW,QAAQ,MAAM,MAAM,OAAU;GACtD,EACD,UACD;EAED,MAAM,sBAAsB,gBAAgB,iBAAiB,YAAY;AACzE,MAAI,iBAAiB,SAAU,qBAAoB,UAAU,QAAQ,iBAAiB;AACtF,SAAO;;CAGT,IAAW,UAAU;AACnB,SAAO,KAAK,gBAAgB;;CAG9B,IAAW,SAAS;AAClB,SAAO,KAAK,gBAAgB;;CAG9B,MAAa,OACX,EACE,mCAAmB,IAAI,MAAM,EAC7B,WACA,4BAA4B,SAiB9B,WACA;EACA,IAAIC;AACJ,MAAI,UAEF,mBAAkB,IAAI,kBAAkB,WADb,8BAA8B,UAAU,EACI,MAAM,UAAU,CAAC,SAAS,CAAC;EAIpG,MAAM,mBAAmB,4BACrB,OACA,MAAM,KAAK,gBAAgB,OAAO;GAAE,eAAe;GAAM,WAAW;GAAiB,EAAE,UAAU;EACrG,MAAM,OAAO,iBAAiB,SAAS;EAEvC,MAAM,mBAAmB,KAAK,gBAAgB,UAAU,SAAS,IAAI;EACrE,MAAM,kBAAkB,QAAQ,KAAK,gBAAgB,SAAS,SAAS;AAEvE,MAAI,CAAC,iBACH,OAAM,IAAI,UAAU,iBAAiB,KAAK,gBAAgB,QAAQ,4BAA4B;AAGhG,MAAI,CAAC,iBACH,OAAM,IAAI,UAAU,iBAAiB,KAAK,gBAAgB,QAAQ,6BAA6B;AAGjG,MAAI,CAAC,gBACH,OAAM,IAAI,UAAU,iBAAiB,KAAK,gBAAgB,QAAQ,4BAA4B;;;;;CAOlG,MAAa,mBAAmB,cAA4B;EAC1D,MAAM,aAAa,MAAM,KAAK,gBAAgB,cAAc,IAAI,eAAe,aAAa,CAAC;AAG7F,SAFsB,kBAAkB,MAAM,IAAI,WAAW,WAAW,CAAC;;;;;CAQ3E,IAAW,OAAO;AAChB,SAAO;GACL,YAAY,KAAK,gBAAgB,WAAW,UAAU;GACtD,QAAQ,KAAK,gBAAgB;GAC7B,aAAa,KAAK,gBAAgB,YAAY,UAAU;GACxD,SAAS,KAAK,gBAAgB;GAC9B,cAAc,KAAK,gBAAgB;GACnC,KAAK,KAAK,gBAAgB,UAAU;GACpC,WAAW,KAAK,gBAAgB;GAChC,UAAU,KAAK,gBAAgB;GAChC;;CAGH,AAAO,mBAAmB,OAAe;AACvC,SAAO,KAAK,gBAAgB,WAAW,SAAS,MAAM;;;;;CAMxD,AAAO,SAAS,QAAkE;AAChF,SAAO,KAAK,gBAAgB,SAAS,UAAU,MAAM;;CAGvD,AAAO,MAAM,aAA8B;EACzC,MAAM,cAAc,IAAI,KAAK,gBAAgB,YAAY,eAAe;AAExE,SAAO,KAAK,gBAAgB,MAAM,YAAY"}
@@ -1,5 +1,6 @@
1
- import { X509CreateCertificateOptions, X509GetLeafCertificateOptions, X509ParseCertificateOptions, X509ValidateCertificateChainOptions } from "./X509ServiceOptions.mjs";
1
+ import { X509CreateCertificateOptions, X509CreateCertificateSigningRequestOptions, X509GetLeafCertificateOptions, X509ParseCertificateOptions, X509ParseCertificateSigningRequestOptions, X509ValidateCertificateChainOptions } from "./X509ServiceOptions.mjs";
2
2
  import { X509Certificate } from "./X509Certificate.mjs";
3
+ import { CertificateSigningRequest } from "./CertificateSigningRequest.mjs";
3
4
  import { AgentContext } from "../../agent/context/AgentContext.mjs";
4
5
  import "../../agent/index.mjs";
5
6
 
@@ -16,11 +17,11 @@ declare class X509Service {
16
17
  *
17
18
  * The Issuer of the certificate is found with the following algorithm:
18
19
  * - Check if there is an AuthorityKeyIdentifierExtension
19
- * - Go through all the other certificates and see if the SubjectKeyIdentifier is equal to thje AuthorityKeyIdentifier
20
+ * - Go through all the other certificates and see if the SubjectKeyIdentifier is equal to the AuthorityKeyIdentifier
20
21
  * - If they are equal, the certificate is verified and returned as the issuer
21
22
  *
22
23
  * Additional validation:
23
- * - Make sure atleast a single certificate is in the chain
24
+ * - Make sure at least a single certificate is in the chain
24
25
  * - Check whether a certificate in the chain matches with a trusted certificate
25
26
  */
26
27
  static validateCertificateChain(agentContext: AgentContext, {
@@ -41,6 +42,10 @@ declare class X509Service {
41
42
  certificateChain
42
43
  }: X509GetLeafCertificateOptions): X509Certificate;
43
44
  static createCertificate(agentContext: AgentContext, options: X509CreateCertificateOptions): Promise<X509Certificate>;
45
+ static createCertificateSigningRequest(agentContext: AgentContext, options: X509CreateCertificateSigningRequestOptions): Promise<CertificateSigningRequest>;
46
+ static parseCertificateSigningRequest({
47
+ encodedCertificateSigningRequest
48
+ }: X509ParseCertificateSigningRequestOptions): CertificateSigningRequest;
44
49
  }
45
50
  //#endregion
46
51
  export { X509Service };
@@ -1 +1 @@
1
- {"version":3,"file":"X509Service.d.mts","names":[],"sources":["../../../src/modules/x509/X509Service.ts"],"sourcesContent":[],"mappings":";;;;;;cAea,WAAA;;;;;AAFb;;;;;;;;;;;;;;EA4IM,OAAA,wBAAA,CAAA,YAAA,EAtHY,YAsHZ,EAAA;IAAA,gBAAA;IAAA,WAAA;IAAA,gBAAA;IAAA;EAAA,CAAA,EAhHC,mCAgHD,CAAA,EAhHoC,OAgHpC,CAhHoC,eAgHpC,EAAA,CAAA;EAAoB;;;;;EAS+E,OAAA,gBAAA,CAAA,aAAA,EAnBtF,YAmBsF,EAAA;IAAA;EAAA,CAAA,EAlB7E,2BAkB6E,CAAA,EAjBpG,eAiBoG;EAAA,OAAA,kBAAA,CAAA,aAAA,EAVtF,YAUsF,EAAA;IAAA;EAAA,CAAA,EAT/E,6BAS+E,CAAA,EARpG,eAQoG;yCAAnD,uBAAuB,+BAA4B,QAAA"}
1
+ {"version":3,"file":"X509Service.d.mts","names":[],"sources":["../../../src/modules/x509/X509Service.ts"],"sourcesContent":[],"mappings":";;;;;;;cAkBa,WAAA;;;;;AAFb;;;;;;;;;;;;;;EA4IM,OAAA,wBAAA,CAAA,YAAA,EAtHY,YAsHZ,EAAA;IAAA,gBAAA;IAAA,WAAA;IAAA,gBAAA;IAAA;EAAA,CAAA,EAhHC,mCAgHD,CAAA,EAhHoC,OAgHpC,CAhHoC,eAgHpC,EAAA,CAAA;EAAoB;;;;;EAS+E,OAAA,gBAAA,CAAA,aAAA,EAnBtF,YAmBsF,EAAA;IAAA;EAAA,CAAA,EAlB7E,2BAkB6E,CAAA,EAjBpG,eAiBoG;EASvF,OAAA,kBAAA,CAAA,aAAA,EAnBC,YAmBD,EAAA;IAAA;EAAA,CAAA,EAlBQ,6BAkBR,CAAA,EAjBb,eAiBa;EACL,OAAA,iBAAA,CAAA,YAAA,EAVyC,YAUzC,EAAA,OAAA,EAVgE,4BAUhE,CAAA,EAV4F,OAU5F,CAV4F,eAU5F,CAAA;EAA0C,OAAA,+BAAA,CAAA,YAAA,EADrC,YACqC,EAAA,OAAA,EAA1C,0CAA0C,CAAA,EAAA,OAAA,CAAA,yBAAA,CAAA;EAAA,OAAA,8BAAA,CAAA;IAAA;EAAA,CAAA,EAWlD,yCAXkD,CAAA,EAWT,yBAXS"}
@@ -6,6 +6,7 @@ import { CredoWebCrypto } from "../../crypto/webcrypto/CredoWebCrypto.mjs";
6
6
  import "../../crypto/webcrypto/index.mjs";
7
7
  import { X509Error } from "./X509Error.mjs";
8
8
  import { X509Certificate } from "./X509Certificate.mjs";
9
+ import { CertificateSigningRequest } from "./CertificateSigningRequest.mjs";
9
10
  import { injectable } from "tsyringe";
10
11
  import * as x509 from "@peculiar/x509";
11
12
 
@@ -22,11 +23,11 @@ let X509Service = class X509Service$1 {
22
23
  *
23
24
  * The Issuer of the certificate is found with the following algorithm:
24
25
  * - Check if there is an AuthorityKeyIdentifierExtension
25
- * - Go through all the other certificates and see if the SubjectKeyIdentifier is equal to thje AuthorityKeyIdentifier
26
+ * - Go through all the other certificates and see if the SubjectKeyIdentifier is equal to the AuthorityKeyIdentifier
26
27
  * - If they are equal, the certificate is verified and returned as the issuer
27
28
  *
28
29
  * Additional validation:
29
- * - Make sure atleast a single certificate is in the chain
30
+ * - Make sure at least a single certificate is in the chain
30
31
  * - Check whether a certificate in the chain matches with a trusted certificate
31
32
  */
32
33
  static async validateCertificateChain(agentContext, { certificateChain, certificate = certificateChain[0], verificationDate = /* @__PURE__ */ new Date(), trustedCertificates }) {
@@ -81,6 +82,13 @@ let X509Service = class X509Service$1 {
81
82
  const webCrypto = new CredoWebCrypto(agentContext);
82
83
  return await X509Certificate.create(options, webCrypto);
83
84
  }
85
+ static async createCertificateSigningRequest(agentContext, options) {
86
+ const webCrypto = new CredoWebCrypto(agentContext);
87
+ return await CertificateSigningRequest.create(options, webCrypto);
88
+ }
89
+ static parseCertificateSigningRequest({ encodedCertificateSigningRequest }) {
90
+ return CertificateSigningRequest.fromEncodedCertificateRequest(encodedCertificateSigningRequest);
91
+ }
84
92
  };
85
93
  X509Service = __decorate([injectable()], X509Service);
86
94
 
@@ -1 +1 @@
1
- {"version":3,"file":"X509Service.mjs","names":["X509Service","parsedLeafCertificate: x509.X509Certificate","certificatesToBuildChain: x509.X509Certificate[]","previousCertificate: X509Certificate | undefined"],"sources":["../../../src/modules/x509/X509Service.ts"],"sourcesContent":["import * as x509 from '@peculiar/x509'\nimport { injectable } from 'tsyringe'\nimport { AgentContext } from '../../agent'\nimport { CredoWebCrypto } from '../../crypto/webcrypto'\nimport { X509Certificate } from './X509Certificate'\nimport { X509Error } from './X509Error'\nimport type {\n X509CreateCertificateOptions,\n X509GetLeafCertificateOptions,\n X509ParseCertificateOptions,\n X509ValidateCertificateChainOptions,\n} from './X509ServiceOptions'\n\n@injectable()\n// biome-ignore lint/complexity/noStaticOnlyClass: no explanation\nexport class X509Service {\n /**\n *\n * Validate a chain of X.509 certificates according to RFC 5280\n *\n * This function requires a list of base64 encoded certificates and, optionally, a certificate that should be found in the chain.\n * If no certificate is provided, it will just assume the leaf certificate\n *\n * The leaf certificate should be the 0th index and the root the last\n *\n * The Issuer of the certificate is found with the following algorithm:\n * - Check if there is an AuthorityKeyIdentifierExtension\n * - Go through all the other certificates and see if the SubjectKeyIdentifier is equal to thje AuthorityKeyIdentifier\n * - If they are equal, the certificate is verified and returned as the issuer\n *\n * Additional validation:\n * - Make sure atleast a single certificate is in the chain\n * - Check whether a certificate in the chain matches with a trusted certificate\n */\n public static async validateCertificateChain(\n agentContext: AgentContext,\n {\n certificateChain,\n certificate = certificateChain[0],\n verificationDate = new Date(),\n trustedCertificates,\n }: X509ValidateCertificateChainOptions\n ) {\n if (certificateChain.length === 0) throw new X509Error('Certificate chain is empty')\n const webCrypto = new CredoWebCrypto(agentContext)\n\n let parsedLeafCertificate: x509.X509Certificate\n let certificatesToBuildChain: x509.X509Certificate[]\n try {\n parsedLeafCertificate = new x509.X509Certificate(certificate)\n certificatesToBuildChain = [...certificateChain, ...(trustedCertificates ?? [])].map(\n (c) => new x509.X509Certificate(c)\n )\n } catch (error) {\n throw new X509Error('Error during parsing of x509 certificate', { cause: error })\n }\n\n const certificateChainBuilder = new x509.X509ChainBuilder({\n certificates: certificatesToBuildChain,\n })\n\n const chain = await certificateChainBuilder.build(parsedLeafCertificate, webCrypto)\n\n // The chain is reversed here as the `x5c` header (the expected input),\n // has the leaf certificate as the first entry, while the `x509` library expects this as the last\n let parsedChain = chain.map((c) => X509Certificate.fromRawCertificate(new Uint8Array(c.rawData))).reverse()\n\n // We allow longer parsed chain, in case the root cert was not part of the chain, but in the\n // list of trusted certificates\n if (parsedChain.length < certificateChain.length) {\n throw new X509Error('Could not parse the full chain. Likely due to incorrect ordering')\n }\n\n let previousCertificate: X509Certificate | undefined\n\n if (trustedCertificates) {\n const parsedTrustedCertificates = trustedCertificates.map((trustedCertificate) =>\n X509Certificate.fromEncodedCertificate(trustedCertificate)\n )\n\n const trustedCertificateIndex = parsedChain.findIndex((cert) =>\n parsedTrustedCertificates.some((tCert) => cert.equal(tCert))\n )\n\n if (trustedCertificateIndex === -1) {\n throw new X509Error('No trusted certificate was found while validating the X.509 chain')\n }\n\n if (trustedCertificateIndex > 0) {\n // When we trust a certificate other than the first certificate in the provided chain we keep a reference to the\n // previous certificate as we need the key of this certificate to verify the first certificate in the chain as\n // it's not self-sigend.\n previousCertificate = parsedChain[trustedCertificateIndex - 1]\n\n // Pop everything off before the index of the trusted certificate (those are more root) as it is not relevant for validation\n parsedChain = parsedChain.slice(trustedCertificateIndex)\n }\n }\n\n // Verify the certificate with the publicKey of the certificate above\n for (let i = 0; i < parsedChain.length; i++) {\n const cert = parsedChain[i]\n const publicJwk = previousCertificate ? previousCertificate.publicJwk : undefined\n\n // The only scenario where this will trigger is if the trusted certificates and the x509 chain both do not contain the\n // intermediate/root certificate needed. E.g. for ISO 18013-5 mDL the root cert MUST NOT be in the chain. If the signer\n // certificate is then trusted, it will fail, as we can't verify the signer certifciate without having access to the signer\n // key of the root certificate.\n // See also https://github.com/openid/OpenID4VCI/issues/62\n //\n // In this case we could skip the signature verification (not other verifications), as we already trust the signer certificate,\n // but i think the purpose of ISO 18013-5 mDL is that you trust the root certificate. If we can't verify the whole chain e.g.\n // when we receive a credential we have the chance it will fail later on.\n const skipSignatureVerification = i === 0 && trustedCertificates && !publicJwk\n // NOTE: at some point we might want to change this to throw an error instead of skipping the signature verification of the trusted\n // but it would basically prevent mDOCs from unknown issuers to be verified in the wallet. Verifiers should only trust the root certificate\n // anyway.\n // if (i === 0 && trustedCertificates && cert.issuer !== cert.subject && !publicKey) {\n // throw new X509Error(\n // 'Unable to verify the certificate chain. A non-self-signed certificate is the first certificate in the chain, and no parent certificate was found in the trusted certificates, meaning the first certificate in the chain cannot be verified. Ensure the certificate is added '\n // )\n // }\n\n await cert.verify(\n {\n publicJwk,\n verificationDate,\n skipSignatureVerification,\n },\n webCrypto\n )\n previousCertificate = cert\n }\n\n return parsedChain\n }\n\n /**\n *\n * Parses a base64-encoded X.509 certificate into a {@link X509Certificate}\n *\n */\n public static parseCertificate(\n _agentContext: AgentContext,\n { encodedCertificate }: X509ParseCertificateOptions\n ): X509Certificate {\n const certificate = X509Certificate.fromEncodedCertificate(encodedCertificate)\n\n return certificate\n }\n\n public static getLeafCertificate(\n _agentContext: AgentContext,\n { certificateChain }: X509GetLeafCertificateOptions\n ): X509Certificate {\n if (certificateChain.length === 0) throw new X509Error('Certificate chain is empty')\n\n const certificate = X509Certificate.fromEncodedCertificate(certificateChain[0])\n\n return certificate\n }\n\n public static async createCertificate(agentContext: AgentContext, options: X509CreateCertificateOptions) {\n const webCrypto = new CredoWebCrypto(agentContext)\n\n const certificate = await X509Certificate.create(options, webCrypto)\n\n return certificate\n }\n}\n"],"mappings":";;;;;;;;;;;;AAeO,wBAAMA,cAAY;;;;;;;;;;;;;;;;;;;CAmBvB,aAAoB,yBAClB,cACA,EACE,kBACA,cAAc,iBAAiB,IAC/B,mCAAmB,IAAI,MAAM,EAC7B,uBAEF;AACA,MAAI,iBAAiB,WAAW,EAAG,OAAM,IAAI,UAAU,6BAA6B;EACpF,MAAM,YAAY,IAAI,eAAe,aAAa;EAElD,IAAIC;EACJ,IAAIC;AACJ,MAAI;AACF,2BAAwB,IAAI,KAAK,gBAAgB,YAAY;AAC7D,8BAA2B,CAAC,GAAG,kBAAkB,GAAI,uBAAuB,EAAE,CAAE,CAAC,KAC9E,MAAM,IAAI,KAAK,gBAAgB,EAAE,CACnC;WACM,OAAO;AACd,SAAM,IAAI,UAAU,4CAA4C,EAAE,OAAO,OAAO,CAAC;;EAWnF,IAAI,eAJU,MAJkB,IAAI,KAAK,iBAAiB,EACxD,cAAc,0BACf,CAAC,CAE0C,MAAM,uBAAuB,UAAU,EAI3D,KAAK,MAAM,gBAAgB,mBAAmB,IAAI,WAAW,EAAE,QAAQ,CAAC,CAAC,CAAC,SAAS;AAI3G,MAAI,YAAY,SAAS,iBAAiB,OACxC,OAAM,IAAI,UAAU,mEAAmE;EAGzF,IAAIC;AAEJ,MAAI,qBAAqB;GACvB,MAAM,4BAA4B,oBAAoB,KAAK,uBACzD,gBAAgB,uBAAuB,mBAAmB,CAC3D;GAED,MAAM,0BAA0B,YAAY,WAAW,SACrD,0BAA0B,MAAM,UAAU,KAAK,MAAM,MAAM,CAAC,CAC7D;AAED,OAAI,4BAA4B,GAC9B,OAAM,IAAI,UAAU,oEAAoE;AAG1F,OAAI,0BAA0B,GAAG;AAI/B,0BAAsB,YAAY,0BAA0B;AAG5D,kBAAc,YAAY,MAAM,wBAAwB;;;AAK5D,OAAK,IAAI,IAAI,GAAG,IAAI,YAAY,QAAQ,KAAK;GAC3C,MAAM,OAAO,YAAY;GACzB,MAAM,YAAY,sBAAsB,oBAAoB,YAAY;GAWxE,MAAM,4BAA4B,MAAM,KAAK,uBAAuB,CAAC;AAUrE,SAAM,KAAK,OACT;IACE;IACA;IACA;IACD,EACD,UACD;AACD,yBAAsB;;AAGxB,SAAO;;;;;;;CAQT,OAAc,iBACZ,eACA,EAAE,sBACe;AAGjB,SAFoB,gBAAgB,uBAAuB,mBAAmB;;CAKhF,OAAc,mBACZ,eACA,EAAE,oBACe;AACjB,MAAI,iBAAiB,WAAW,EAAG,OAAM,IAAI,UAAU,6BAA6B;AAIpF,SAFoB,gBAAgB,uBAAuB,iBAAiB,GAAG;;CAKjF,aAAoB,kBAAkB,cAA4B,SAAuC;EACvG,MAAM,YAAY,IAAI,eAAe,aAAa;AAIlD,SAFoB,MAAM,gBAAgB,OAAO,SAAS,UAAU;;;0BAxJvE,YAAY"}
1
+ {"version":3,"file":"X509Service.mjs","names":["X509Service","parsedLeafCertificate: x509.X509Certificate","certificatesToBuildChain: x509.X509Certificate[]","previousCertificate: X509Certificate | undefined"],"sources":["../../../src/modules/x509/X509Service.ts"],"sourcesContent":["import * as x509 from '@peculiar/x509'\nimport { injectable } from 'tsyringe'\nimport { AgentContext } from '../../agent'\nimport { CredoWebCrypto } from '../../crypto/webcrypto'\nimport { CertificateSigningRequest } from './CertificateSigningRequest'\nimport { X509Certificate } from './X509Certificate'\nimport { X509Error } from './X509Error'\nimport type {\n X509CreateCertificateOptions,\n X509CreateCertificateSigningRequestOptions,\n X509GetLeafCertificateOptions,\n X509ParseCertificateOptions,\n X509ParseCertificateSigningRequestOptions,\n X509ValidateCertificateChainOptions,\n} from './X509ServiceOptions'\n\n@injectable()\n// biome-ignore lint/complexity/noStaticOnlyClass: no explanation\nexport class X509Service {\n /**\n *\n * Validate a chain of X.509 certificates according to RFC 5280\n *\n * This function requires a list of base64 encoded certificates and, optionally, a certificate that should be found in the chain.\n * If no certificate is provided, it will just assume the leaf certificate\n *\n * The leaf certificate should be the 0th index and the root the last\n *\n * The Issuer of the certificate is found with the following algorithm:\n * - Check if there is an AuthorityKeyIdentifierExtension\n * - Go through all the other certificates and see if the SubjectKeyIdentifier is equal to the AuthorityKeyIdentifier\n * - If they are equal, the certificate is verified and returned as the issuer\n *\n * Additional validation:\n * - Make sure at least a single certificate is in the chain\n * - Check whether a certificate in the chain matches with a trusted certificate\n */\n public static async validateCertificateChain(\n agentContext: AgentContext,\n {\n certificateChain,\n certificate = certificateChain[0],\n verificationDate = new Date(),\n trustedCertificates,\n }: X509ValidateCertificateChainOptions\n ) {\n if (certificateChain.length === 0) throw new X509Error('Certificate chain is empty')\n const webCrypto = new CredoWebCrypto(agentContext)\n\n let parsedLeafCertificate: x509.X509Certificate\n let certificatesToBuildChain: x509.X509Certificate[]\n try {\n parsedLeafCertificate = new x509.X509Certificate(certificate)\n certificatesToBuildChain = [...certificateChain, ...(trustedCertificates ?? [])].map(\n (c) => new x509.X509Certificate(c)\n )\n } catch (error) {\n throw new X509Error('Error during parsing of x509 certificate', { cause: error })\n }\n\n const certificateChainBuilder = new x509.X509ChainBuilder({\n certificates: certificatesToBuildChain,\n })\n\n const chain = await certificateChainBuilder.build(parsedLeafCertificate, webCrypto)\n\n // The chain is reversed here as the `x5c` header (the expected input),\n // has the leaf certificate as the first entry, while the `x509` library expects this as the last\n let parsedChain = chain.map((c) => X509Certificate.fromRawCertificate(new Uint8Array(c.rawData))).reverse()\n\n // We allow longer parsed chain, in case the root cert was not part of the chain, but in the\n // list of trusted certificates\n if (parsedChain.length < certificateChain.length) {\n throw new X509Error('Could not parse the full chain. Likely due to incorrect ordering')\n }\n\n let previousCertificate: X509Certificate | undefined\n\n if (trustedCertificates) {\n const parsedTrustedCertificates = trustedCertificates.map((trustedCertificate) =>\n X509Certificate.fromEncodedCertificate(trustedCertificate)\n )\n\n const trustedCertificateIndex = parsedChain.findIndex((cert) =>\n parsedTrustedCertificates.some((tCert) => cert.equal(tCert))\n )\n\n if (trustedCertificateIndex === -1) {\n throw new X509Error('No trusted certificate was found while validating the X.509 chain')\n }\n\n if (trustedCertificateIndex > 0) {\n // When we trust a certificate other than the first certificate in the provided chain we keep a reference to the\n // previous certificate as we need the key of this certificate to verify the first certificate in the chain as\n // it's not self-sigend.\n previousCertificate = parsedChain[trustedCertificateIndex - 1]\n\n // Pop everything off before the index of the trusted certificate (those are more root) as it is not relevant for validation\n parsedChain = parsedChain.slice(trustedCertificateIndex)\n }\n }\n\n // Verify the certificate with the publicKey of the certificate above\n for (let i = 0; i < parsedChain.length; i++) {\n const cert = parsedChain[i]\n const publicJwk = previousCertificate ? previousCertificate.publicJwk : undefined\n\n // The only scenario where this will trigger is if the trusted certificates and the x509 chain both do not contain the\n // intermediate/root certificate needed. E.g. for ISO 18013-5 mDL the root cert MUST NOT be in the chain. If the signer\n // certificate is then trusted, it will fail, as we can't verify the signer certifciate without having access to the signer\n // key of the root certificate.\n // See also https://github.com/openid/OpenID4VCI/issues/62\n //\n // In this case we could skip the signature verification (not other verifications), as we already trust the signer certificate,\n // but i think the purpose of ISO 18013-5 mDL is that you trust the root certificate. If we can't verify the whole chain e.g.\n // when we receive a credential we have the chance it will fail later on.\n const skipSignatureVerification = i === 0 && trustedCertificates && !publicJwk\n // NOTE: at some point we might want to change this to throw an error instead of skipping the signature verification of the trusted\n // but it would basically prevent mDOCs from unknown issuers to be verified in the wallet. Verifiers should only trust the root certificate\n // anyway.\n // if (i === 0 && trustedCertificates && cert.issuer !== cert.subject && !publicKey) {\n // throw new X509Error(\n // 'Unable to verify the certificate chain. A non-self-signed certificate is the first certificate in the chain, and no parent certificate was found in the trusted certificates, meaning the first certificate in the chain cannot be verified. Ensure the certificate is added '\n // )\n // }\n\n await cert.verify(\n {\n publicJwk,\n verificationDate,\n skipSignatureVerification,\n },\n webCrypto\n )\n previousCertificate = cert\n }\n\n return parsedChain\n }\n\n /**\n *\n * Parses a base64-encoded X.509 certificate into a {@link X509Certificate}\n *\n */\n public static parseCertificate(\n _agentContext: AgentContext,\n { encodedCertificate }: X509ParseCertificateOptions\n ): X509Certificate {\n const certificate = X509Certificate.fromEncodedCertificate(encodedCertificate)\n\n return certificate\n }\n\n public static getLeafCertificate(\n _agentContext: AgentContext,\n { certificateChain }: X509GetLeafCertificateOptions\n ): X509Certificate {\n if (certificateChain.length === 0) throw new X509Error('Certificate chain is empty')\n\n const certificate = X509Certificate.fromEncodedCertificate(certificateChain[0])\n\n return certificate\n }\n\n public static async createCertificate(agentContext: AgentContext, options: X509CreateCertificateOptions) {\n const webCrypto = new CredoWebCrypto(agentContext)\n\n const certificate = await X509Certificate.create(options, webCrypto)\n\n return certificate\n }\n\n public static async createCertificateSigningRequest(\n agentContext: AgentContext,\n options: X509CreateCertificateSigningRequestOptions\n ) {\n const webCrypto = new CredoWebCrypto(agentContext)\n\n const csr = await CertificateSigningRequest.create(options, webCrypto)\n\n return csr\n }\n\n public static parseCertificateSigningRequest({\n encodedCertificateSigningRequest,\n }: X509ParseCertificateSigningRequestOptions) {\n const csr = CertificateSigningRequest.fromEncodedCertificateRequest(encodedCertificateSigningRequest)\n\n return csr\n }\n}\n"],"mappings":";;;;;;;;;;;;;AAkBO,wBAAMA,cAAY;;;;;;;;;;;;;;;;;;;CAmBvB,aAAoB,yBAClB,cACA,EACE,kBACA,cAAc,iBAAiB,IAC/B,mCAAmB,IAAI,MAAM,EAC7B,uBAEF;AACA,MAAI,iBAAiB,WAAW,EAAG,OAAM,IAAI,UAAU,6BAA6B;EACpF,MAAM,YAAY,IAAI,eAAe,aAAa;EAElD,IAAIC;EACJ,IAAIC;AACJ,MAAI;AACF,2BAAwB,IAAI,KAAK,gBAAgB,YAAY;AAC7D,8BAA2B,CAAC,GAAG,kBAAkB,GAAI,uBAAuB,EAAE,CAAE,CAAC,KAC9E,MAAM,IAAI,KAAK,gBAAgB,EAAE,CACnC;WACM,OAAO;AACd,SAAM,IAAI,UAAU,4CAA4C,EAAE,OAAO,OAAO,CAAC;;EAWnF,IAAI,eAJU,MAJkB,IAAI,KAAK,iBAAiB,EACxD,cAAc,0BACf,CAAC,CAE0C,MAAM,uBAAuB,UAAU,EAI3D,KAAK,MAAM,gBAAgB,mBAAmB,IAAI,WAAW,EAAE,QAAQ,CAAC,CAAC,CAAC,SAAS;AAI3G,MAAI,YAAY,SAAS,iBAAiB,OACxC,OAAM,IAAI,UAAU,mEAAmE;EAGzF,IAAIC;AAEJ,MAAI,qBAAqB;GACvB,MAAM,4BAA4B,oBAAoB,KAAK,uBACzD,gBAAgB,uBAAuB,mBAAmB,CAC3D;GAED,MAAM,0BAA0B,YAAY,WAAW,SACrD,0BAA0B,MAAM,UAAU,KAAK,MAAM,MAAM,CAAC,CAC7D;AAED,OAAI,4BAA4B,GAC9B,OAAM,IAAI,UAAU,oEAAoE;AAG1F,OAAI,0BAA0B,GAAG;AAI/B,0BAAsB,YAAY,0BAA0B;AAG5D,kBAAc,YAAY,MAAM,wBAAwB;;;AAK5D,OAAK,IAAI,IAAI,GAAG,IAAI,YAAY,QAAQ,KAAK;GAC3C,MAAM,OAAO,YAAY;GACzB,MAAM,YAAY,sBAAsB,oBAAoB,YAAY;GAWxE,MAAM,4BAA4B,MAAM,KAAK,uBAAuB,CAAC;AAUrE,SAAM,KAAK,OACT;IACE;IACA;IACA;IACD,EACD,UACD;AACD,yBAAsB;;AAGxB,SAAO;;;;;;;CAQT,OAAc,iBACZ,eACA,EAAE,sBACe;AAGjB,SAFoB,gBAAgB,uBAAuB,mBAAmB;;CAKhF,OAAc,mBACZ,eACA,EAAE,oBACe;AACjB,MAAI,iBAAiB,WAAW,EAAG,OAAM,IAAI,UAAU,6BAA6B;AAIpF,SAFoB,gBAAgB,uBAAuB,iBAAiB,GAAG;;CAKjF,aAAoB,kBAAkB,cAA4B,SAAuC;EACvG,MAAM,YAAY,IAAI,eAAe,aAAa;AAIlD,SAFoB,MAAM,gBAAgB,OAAO,SAAS,UAAU;;CAKtE,aAAoB,gCAClB,cACA,SACA;EACA,MAAM,YAAY,IAAI,eAAe,aAAa;AAIlD,SAFY,MAAM,0BAA0B,OAAO,SAAS,UAAU;;CAKxE,OAAc,+BAA+B,EAC3C,oCAC4C;AAG5C,SAFY,0BAA0B,8BAA8B,iCAAiC;;;0BA3KxG,YAAY"}