{"version":3,"file":"PublicJwk.mjs","names":[],"sources":["../../../../src/modules/kms/jwk/PublicJwk.ts"],"sourcesContent":["import type { HashName } from '../../../crypto'\nimport { CredoError } from '../../../error'\nimport { MultiBaseEncoder, TypedArrayEncoder, VarintEncoder } from '../../../utils'\nimport type { Constructor } from '../../../utils/mixins'\nimport { zParseWithErrorHandling } from '../../../utils/zod'\nimport { KeyManagementError } from '../error/KeyManagementError'\nimport { legacyKeyIdFromPublicJwk } from '../legacy'\nimport { asymmetricPublicJwkMatches } from './equals'\nimport { getJwkHumanDescription } from './humanDescription'\nimport type { KnownJwaKeyAgreementAlgorithm, KnownJwaSignatureAlgorithm } from './jwa'\nimport { calculateJwkThumbprint } from './jwkThumbprint'\nimport { assertJwkAsymmetric, type KmsJwkPublicAsymmetric, publicJwkFromPrivateJwk, zKmsJwkPublic } from './knownJwk'\nimport {\n  Ed25519PublicJwk,\n  P256PublicJwk,\n  P384PublicJwk,\n  P521PublicJwk,\n  RsaPublicJwk,\n  Secp256k1PublicJwk,\n  X25519PublicJwk,\n} from './kty'\n\nexport const SupportedPublicJwks = [\n  Ed25519PublicJwk,\n  P256PublicJwk,\n  P384PublicJwk,\n  P521PublicJwk,\n  RsaPublicJwk,\n  Secp256k1PublicJwk,\n  X25519PublicJwk,\n]\nexport type SupportedPublicJwkClass = (typeof SupportedPublicJwks)[number]\nexport type SupportedPublicJwk =\n  | Ed25519PublicJwk\n  | P256PublicJwk\n  | P384PublicJwk\n  | P521PublicJwk\n  | RsaPublicJwk\n  | Secp256k1PublicJwk\n  | X25519PublicJwk\n\ntype ExtractByJwk<T, K> = T extends { jwk: infer J } ? (K extends J ? T : never) : never\n\ntype ExtractByPublicKey<T, K> = T extends { publicKey: infer J } ? (K extends J ? T : never) : never\n\nexport class PublicJwk<Jwk extends SupportedPublicJwk = SupportedPublicJwk> {\n  private constructor(private readonly jwk: Jwk) {}\n\n  public static fromUnknown(jwkJson: unknown) {\n    // We remove any private properties if they are present\n    const publicJwk = publicJwkFromPrivateJwk(zParseWithErrorHandling(zKmsJwkPublic, jwkJson, 'jwk is not a valid jwk'))\n    assertJwkAsymmetric(publicJwk)\n\n    let jwkInstance: SupportedPublicJwk\n    if (publicJwk.kty === 'RSA') {\n      jwkInstance = new RsaPublicJwk(publicJwk)\n    } else if (publicJwk.kty === 'EC') {\n      if (publicJwk.crv === 'P-256') {\n        jwkInstance = new P256PublicJwk({\n          ...publicJwk,\n          crv: publicJwk.crv,\n        })\n      } else if (publicJwk.crv === 'P-384') {\n        jwkInstance = new P384PublicJwk({\n          ...publicJwk,\n          crv: publicJwk.crv,\n        })\n      } else if (publicJwk.crv === 'P-521') {\n        jwkInstance = new P521PublicJwk({\n          ...publicJwk,\n          crv: publicJwk.crv,\n        })\n      } else if (publicJwk.crv === 'secp256k1') {\n        jwkInstance = new Secp256k1PublicJwk({\n          ...publicJwk,\n          crv: publicJwk.crv,\n        })\n      } else {\n        throw new KeyManagementError(\n          `Unsupported kty '${publicJwk.kty}' with crv '${publicJwk.crv}' for creating jwk instance`\n        )\n      }\n    } else if (publicJwk.crv === 'Ed25519') {\n      jwkInstance = new Ed25519PublicJwk({\n        ...publicJwk,\n        crv: publicJwk.crv,\n      })\n    } else if (publicJwk.crv === 'X25519') {\n      jwkInstance = new X25519PublicJwk({\n        ...publicJwk,\n        crv: publicJwk.crv,\n      })\n    } else {\n      throw new KeyManagementError(`Unsupported kty '${publicJwk.kty}' for creating jwk instance`)\n    }\n\n    return new PublicJwk(jwkInstance)\n  }\n\n  // FIXME: all Jwk combinations should be separate types.\n  // so not kty: EC, and crv: P-256 | P-384\n  // but: kty: EC, and crv: P-256 | kty: EC, and crv: P-384\n  // As the first approach messes with TypeScript's type inference\n  public static fromPublicJwk<Jwk extends KmsJwkPublicAsymmetric>(jwk: Jwk) {\n    return PublicJwk.fromUnknown(jwk) as PublicJwk<\n      ExtractByJwk<SupportedPublicJwk, Jwk> extends never ? SupportedPublicJwk : ExtractByJwk<SupportedPublicJwk, Jwk>\n    >\n  }\n\n  public toJson({ includeKid = true }: { includeKid?: boolean } = {}): Jwk['jwk'] {\n    if (includeKid) return this.jwk.jwk\n\n    const { kid, ...jwk } = this.jwk.jwk\n    return jwk\n  }\n\n  /**\n   * Get the signature algorithms supported for this jwk.\n   *\n   * If the jwk has an `alg` field defined it will only return that alg\n   * and otherwise return all known supported signature algorithms.\n   */\n  public get supportedSignatureAlgorithms(): KnownJwaSignatureAlgorithm[] {\n    const supportedSignatureAlgorithms: KnownJwaSignatureAlgorithm[] = this.jwk.supportedSignatureAlgorithms ?? []\n\n    if (this.jwk.jwk.alg) {\n      if (!supportedSignatureAlgorithms.includes(this.jwk.jwk.alg as KnownJwaSignatureAlgorithm)) {\n        throw new KeyManagementError(\n          `${this.jwkTypeHumanDescription} defines alg '${this.jwk.jwk.alg}' but this alg is not supported.`\n        )\n      }\n\n      return [this.jwk.jwk.alg] as this['supportedSignatureAlgorithms']\n    }\n\n    return supportedSignatureAlgorithms\n  }\n\n  public get supportedEncryptionKeyAgreementAlgorithms(): KnownJwaKeyAgreementAlgorithm[] {\n    return this.jwk.supportedEncryptionKeyAgreementAlgorithms ?? []\n  }\n\n  /**\n   * key type as defined in [JWA Specification](https://tools.ietf.org/html/rfc7518#section-6.1)\n   */\n  public get kty(): Jwk['jwk']['kty'] {\n    return this.jwk.jwk.kty\n  }\n\n  /**\n   * Get the key id for a public jwk. If the public jwk does not have\n   * a key id, an error will be thrown\n   */\n  public get keyId(): string {\n    if (this.jwk.jwk.kid) return this.jwk.jwk.kid\n\n    throw new KeyManagementError('Unable to determine keyId for jwk')\n  }\n\n  public get hasKeyId(): boolean {\n    return this.jwk.jwk.kid !== undefined\n  }\n\n  public set keyId(keyId: string) {\n    this.jwk.jwk.kid = keyId\n  }\n\n  public get legacyKeyId() {\n    return legacyKeyIdFromPublicJwk(this)\n  }\n\n  public get publicKey(): Jwk['publicKey'] {\n    return this.jwk.publicKey\n  }\n\n  /**\n   * Return the compressed public key. If the key type does not support compressed public keys, it will return null\n   */\n  public get compressedPublicKey(): Jwk['compressedPublicKey'] {\n    return this.jwk.compressedPublicKey\n  }\n\n  public get JwkClass() {\n    return this.jwk.constructor as SupportedPublicJwkClass\n  }\n\n  /**\n   * SHA-256 jwk thumbprint\n   */\n  public getJwkThumbprint(hashAlgorithm: HashName = 'sha-256') {\n    return calculateJwkThumbprint({\n      jwk: this.jwk.jwk,\n      hashAlgorithm: hashAlgorithm,\n    })\n  }\n\n  /**\n   * Get the first signature algorithm to use with this jwk. If the jwk has an `alg` field defined\n   * it will use that alg, and otherwise fall back to the first supported signature algorithm.\n   *\n   * If no algorithm is supported it will throw an error\n   */\n  public get signatureAlgorithm() {\n    const alg = this.supportedSignatureAlgorithms[0]\n    if (!alg) {\n      throw new KeyManagementError(`${this.jwkTypeHumanDescription} has no supported signature algorithms`)\n    }\n\n    return alg as this['supportedSignatureAlgorithms'][number]\n  }\n\n  /**\n   * The `alg` field of the jwk, indicating the algorithm the key is intended to be used with.\n   */\n  public get alg(): string | undefined {\n    return this.jwk.jwk.alg\n  }\n\n  /**\n   * Set the `alg` field of the jwk, indicating the algorithm the key is intended to be used\n   * with. This restricts the jwk to that algorithm (e.g. {@link signatureAlgorithm} will\n   * return the `alg` when defined).\n   *\n   * If the algorithm is not supported by this jwk an error will be thrown.\n   */\n  public set alg(alg: KnownJwaSignatureAlgorithm | KnownJwaKeyAgreementAlgorithm) {\n    const supportedAlgorithms: Array<KnownJwaSignatureAlgorithm | KnownJwaKeyAgreementAlgorithm> = [\n      ...(this.jwk.supportedSignatureAlgorithms ?? []),\n      ...(this.jwk.supportedEncryptionKeyAgreementAlgorithms ?? []),\n    ]\n\n    if (!supportedAlgorithms.includes(alg)) {\n      throw new KeyManagementError(`${this.jwkTypeHumanDescription} does not support alg '${alg}'.`)\n    }\n\n    this.jwk.jwk.alg = alg\n  }\n\n  public assertSignatureAlgorithmSupported(\n    alg: KnownJwaSignatureAlgorithm\n  ): asserts alg is this['supportedSignatureAlgorithms'][number] {\n    if (!this.supportedSignatureAlgorithms.includes(alg)) {\n      throw new KeyManagementError(`${this.jwkTypeHumanDescription} does not support signature alg '${alg}'.`)\n    }\n  }\n\n  public static fromPublicKey<Supported extends SupportedPublicJwk['publicKey']>(publicKey: Supported) {\n    let jwkInstance: SupportedPublicJwk\n\n    if (publicKey.kty === 'RSA') {\n      jwkInstance = RsaPublicJwk.fromPublicKey(publicKey)\n    } else if (publicKey.kty === 'EC') {\n      if (publicKey.crv === 'P-256') {\n        jwkInstance = P256PublicJwk.fromPublicKey(publicKey.publicKey)\n      } else if (publicKey.crv === 'P-384') {\n        jwkInstance = P384PublicJwk.fromPublicKey(publicKey.publicKey)\n      } else if (publicKey.crv === 'P-521') {\n        jwkInstance = P521PublicJwk.fromPublicKey(publicKey.publicKey)\n      } else if (publicKey.crv === 'secp256k1') {\n        jwkInstance = Secp256k1PublicJwk.fromPublicKey(publicKey.publicKey)\n      } else {\n        throw new KeyManagementError(\n          // @ts-expect-error\n          `Unsupported kty '${publicKey.kty}' with crv '${publicKey.crv}' for creating jwk instance based on public key bytes`\n        )\n      }\n    } else if (publicKey.crv === 'X25519') {\n      jwkInstance = X25519PublicJwk.fromPublicKey(publicKey.publicKey)\n    } else if (publicKey.crv === 'Ed25519') {\n      jwkInstance = Ed25519PublicJwk.fromPublicKey(publicKey.publicKey)\n    } else {\n      throw new KeyManagementError(\n        // @ts-expect-error\n        `Unsupported kty '${publicKey.kty}' for creating jwk instance based on public key bytes`\n      )\n    }\n\n    return new PublicJwk(jwkInstance) as PublicJwk<ExtractByPublicKey<SupportedPublicJwk, Supported>>\n  }\n\n  /**\n   * Returns the jwk encoded a Base58 multibase encoded multicodec key\n   */\n  public get fingerprint() {\n    const prefixBytes = VarintEncoder.encode(this.jwk.multicodecPrefix)\n    const prefixedPublicKey = new Uint8Array([...prefixBytes, ...this.jwk.multicodec])\n\n    return `z${TypedArrayEncoder.toBase58(prefixedPublicKey)}`\n  }\n\n  /**\n   * Create a jwk instance based on a Base58 multibase encoded multicodec key\n   */\n  public static fromFingerprint(fingerprint: string) {\n    const { data } = MultiBaseEncoder.decode(fingerprint)\n    const [code, byteLength] = VarintEncoder.decode(data)\n    const publicKey = data.slice(byteLength)\n\n    const PublicJwkClass = SupportedPublicJwks.find((JwkClass) => JwkClass.multicodecPrefix === code)\n    if (!PublicJwkClass) {\n      throw new KeyManagementError(`Unsupported multicodec public key with prefix '${code}'`)\n    }\n\n    const jwk = PublicJwkClass.fromMulticodec(publicKey)\n    return new PublicJwk(jwk)\n  }\n\n  /**\n   * Check whether this PublicJwk instance is of a specific type\n   */\n  public is<\n    Jwk1 extends SupportedPublicJwk,\n    Jwk2 extends SupportedPublicJwk = Jwk1,\n    Jwk3 extends SupportedPublicJwk = Jwk1,\n  >(\n    jwkType1: Constructor<Jwk1>,\n    jwkType2?: Constructor<Jwk2>,\n    jwkType3?: Constructor<Jwk3>\n  ): this is PublicJwk<Jwk1> | PublicJwk<Jwk2> | PublicJwk<Jwk3> {\n    const types = [jwkType1, jwkType2, jwkType3].filter(Boolean) as Constructor<SupportedPublicJwk>[]\n    return types.some((type) => this.jwk.constructor === type)\n  }\n\n  /**\n   * Convert the PublicJwk to another type.\n   *\n   * NOTE: only supported for Ed25519 to X25519 at the moment\n   */\n  public convertTo(\n    type: Jwk extends Ed25519PublicJwk ? typeof X25519PublicJwk : never\n  ): Jwk extends Ed25519PublicJwk ? PublicJwk<X25519PublicJwk> : never {\n    if (!this.is(Ed25519PublicJwk) || type !== X25519PublicJwk) {\n      throw new KeyManagementError('Unsupported key conversion. Only Ed25519 to X25519 is supported.')\n    }\n\n    return PublicJwk.fromPublicJwk(this.jwk.toX25519PublicJwk()) as Jwk extends Ed25519PublicJwk\n      ? PublicJwk<X25519PublicJwk>\n      : never\n  }\n\n  /**\n   * Check whether this jwk instance is the same as another jwk instance.\n   * It does this by comparing the key types and public keys, not other fields\n   * of the JWK such as keyId, use, etc..\n   */\n  public equals(other: PublicJwk) {\n    return asymmetricPublicJwkMatches(this.toJson(), other.toJson())\n  }\n\n  /**\n   * Get human description of a jwk type. This does\n   * not include the (public) key material\n   */\n  public get jwkTypeHumanDescription() {\n    return getJwkHumanDescription(this.toJson())\n  }\n\n  public static supportedPublicJwkClassForSignatureAlgorithm(alg: KnownJwaSignatureAlgorithm): SupportedPublicJwkClass {\n    const supportedPublicJwkClass = SupportedPublicJwks.find((JwkClass) =>\n      JwkClass.supportedSignatureAlgorithms.includes(alg)\n    )\n\n    if (!supportedPublicJwkClass) {\n      throw new CredoError(`Could not determine supported public jwk class for alg '${alg}'`)\n    }\n\n    return supportedPublicJwkClass\n  }\n}\n"],"mappings":"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"}