{"version":3,"file":"JwsService.mjs","names":[],"sources":["../../src/crypto/JwsService.ts"],"sourcesContent":["import type { AgentContext } from '../agent'\nimport { CredoError } from '../error'\nimport {\n  assertJwkAsymmetric,\n  asymmetricPublicJwkMatches,\n  getJwkHumanDescription,\n  KeyManagementApi,\n  KeyManagementError,\n  type KnownJwaSignatureAlgorithm,\n  PublicJwk,\n} from '../modules/kms'\nimport { isKnownJwaSignatureAlgorithm } from '../modules/kms/jwk/jwa'\nimport { convertLegacyTrustedCertificates } from '../modules/x509/utils/convertLegacyTrustedCertificates'\nimport { X509ModuleConfig, type X509VerificationTrustedCertificates } from '../modules/x509/X509ModuleConfig'\nimport { X509Service } from './../modules/x509/X509Service'\nimport { type EncodedX509Certificate } from '../modules/x509/X509ServiceOptions'\nimport { injectable } from '../plugins'\nimport { isJsonObject } from '../types'\nimport { JsonEncoder, TypedArrayEncoder } from '../utils'\nimport type { JwsSigner, JwsSignerWithJwk } from './JwsSigner'\nimport type {\n  Jws,\n  JwsDetachedFormat,\n  JwsFlattenedFormat,\n  JwsGeneralFormat,\n  JwsProtectedHeaderOptions,\n} from './JwsTypes'\nimport { JWS_COMPACT_FORMAT_MATCHER } from './JwsTypes'\nimport { JwtPayload } from './jose/jwt'\n\n@injectable()\nexport class JwsService {\n  private async createJwsBase(agentContext: AgentContext, options: CreateJwsBaseOptions) {\n    const { jwk, alg, x5c } = options.protectedHeaderOptions\n\n    const kms = agentContext.dependencyManager.resolve(KeyManagementApi)\n\n    const key = await kms.getPublicKey({ keyId: options.keyId })\n    assertJwkAsymmetric(key)\n\n    const publicJwk = PublicJwk.fromPublicJwk(key)\n\n    // Make sure the options.x5c and x5c from protectedHeader are the same.\n    if (x5c) {\n      const certificate = X509Service.getLeafCertificate(agentContext, {\n        certificateChain: x5c,\n      })\n\n      if (!asymmetricPublicJwkMatches(certificate.publicJwk.toJson(), key)) {\n        throw new CredoError('Protected header x5c does not match key for signing.')\n      }\n    }\n\n    const jwkInstance = jwk instanceof PublicJwk ? jwk : jwk ? PublicJwk.fromUnknown(jwk) : undefined\n    // Make sure the options.key and jwk from protectedHeader are the same.\n    if (jwkInstance && !asymmetricPublicJwkMatches(jwkInstance.toJson(), key)) {\n      throw new CredoError('Protected header JWK does not match key for signing.')\n    }\n\n    // Validate the options.key used for signing against the jws options\n    if (!publicJwk.supportedSignatureAlgorithms.includes(alg)) {\n      throw new CredoError(\n        `alg '${alg}' is not a valid JWA signature algorithm for this jwk with ${publicJwk.jwkTypeHumanDescription}. Supported algorithms are ${publicJwk.supportedSignatureAlgorithms.join(\n          ', '\n        )}`\n      )\n    }\n\n    const payload =\n      options.payload instanceof JwtPayload ? JsonEncoder.toUint8Array(options.payload.toJson()) : options.payload\n\n    const base64Payload = TypedArrayEncoder.toBase64Url(payload)\n    const base64UrlProtectedHeader = JsonEncoder.toBase64Url(this.buildProtected(options.protectedHeaderOptions))\n\n    const signResult = await kms.sign({\n      algorithm: alg,\n      data: TypedArrayEncoder.fromUtf8String(`${base64UrlProtectedHeader}.${base64Payload}`),\n      keyId: options.keyId,\n    })\n    const signature = TypedArrayEncoder.toBase64Url(signResult.signature)\n\n    return {\n      base64Payload,\n      base64UrlProtectedHeader,\n      signature,\n    }\n  }\n\n  public async createJws(\n    agentContext: AgentContext,\n    { payload, keyId, header, protectedHeaderOptions }: CreateJwsOptions\n  ): Promise<JwsGeneralFormat> {\n    const { base64UrlProtectedHeader, signature, base64Payload } = await this.createJwsBase(agentContext, {\n      payload,\n      keyId,\n      protectedHeaderOptions,\n    })\n\n    return {\n      protected: base64UrlProtectedHeader,\n      signature,\n      header,\n      payload: base64Payload,\n    }\n  }\n\n  /**\n   *  @see {@link https://www.rfc-editor.org/rfc/rfc7515#section-3.1}\n   * */\n  public async createJwsCompact(\n    agentContext: AgentContext,\n    { payload, keyId, protectedHeaderOptions }: CreateCompactJwsOptions\n  ): Promise<string> {\n    const { base64Payload, base64UrlProtectedHeader, signature } = await this.createJwsBase(agentContext, {\n      payload,\n      keyId,\n      protectedHeaderOptions,\n    })\n    return `${base64UrlProtectedHeader}.${base64Payload}.${signature}`\n  }\n\n  /**\n   * Verify a JWS\n   */\n  public async verifyJws(\n    agentContext: AgentContext,\n    {\n      jws,\n      resolveJwsSigner,\n      trustedCertificates,\n      jwsSigner: expectedJwsSigner,\n      allowedJwsSignerMethods = ['did', 'jwk', 'x5c'],\n    }: VerifyJwsOptions\n  ): Promise<VerifyJwsResult> {\n    let signatures: JwsDetachedFormat[] = []\n    let payload: string\n\n    if (expectedJwsSigner && !allowedJwsSignerMethods.includes(expectedJwsSigner.method)) {\n      throw new CredoError(\n        `jwsSigner provided with method '${\n          expectedJwsSigner.method\n        }', but allowed jws signer methods are ${allowedJwsSignerMethods.join(', ')}.`\n      )\n    }\n\n    if (typeof jws === 'string') {\n      if (!JWS_COMPACT_FORMAT_MATCHER.test(jws)) throw new CredoError(`Invalid JWS compact format for value '${jws}'.`)\n\n      const [protectedHeader, _payload, signature] = jws.split('.')\n\n      payload = _payload\n      signatures.push({\n        header: {},\n        protected: protectedHeader,\n        signature,\n      })\n    } else if ('signatures' in jws) {\n      signatures = jws.signatures\n      payload = jws.payload\n    } else {\n      signatures.push(jws)\n      payload = jws.payload\n    }\n\n    if (signatures.length === 0) {\n      throw new CredoError('Unable to verify JWS, no signatures present in JWS.')\n    }\n\n    const jwsFlattened = {\n      signatures,\n      payload,\n    } satisfies JwsFlattenedFormat\n\n    const jwsSigners: JwsSignerWithJwk[] = []\n    for (const jws of signatures) {\n      const protectedJson = JsonEncoder.fromBase64Url(jws.protected)\n\n      if (!isJsonObject(protectedJson)) {\n        throw new CredoError('Unable to verify JWS, protected header is not a valid JSON object.')\n      }\n\n      if (!protectedJson.alg || typeof protectedJson.alg !== 'string') {\n        throw new CredoError('Unable to verify JWS, protected header alg is not provided or not a string.')\n      }\n\n      const jwsSigner =\n        expectedJwsSigner ??\n        (await this.jwsSignerFromJws(agentContext, {\n          jws,\n          payload,\n          protectedHeader: {\n            ...protectedJson,\n            alg: protectedJson.alg,\n          },\n          allowedJwsSignerMethods,\n          resolveJwsSigner,\n        }))\n\n      await this.verifyJwsSigner(agentContext, {\n        jwsSigner,\n        trustedCertificates,\n      })\n\n      if (!jwsSigner.jwk.supportedSignatureAlgorithms.includes(protectedJson.alg as KnownJwaSignatureAlgorithm)) {\n        throw new CredoError(\n          `alg '${protectedJson.alg}' is not a valid JWA signature algorithm for this jwk ${getJwkHumanDescription(jwsSigner.jwk.toJson())}. Supported algorithms are ${jwsSigner.jwk.supportedSignatureAlgorithms.join(', ')}`\n        )\n      }\n\n      const data = TypedArrayEncoder.fromUtf8String(`${jws.protected}.${payload}`)\n      const signature = TypedArrayEncoder.fromBase64Url(jws.signature)\n      jwsSigners.push(jwsSigner)\n\n      const kms = agentContext.dependencyManager.resolve(KeyManagementApi)\n\n      try {\n        const { verified } = await kms.verify({\n          key: {\n            publicJwk: jwsSigner.jwk.toJson(),\n          },\n          data,\n          signature,\n          algorithm: protectedJson.alg as KnownJwaSignatureAlgorithm,\n        })\n\n        if (!verified) {\n          return {\n            isValid: false,\n            jwsSigners: [],\n            jws: jwsFlattened,\n          }\n        }\n      } catch (error) {\n        // WalletError probably means signature verification failed. Would be useful to add\n        // more specific error type in kms.verify method\n        if (error instanceof KeyManagementError) {\n          return {\n            isValid: false,\n            jwsSigners: [],\n            jws: jwsFlattened,\n          }\n        }\n\n        throw error\n      }\n    }\n\n    return { isValid: true, jwsSigners, jws: jwsFlattened }\n  }\n\n  private buildProtected(options: JwsProtectedHeaderOptions) {\n    return {\n      ...options,\n      alg: options.alg,\n      jwk: options.jwk instanceof PublicJwk ? options.jwk.toJson() : options.jwk,\n      kid: options.kid,\n    }\n  }\n\n  private async verifyJwsSigner(\n    agentContext: AgentContext,\n    options: {\n      jwsSigner: JwsSignerWithJwk\n      trustedCertificates?: EncodedX509Certificate[] | X509VerificationTrustedCertificates[]\n    }\n  ) {\n    const { jwsSigner } = options\n    const x509ModuleConfig = agentContext.dependencyManager.resolve(X509ModuleConfig)\n\n    if (jwsSigner.method === 'x5c') {\n      const trustedCertificatesFromConfig = x509ModuleConfig.trustedCertificates ?? []\n      const trustedCertificates = options.trustedCertificates ?? trustedCertificatesFromConfig\n      if (trustedCertificates.length === 0) {\n        throw new CredoError(\n          `trustedCertificates is required when the JWS protected header contains an 'x5c' property.`\n        )\n      }\n\n      const convertedTrustedCertificates = convertLegacyTrustedCertificates(trustedCertificates)\n\n      await X509Service.validateCertificateChain(agentContext, {\n        certificateChain: jwsSigner.x5c,\n        trustedCertificates: convertedTrustedCertificates.flatMap(({ issuance }) => issuance),\n      })\n    }\n  }\n\n  private async jwsSignerFromJws(\n    agentContext: AgentContext,\n    options: {\n      jws: JwsDetachedFormat\n      allowedJwsSignerMethods: JwsSigner['method'][]\n      protectedHeader: { alg: string; [key: string]: unknown }\n      payload: string\n      resolveJwsSigner?: JwsSignerResolver\n    }\n  ): Promise<JwsSignerWithJwk> {\n    const { protectedHeader, resolveJwsSigner, jws, payload, allowedJwsSignerMethods } = options\n\n    const alg = protectedHeader.alg\n    if (!isKnownJwaSignatureAlgorithm(alg)) {\n      throw new CredoError(`Unsupported JWA signature algorithm '${protectedHeader.alg}'`)\n    }\n\n    if (protectedHeader.x5c && allowedJwsSignerMethods.includes('x5c')) {\n      if (\n        !Array.isArray(protectedHeader.x5c) ||\n        protectedHeader.x5c.some((certificate) => typeof certificate !== 'string')\n      ) {\n        throw new CredoError('x5c header is not a valid JSON array of strings.')\n      }\n\n      const certificate = X509Service.getLeafCertificate(agentContext, {\n        certificateChain: protectedHeader.x5c,\n      })\n      return {\n        method: 'x5c',\n        jwk: certificate.publicJwk,\n        x5c: protectedHeader.x5c,\n      }\n    }\n\n    // Jwk\n    if (protectedHeader.jwk && allowedJwsSignerMethods.includes('jwk')) {\n      if (!isJsonObject(protectedHeader.jwk)) throw new CredoError('JWK is not a valid JSON object.')\n\n      const protectedJwk = PublicJwk.fromUnknown(protectedHeader.jwk)\n\n      return {\n        method: 'jwk',\n        jwk: protectedJwk,\n      }\n    }\n\n    if (!resolveJwsSigner) {\n      throw new CredoError(`resolveJwsSigner is required for resolving jws signers other than 'jwk' and 'x5c'.`)\n    }\n\n    try {\n      const jwsSigner = await resolveJwsSigner({\n        jws,\n        protectedHeader: {\n          ...protectedHeader,\n          alg,\n        },\n        payload,\n      })\n\n      if (!allowedJwsSignerMethods.includes(jwsSigner.method)) {\n        throw new CredoError(\n          `resolveJwsSigner returned jws signer with method '${\n            jwsSigner.method\n          }', but allowed jws signer methods are ${allowedJwsSignerMethods.join(', ')}.`\n        )\n      }\n\n      return jwsSigner\n    } catch (error) {\n      throw new CredoError(`Error when resolving jws signer for jws in resolveJwsSigner. ${error.message}`, {\n        cause: error,\n      })\n    }\n  }\n}\n\nexport interface CreateJwsOptions {\n  payload: Uint8Array | JwtPayload\n  keyId: string\n  header: Record<string, unknown>\n  protectedHeaderOptions: JwsProtectedHeaderOptions\n}\n\ntype CreateJwsBaseOptions = Omit<CreateJwsOptions, 'header'>\ntype CreateCompactJwsOptions = Omit<CreateJwsOptions, 'header'>\n\nexport interface VerifyJwsOptions {\n  jws: Jws\n\n  /**\n   * The expected signer of the JWS. If provided the signer won't be dynamically\n   * detected based on the values in the JWS.\n   */\n  jwsSigner?: JwsSignerWithJwk\n\n  /**\n   * Allowed jws signer methods when dynamically inferring the jws signer method.\n   */\n  allowedJwsSignerMethods?: JwsSigner['method'][]\n\n  /*\n   * Method that should return the JWS signer was used\n   * to sign the JWS.\n   *\n   * This method is called by the JWS Service when it could not determine the public key.\n   *\n   * Currently the JWS Service can only determine the public key if the JWS protected header\n   * contains a `jwk` or `x5c` property. In all other cases, it's up to the caller to resolve the public\n   * key based on the JWS.\n   *\n   * A common use case is the `kid` property in the JWS protected header. Or determining the key\n   * base on the `iss` property in the JWT payload.\n   */\n  resolveJwsSigner?: JwsSignerResolver\n\n  trustedCertificates?: EncodedX509Certificate[] | X509VerificationTrustedCertificates[]\n}\n\nexport type JwsSignerResolver = (options: {\n  jws: JwsDetachedFormat\n  payload: string\n  protectedHeader: {\n    alg: KnownJwaSignatureAlgorithm\n    jwk?: string\n    kid?: string\n    [key: string]: unknown\n  }\n}) => Promise<JwsSignerWithJwk> | JwsSignerWithJwk\n\nexport interface VerifyJwsResult {\n  isValid: boolean\n  jwsSigners: JwsSignerWithJwk[]\n\n  jws: JwsFlattenedFormat\n}\n"],"mappings":"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"}