{"version":3,"file":"Mdoc.mjs","names":[],"sources":["../../../src/modules/mdoc/Mdoc.ts"],"sourcesContent":["import { DeviceKey, DeviceKeyInfo, Holder, Issuer, IssuerSigned, SignatureAlgorithm } from '@owf/mdoc'\nimport type { AgentContext } from '../../agent'\nimport { type KnownJwaSignatureAlgorithm, PublicJwk } from '../kms'\nimport { isKnownJwaSignatureAlgorithm } from '../kms/jwk/jwa'\nimport { ClaimFormat } from '../vc/index'\nimport { X509Certificate, X509ModuleConfig } from '../x509'\nimport { getMdocContext } from './MdocContext'\nimport { MdocError } from './MdocError'\nimport type { MdocNameSpaces, MdocSignOptions, MdocVerifyOptions } from './MdocOptions'\nimport { isMdocSupportedSignatureAlgorithm, mdocSupportedSignatureAlgorithms } from './mdocSupportedAlgs'\n\n/**\n * This class represents a IssuerSigned Mdoc Document,\n * which are the actual credentials being issued to holders.\n */\nexport class Mdoc {\n  public get base64Url() {\n    return this.issuerSigned.encodedForOid4Vci\n  }\n\n  #deviceKeyId?: string\n\n  public constructor(public issuerSigned: IssuerSigned) {}\n\n  /**\n   * claim format is convenience method added to all credential instances\n   */\n  public get claimFormat() {\n    return ClaimFormat.MsoMdoc as const\n  }\n\n  /**\n   * Encoded is convenience method added to all credential instances\n   */\n  public get encoded() {\n    return this.issuerSigned.encodedForOid4Vci\n  }\n\n  /**\n   * Get the device key to which the mdoc is bound\n   */\n  public get deviceKey(): PublicJwk {\n    const publicJwk = PublicJwk.fromUnknown(\n      this.issuerSigned.issuerAuth.mobileSecurityObject.deviceKeyInfo.deviceKey.jwk\n    )\n\n    if (this.#deviceKeyId) publicJwk.keyId = this.#deviceKeyId\n    return publicJwk\n  }\n\n  public set deviceKeyId(keyId: string | undefined) {\n    this.#deviceKeyId = keyId\n  }\n\n  public get deviceKeyId() {\n    const deviceKey = this.deviceKey\n\n    if (deviceKey.hasKeyId) return deviceKey.keyId\n    return undefined\n  }\n\n  public static fromBase64Url(mdocBase64Url: string): Mdoc {\n    const issuerSigned = IssuerSigned.fromEncodedForOid4Vci(mdocBase64Url)\n    return new Mdoc(issuerSigned)\n  }\n\n  public get docType(): string {\n    return this.issuerSigned.issuerAuth.mobileSecurityObject.docType\n  }\n\n  public get alg(): KnownJwaSignatureAlgorithm {\n    const algName = this.issuerSigned.issuerAuth.signatureAlgorithmName\n    if (isKnownJwaSignatureAlgorithm(algName)) {\n      return algName\n    }\n\n    throw new MdocError(`Cannot parse mdoc. The signature algorithm '${algName}' is not supported.`)\n  }\n\n  public get validityInfo() {\n    const { signed, validFrom, validUntil } = this.issuerSigned.issuerAuth.mobileSecurityObject.validityInfo\n    return {\n      signed,\n      validFrom,\n      validUntil,\n    }\n  }\n\n  public get issuerSignedCertificateChain() {\n    return this.issuerSigned.issuerAuth.certificateChain\n  }\n\n  public get signingCertificate() {\n    return this.issuerSigned.issuerAuth.certificate\n  }\n\n  public get issuerSignedNamespaces(): MdocNameSpaces {\n    if (!this.issuerSigned.issuerNamespaces?.issuerNamespaces) return {}\n\n    return Object.fromEntries(\n      Array.from(this.issuerSigned.issuerNamespaces.issuerNamespaces.entries()).map(([namespace, value]) => [\n        namespace,\n        Object.fromEntries(Array.from(value.values()).map((v) => [v.elementIdentifier, v.elementValue])),\n      ])\n    )\n  }\n\n  public static async sign(agentContext: AgentContext, options: MdocSignOptions) {\n    const { docType, validityInfo, namespaces, holderKey, issuerCertificate } = options\n    const mdocContext = getMdocContext(agentContext)\n\n    const issuer = new Issuer(docType, mdocContext)\n\n    for (const [namespace, namespaceRecord] of Object.entries(namespaces)) {\n      issuer.addIssuerNamespace(namespace, namespaceRecord)\n    }\n\n    const issuerKey = issuerCertificate.publicJwk\n    const alg = issuerKey.supportedSignatureAlgorithms.find(isMdocSupportedSignatureAlgorithm)\n    if (!alg) {\n      throw new MdocError(\n        `Unable to create sign mdoc. No supported signature algorithm found to sign mdoc for jwk with key ${\n          issuerKey.jwkTypeHumanDescription\n        }. Key supports algs ${issuerKey.supportedSignatureAlgorithms.join(\n          ', '\n        )}. mdoc supports algs ${mdocSupportedSignatureAlgorithms.join(', ')}`\n      )\n    }\n\n    const now = new Date()\n    const issuerSigned = await issuer.sign({\n      digestAlgorithm: 'SHA-256',\n      validityInfo: {\n        ...validityInfo,\n        signed: validityInfo.signed ?? now,\n        validFrom: validityInfo.validFrom ?? now,\n      },\n      algorithm: SignatureAlgorithm[alg],\n      certificates: [issuerCertificate.rawCertificate],\n      deviceKeyInfo: DeviceKeyInfo.create({ deviceKey: DeviceKey.fromJwk(holderKey.toJson()) }),\n      signingKey: issuerKey.toJson(),\n    })\n\n    return new Mdoc(issuerSigned)\n  }\n\n  public async verify(\n    agentContext: AgentContext,\n    options?: MdocVerifyOptions\n  ): Promise<{ isValid: true } | { isValid: false; error: string }> {\n    const x509ModuleConfig = agentContext.dependencyManager.resolve(X509ModuleConfig)\n    const certificateChain = this.issuerSigned.issuerAuth.certificateChain.map((certificate) =>\n      X509Certificate.fromRawCertificate(certificate)\n    )\n\n    let trustedCertificates = options?.trustedCertificates\n    if (!trustedCertificates) {\n      trustedCertificates =\n        (await x509ModuleConfig.getTrustedCertificatesForVerification?.(agentContext, {\n          verification: {\n            type: 'credential',\n            credential: this,\n          },\n          certificateChain,\n        })) ?? x509ModuleConfig.trustedCertificates\n    }\n\n    if (!trustedCertificates) {\n      throw new MdocError('No trusted certificates found. Cannot verify mdoc.')\n    }\n\n    const mdocContext = getMdocContext(agentContext, {\n      now: options?.now,\n    })\n    try {\n      await Holder.verifyIssuerSigned(\n        {\n          trustedCertificates: trustedCertificates.map(\n            (cert) => X509Certificate.fromEncodedCertificate(cert).rawCertificate\n          ),\n          issuerSigned: this.issuerSigned,\n          disableCertificateChainValidation: false,\n          now: options?.now,\n        },\n        mdocContext\n      )\n\n      return { isValid: true }\n    } catch (error) {\n      return { isValid: false, error: error.message }\n    }\n  }\n}\n"],"mappings":"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"}