{"version":3,"file":"X509Certificate.mjs","names":[],"sources":["../../../src/modules/x509/X509Certificate.ts"],"sourcesContent":["import { AsnParser } from '@peculiar/asn1-schema'\nimport { SubjectPublicKeyInfo } 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 { 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  X509ExtensionIdentifier,\n  x509SignatureAlgorithmToJwa,\n} from './utils'\nimport type { X509CrlDistributionPoint, X509RevocationReason } from './X509CrlDistributionPoint'\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?: Uint8Array\n  x509Certificate: x509.X509Certificate\n}\n\nexport class X509Certificate {\n  public publicJwk: PublicJwk\n  public privateKey?: Uint8Array\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: Uint8Array): 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>(X509ExtensionIdentifier.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>(X509ExtensionIdentifier.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>(\n      X509ExtensionIdentifier.AuthorityKeyIdentifier\n    )?.map((e) => e.keyId)\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>(\n      X509ExtensionIdentifier.SubjectKeyIdentifier\n    )?.map((e) => e.keyId)\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>(X509ExtensionIdentifier.KeyUsage)?.map(\n      (e) => e.usages\n    )\n\n    if (keyUsages && keyUsages.length > 1) {\n      throw new X509Error('Multiple Key Usages are not allowed')\n    }\n\n    if (keyUsages) {\n      return (\n        Object.values(X509KeyUsage)\n          .filter((key): key is number => typeof key === 'number')\n          // KeyUsage is stored as bit value\n          .filter((flagValue) => (keyUsages[0] & flagValue) === flagValue)\n          .map((flagValue) => flagValue as X509KeyUsage)\n      )\n    }\n  }\n\n  public get extendedKeyUsage() {\n    const extendedKeyUsages = this.getMatchingExtensions<x509.ExtendedKeyUsageExtension>(\n      X509ExtensionIdentifier.ExtendedKeyUsage\n    )?.map((e) => e.usages)\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  /**\n   * Whether this certificate is a certificate authority (the Basic Constraints `cA` flag is set).\n   * Returns `false` when the Basic Constraints extension is absent (e.g. an end-entity certificate).\n   */\n  public get isCertificateAuthority(): boolean {\n    const basicConstraints = this.getMatchingExtensions<x509.BasicConstraintsExtension>(\n      X509ExtensionIdentifier.BasicConstraints\n    )\n\n    if (basicConstraints && basicConstraints.length > 1) {\n      throw new X509Error('Multiple Basic Constraints extensions are not allowed')\n    }\n\n    return basicConstraints?.[0]?.ca ?? false\n  }\n\n  /**\n   * Get CRL Distribution Points with full structure including URLs, reasons, and CRL issuer.\n   * Based on RFC 5280 Section 4.2.1.13\n   *\n   * NOTE: only the URI form is surfaced for both the distribution point name (fullName) and the\n   * cRLIssuer; nameRelativeToCRLIssuer and non-URI general names are ignored. Indirect CRLs\n   * (those with a cRLIssuer) are surfaced here but are not verified during revocation checking.\n   */\n  public get crlDistributionPoints(): X509CrlDistributionPoint[] {\n    const crlDistributionPointsExt = this.getMatchingExtensions<x509.CRLDistributionPointsExtension>(\n      X509ExtensionIdentifier.CrlDistributionPoints\n    )\n\n    if (crlDistributionPointsExt && crlDistributionPointsExt.length > 1) {\n      throw new X509Error('Multiple CRL Distribution Points extensions are not allowed')\n    }\n\n    const ext = crlDistributionPointsExt?.[0]\n    if (!ext) {\n      return []\n    }\n\n    const distributionPoints = ext.distributionPoints\n    if (!distributionPoints || distributionPoints.length === 0) {\n      return []\n    }\n\n    const result: X509CrlDistributionPoint[] = []\n\n    for (const dp of distributionPoints) {\n      // Extract URLs - @peculiar library stores these as uniformResourceIdentifier in fullName\n      const urls: string[] = []\n\n      // fullName is an array of GeneralName objects\n      if (dp.distributionPoint?.fullName) {\n        for (const generalName of dp.distributionPoint.fullName) {\n          // GeneralName has uniformResourceIdentifier property for URLs\n          if (generalName.uniformResourceIdentifier) {\n            urls.push(generalName.uniformResourceIdentifier)\n          }\n        }\n      }\n\n      // Skip distribution points with no URLs\n      if (urls.length === 0) {\n        continue\n      }\n\n      // Extract reasons if present\n      // If reasons is undefined/null, this is a \"full\" distribution point covering all reasons\n      let reasons: X509RevocationReason[] | undefined\n      if (dp.reasons !== undefined && dp.reasons !== null) {\n        // The reasons field is an ASN.1 BIT STRING. `toNumber()` returns a bitmask where\n        // bit `i` corresponds to revocation reason code `i` (e.g. keyCompromise = bit 1).\n        const reasonBits = dp.reasons.toNumber()\n        reasons = []\n        for (let i = 0; i <= 8; i++) {\n          // Check if bit i is set (reasons 0-8)\n          if ((reasonBits & (1 << i)) !== 0) {\n            reasons.push(i)\n          }\n        }\n      }\n\n      // Extract the cRLIssuer URI (indirect CRL), if present. Only the URI (uniformResourceIdentifier)\n      // form is surfaced. Indirect CRLs are not verified during revocation checking, but exposing the\n      // field lets the revocation service recognise and skip such distribution points.\n      let crlIssuer: string | undefined\n      if (dp.cRLIssuer) {\n        for (const generalName of dp.cRLIssuer) {\n          if (generalName.uniformResourceIdentifier) {\n            crlIssuer = generalName.uniformResourceIdentifier\n            break\n          }\n        }\n      }\n\n      result.push({\n        urls,\n        reasons,\n        crlIssuer,\n      })\n    }\n\n    return result\n  }\n\n  public isExtensionCritical(id: X509ExtensionIdentifier | 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        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  public get subject() {\n    return this.x509Certificate.subject\n  }\n\n  /**\n   * The DER-encoded subject distinguished name. Use this for exact, encoding-stable name comparison\n   * (e.g. binding a CRL to its issuer) rather than the string form returned by {@link subject}.\n   */\n  public get subjectNameBytes(): Uint8Array {\n    return new Uint8Array(this.x509Certificate.subjectName.toArrayBuffer())\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        alg: publicJwk.kty === 'RSA' ? x509SignatureAlgorithmToJwa(this.x509Certificate.signatureAlgorithm) : undefined,\n      })\n\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  public getSubjectNameField(field: string) {\n    return this.x509Certificate.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.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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"}