{"version":3,"file":"CredoWalletWebCrypto.mjs","names":[],"sources":["../../../src/crypto/webcrypto/CredoWalletWebCrypto.ts"],"sourcesContent":["import { p256, p384, p521 } from '@noble/curves/nist.js'\nimport { AsnConvert, AsnParser } from '@peculiar/asn1-schema'\nimport { SubjectPublicKeyInfo } from '@peculiar/asn1-x509'\nimport type { AgentContext } from '../../agent'\nimport { KeyManagementApi, PublicJwk } from '../../modules/kms'\nimport { Hasher } from '../hashes'\nimport { CredoWebCryptoError } from './CredoWebCryptoError'\nimport { CredoWebCryptoKey } from './CredoWebCryptoKey'\nimport {\n  type JsonWebKey,\n  type KeyFormat,\n  type KeyGenAlgorithm,\n  type KeyImportParams,\n  type KeySignParams,\n  type KeyUsage,\n  type KeyVerifyParams,\n  keyParamsToJwaAlgorithm,\n} from './types'\nimport { cryptoKeyAlgorithmToCreateKeyOptions, publicJwkToSpki, spkiToPublicJwk } from './utils'\n\nexport class CredoWalletWebCrypto {\n  private kms: KeyManagementApi\n\n  public constructor(agentContext: AgentContext) {\n    this.kms = agentContext.resolve(KeyManagementApi)\n  }\n\n  public generateRandomValues<T extends ArrayBufferView | null>(array: T): T {\n    if (!array) return array\n\n    return this.kms.randomBytes({ length: array.byteLength }) as unknown as T\n  }\n\n  public async sign(key: CredoWebCryptoKey, message: Uint8Array, algorithm: KeySignParams): Promise<Uint8Array> {\n    const jwaAlgorithm = keyParamsToJwaAlgorithm(algorithm, key)\n\n    const keyId = key.publicJwk.keyId\n    const { signature } = await this.kms.sign({\n      keyId,\n      data: message,\n      algorithm: jwaAlgorithm,\n    })\n\n    return signature\n  }\n\n  public async verify(\n    key: CredoWebCryptoKey,\n    algorithm: KeyVerifyParams,\n    message: Uint8Array,\n    signature: Uint8Array\n  ): Promise<boolean> {\n    const publicKey = key.publicJwk.publicKey\n\n    // TODO: with new KMS api we can now define custom algorithms\n    // such as ES256-SHA384 to support these non-standard JWA combinatiosn\n    // or we can do something like ES256-ph (pre-hashed for more generic)\n    if (algorithm.name === 'ECDSA') {\n      const hashAlg = typeof algorithm.hash === 'string' ? algorithm.hash : algorithm.hash.name\n      if (publicKey.kty === 'EC' && publicKey.crv === 'P-256' && hashAlg !== 'SHA-256') {\n        if (hashAlg !== 'SHA-384' && hashAlg !== 'SHA-512') {\n          throw new CredoWebCryptoError(\n            `Hash Alg: ${hashAlg} is not supported with key type ${publicKey.crv} currently`\n          )\n        }\n\n        return p256.verify(signature, Hasher.hash(message, hashAlg.toLowerCase()), publicKey.publicKey, {\n          // we use a custom hash\n          prehash: false,\n          lowS: false,\n        })\n      }\n      if (publicKey.kty === 'EC' && publicKey.crv === 'P-384' && hashAlg !== 'SHA-384') {\n        if (hashAlg !== 'SHA-256' && hashAlg !== 'SHA-512') {\n          throw new CredoWebCryptoError(\n            `Hash Alg: ${hashAlg} is not supported with key type ${publicKey.crv} currently`\n          )\n        }\n\n        return p384.verify(signature, Hasher.hash(message, hashAlg.toLowerCase()), publicKey.publicKey, {\n          // we use a custom hash\n          prehash: false,\n          lowS: false,\n        })\n      }\n      if (publicKey.kty === 'EC' && publicKey.crv === 'P-521' && hashAlg !== 'SHA-512') {\n        if (hashAlg !== 'SHA-256' && hashAlg !== 'SHA-384') {\n          throw new CredoWebCryptoError(\n            `Hash Alg: ${hashAlg} is not supported with key type ${publicKey.crv} currently`\n          )\n        }\n\n        return p521.verify(signature, Hasher.hash(message, hashAlg.toLowerCase()), publicKey.publicKey, {\n          prehash: false,\n          lowS: false,\n        })\n      }\n    }\n\n    const jwaAlgorithm = keyParamsToJwaAlgorithm(algorithm, key)\n    const { verified } = await this.kms.verify({\n      key: {\n        publicJwk: key.publicJwk.toJson(),\n      },\n      algorithm: jwaAlgorithm,\n      signature,\n      data: message,\n    })\n\n    return verified\n  }\n\n  public async generate(algorithm: KeyGenAlgorithm) {\n    const key = await this.kms.createKey({\n      type: cryptoKeyAlgorithmToCreateKeyOptions(algorithm),\n    })\n\n    return key\n  }\n\n  public async importKey(\n    format: KeyFormat,\n    keyData: Uint8Array | JsonWebKey,\n    algorithm: KeyImportParams,\n    extractable: boolean,\n    keyUsages: Array<KeyUsage>\n  ): Promise<CredoWebCryptoKey> {\n    if (format === 'jwk' && keyData instanceof Uint8Array) {\n      throw new Error('JWK format is only allowed with a jwk as key data')\n    }\n\n    if (format !== 'jwk' && !(keyData instanceof Uint8Array)) {\n      throw new Error('non-jwk formats are only allowed with a uint8array as key data')\n    }\n\n    switch (format.toLowerCase()) {\n      case 'jwk': {\n        const publicJwk = PublicJwk.fromUnknown(keyData)\n        return new CredoWebCryptoKey(publicJwk, algorithm as KeyGenAlgorithm, extractable, 'public', keyUsages)\n      }\n      case 'spki': {\n        const subjectPublicKey = AsnParser.parse(keyData as Uint8Array, SubjectPublicKeyInfo)\n        const publicJwk = spkiToPublicJwk(subjectPublicKey)\n\n        return new CredoWebCryptoKey(publicJwk, algorithm as KeyGenAlgorithm, extractable, 'public', keyUsages)\n      }\n      default:\n        throw new Error(`Unsupported export format: ${format}`)\n    }\n  }\n\n  public async exportKey(format: KeyFormat, key: CredoWebCryptoKey): Promise<Uint8Array | JsonWebKey> {\n    switch (format.toLowerCase()) {\n      case 'jwk': {\n        return key.publicJwk.toJson()\n      }\n      case 'spki': {\n        const publicKeyInfo = publicJwkToSpki(key.publicJwk)\n\n        const derEncoded = AsnConvert.serialize(publicKeyInfo)\n        return new Uint8Array(derEncoded)\n      }\n\n      default:\n        throw new Error(`Unsupported export format: ${format}`)\n    }\n  }\n}\n"],"mappings":"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"}