@credo-ts/node 0.7.0-alpha-20260218222221 → 0.7.0-alpha-20260401141348

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -89,7 +89,7 @@ var NodeKeyManagementService = class {
89
89
  kid: kid ?? randomUUID()
90
90
  };
91
91
  try {
92
- if (privateJwk.kty === "oct") createSecretKey(TypedArrayEncoder.fromBase64(privateJwk.k)).export({ format: "jwk" });
92
+ if (privateJwk.kty === "oct") createSecretKey(TypedArrayEncoder.fromBase64Url(privateJwk.k)).export({ format: "jwk" });
93
93
  else if (privateJwk.kty === "EC") {
94
94
  assertNodeSupportedEcCrv({
95
95
  kty: privateJwk.kty,
@@ -1 +1 @@
1
- {"version":3,"file":"NodeKeyManagementService.mjs","names":[],"sources":["../../src/kms/NodeKeyManagementService.ts"],"sourcesContent":["import { createPrivateKey, createSecretKey, randomBytes, randomUUID } from 'node:crypto'\nimport type { AgentContext } from '@credo-ts/core'\nimport { Kms, TypedArrayEncoder } from '@credo-ts/core'\nimport {\n assertNodeSupportedEcCrv,\n assertNodeSupportedOctAlgorithm,\n assertNodeSupportedOkpCrv,\n createEcKey,\n createOctKey,\n createOkpKey,\n createRsaKey,\n} from './crypto/createKey'\nimport { performDecrypt } from './crypto/decrypt'\nimport { deriveDecryptionKey, deriveEncryptionKey, nodeSupportedKeyAgreementAlgorithms } from './crypto/deriveKey'\nimport { nodeSupportedEncryptionAlgorithms, performEncrypt } from './crypto/encrypt'\nimport { nodeSupportedJwaAlgorithm, performSign } from './crypto/sign'\nimport { performVerify } from './crypto/verify'\nimport type { NodeKeyManagementStorage } from './NodeKeyManagementStorage'\n\nexport class NodeKeyManagementService implements Kms.KeyManagementService {\n public readonly backend = 'node'\n\n #storage: NodeKeyManagementStorage\n\n public constructor(storage: NodeKeyManagementStorage) {\n this.#storage = storage\n }\n\n public isOperationSupported(_agentContext: AgentContext, operation: Kms.KmsOperation): boolean {\n if (operation.operation === 'deleteKey') return true\n if (operation.operation === 'randomBytes') return true\n\n if (operation.operation === 'createKey') {\n // TODO: probably clean to split the assert methods so we don't need try/catch here\n try {\n if (operation.type.kty === 'RSA') {\n return true\n }\n\n if (operation.type.kty === 'EC') {\n assertNodeSupportedEcCrv(operation.type)\n return true\n }\n\n if (operation.type.kty === 'OKP') {\n assertNodeSupportedOkpCrv(operation.type)\n return true\n }\n\n if (operation.type.kty === 'oct') {\n assertNodeSupportedOctAlgorithm(operation.type)\n return true\n }\n } catch {\n return false\n }\n\n return false\n }\n\n if (operation.operation === 'importKey') {\n try {\n if (operation.privateJwk.kty === 'RSA' || operation.privateJwk.kty === 'oct') {\n return true\n }\n\n if (operation.privateJwk.kty === 'EC') {\n assertNodeSupportedEcCrv({ kty: operation.privateJwk.kty, crv: operation.privateJwk.crv })\n return true\n }\n\n if (operation.privateJwk.kty === 'OKP') {\n assertNodeSupportedOkpCrv({ kty: operation.privateJwk.kty, crv: operation.privateJwk.crv })\n return true\n }\n } catch {\n return false\n }\n }\n\n if (operation.operation === 'sign' || operation.operation === 'verify') {\n return nodeSupportedJwaAlgorithm.includes(operation.algorithm)\n }\n\n if (operation.operation === 'encrypt') {\n const isSupportedEncryptionAlgorithm = nodeSupportedEncryptionAlgorithms.includes(\n operation.encryption.algorithm as (typeof nodeSupportedEncryptionAlgorithms)[number]\n )\n if (!isSupportedEncryptionAlgorithm) return false\n if (!operation.keyAgreement) return true\n\n return nodeSupportedKeyAgreementAlgorithms.includes(\n operation.keyAgreement.algorithm as (typeof nodeSupportedKeyAgreementAlgorithms)[number]\n )\n }\n\n if (operation.operation === 'decrypt') {\n const isSupportedEncryptionAlgorithm = nodeSupportedEncryptionAlgorithms.includes(\n operation.decryption.algorithm as (typeof nodeSupportedEncryptionAlgorithms)[number]\n )\n if (!isSupportedEncryptionAlgorithm) return false\n if (!operation.keyAgreement) return true\n\n return nodeSupportedKeyAgreementAlgorithms.includes(\n operation.keyAgreement.algorithm as (typeof nodeSupportedKeyAgreementAlgorithms)[number]\n )\n }\n\n return false\n }\n\n public randomBytes(_agentContext: AgentContext, options: Kms.KmsRandomBytesOptions): Kms.KmsRandomBytesReturn {\n return randomBytes(options.length)\n }\n\n public async getPublicKey(agentContext: AgentContext, keyId: string): Promise<Kms.KmsJwkPublic | null> {\n const privateJwk = await this.#storage.get(agentContext, keyId)\n if (!privateJwk) return null\n\n return Kms.publicJwkFromPrivateJwk(privateJwk)\n }\n\n public async importKey<Jwk extends Kms.KmsJwkPrivate>(\n agentContext: AgentContext,\n options: Kms.KmsImportKeyOptions<Jwk>\n ): Promise<Kms.KmsImportKeyReturn<Jwk>> {\n const { kid } = options.privateJwk\n\n if (kid) await this.assertKeyNotExists(agentContext, kid)\n\n const privateJwk = {\n ...options.privateJwk,\n kid: kid ?? randomUUID(),\n }\n\n try {\n if (privateJwk.kty === 'oct') {\n // Just check if we can create a secret key instance\n createSecretKey(TypedArrayEncoder.fromBase64(privateJwk.k)).export({ format: 'jwk' })\n } else if (privateJwk.kty === 'EC') {\n assertNodeSupportedEcCrv({ kty: privateJwk.kty, crv: privateJwk.crv })\n // This validates the JWK\n createPrivateKey({\n format: 'jwk',\n key: privateJwk,\n })\n } else if (privateJwk.kty === 'OKP') {\n assertNodeSupportedOkpCrv({ kty: privateJwk.kty, crv: privateJwk.crv })\n // This validates the JWK\n createPrivateKey({\n format: 'jwk',\n key: privateJwk,\n })\n } else if (privateJwk.kty === 'RSA') {\n // This validates the JWK\n createPrivateKey({\n format: 'jwk',\n key: privateJwk,\n })\n } else {\n // All kty values supported for now, but can change in the future\n // @ts-expect-error\n throw new Kms.KeyManagementAlgorithmNotSupportedError(`kty '${privateJwk.kty}'`, this.backend)\n }\n\n await this.#storage.set(agentContext, privateJwk.kid, privateJwk)\n const publicJwk = Kms.publicJwkFromPrivateJwk(privateJwk)\n\n return {\n keyId: privateJwk.kid,\n publicJwk: {\n ...publicJwk,\n kid: privateJwk.kid,\n },\n } as Kms.KmsImportKeyReturn<Jwk>\n } catch (error) {\n if (error instanceof Kms.KeyManagementError) throw error\n\n throw new Kms.KeyManagementError('Error importing key', { cause: error })\n }\n }\n\n public async deleteKey(agentContext: AgentContext, options: Kms.KmsDeleteKeyOptions): Promise<boolean> {\n return await this.#storage.delete(agentContext, options.keyId)\n }\n\n public async createKey<Type extends Kms.KmsCreateKeyType>(\n agentContext: AgentContext,\n options: Kms.KmsCreateKeyOptions<Type>\n ): Promise<Kms.KmsCreateKeyReturn<Type>> {\n const { type, keyId } = options\n\n if (keyId) await this.assertKeyNotExists(agentContext, keyId)\n\n try {\n let jwks: { publicJwk: Kms.KmsJwkPublic; privateJwk: Kms.KmsJwkPrivate }\n if (type.kty === 'EC') {\n assertNodeSupportedEcCrv(type)\n jwks = await createEcKey(type)\n } else if (type.kty === 'OKP') {\n assertNodeSupportedOkpCrv(type)\n jwks = await createOkpKey(type)\n } else if (type.kty === 'RSA') {\n jwks = await createRsaKey(type)\n } else if (type.kty === 'oct') {\n assertNodeSupportedOctAlgorithm(type)\n jwks = await createOctKey(type)\n } else {\n // @ts-expect-error\n throw new Kms.KeyManagementAlgorithmNotSupportedError(`kty '${type.kty}'`, this.backend)\n }\n\n jwks.privateJwk.kid = keyId ?? randomUUID()\n jwks.publicJwk.kid = jwks.privateJwk.kid\n\n await this.#storage.set(agentContext, jwks.privateJwk.kid, jwks.privateJwk)\n\n return {\n publicJwk: jwks.publicJwk as Kms.KmsCreateKeyReturn<Type>['publicJwk'],\n keyId: jwks.publicJwk.kid,\n }\n } catch (error) {\n if (error instanceof Kms.KeyManagementError) throw error\n\n throw new Kms.KeyManagementError('Error creating key', { cause: error })\n }\n }\n\n public async sign(agentContext: AgentContext, options: Kms.KmsSignOptions): Promise<Kms.KmsSignReturn> {\n const { keyId, algorithm, data } = options\n\n // 1. Retrieve the key\n const key = await this.getKeyAsserted(agentContext, keyId)\n\n try {\n // 2. Validate alg and use for key\n Kms.assertAllowedSigningAlgForKey(key, algorithm)\n Kms.assertKeyAllowsSign(key)\n\n // 3. Perform the signing operation\n const signature = await performSign(key, algorithm, data)\n\n return {\n signature,\n }\n } catch (error) {\n if (error instanceof Kms.KeyManagementError) throw error\n\n throw new Kms.KeyManagementError('Error signing with key', { cause: error })\n }\n }\n\n public async verify(agentContext: AgentContext, options: Kms.KmsVerifyOptions): Promise<Kms.KmsVerifyReturn> {\n const { algorithm, data, signature } = options\n\n try {\n let key: Exclude<Kms.KmsJwkPublic, Kms.KmsJwkPublicOct> | Kms.KmsJwkPrivate\n if (options.key.keyId) {\n key = await this.getKeyAsserted(agentContext, options.key.keyId)\n } else if (options.key.publicJwk?.kty === 'EC') {\n assertNodeSupportedEcCrv(options.key.publicJwk)\n key = options.key.publicJwk\n } else if (options.key.publicJwk?.kty === 'OKP') {\n assertNodeSupportedOkpCrv(options.key.publicJwk)\n key = options.key.publicJwk\n } else if (options.key.publicJwk?.kty === 'RSA') {\n key = options.key.publicJwk\n } else {\n // @ts-expect-error\n throw new Kms.KeyManagementAlgorithmNotSupportedError(`kty ${options.key.kty}`, this.backend)\n }\n\n // 2. Validate alg and use for key\n Kms.assertAllowedSigningAlgForKey(key, algorithm)\n Kms.assertKeyAllowsVerify(key)\n\n // 3. Perform the verify operation\n const verified = await performVerify(key, algorithm, data, signature)\n if (verified) {\n return {\n verified: true,\n publicJwk: Kms.publicJwkFromPrivateJwk(key),\n }\n }\n\n return {\n verified: false,\n }\n } catch (error) {\n if (error instanceof Kms.KeyManagementError) throw error\n\n throw new Kms.KeyManagementError('Error verifying with key', { cause: error })\n }\n }\n\n public async encrypt(agentContext: AgentContext, options: Kms.KmsEncryptOptions): Promise<Kms.KmsEncryptReturn> {\n const { data, encryption, key } = options\n\n Kms.assertSupportedEncryptionAlgorithm(encryption, nodeSupportedEncryptionAlgorithms, this.backend)\n\n let encryptionKey: Kms.KmsJwkPrivate\n let encryptedKey: Kms.KmsEncryptedKey | undefined\n\n if (key.keyId) {\n encryptionKey = await this.getKeyAsserted(agentContext, key.keyId)\n } else if (key.privateJwk) {\n encryptionKey = key.privateJwk\n } else if (key.keyAgreement) {\n Kms.assertAllowedKeyDerivationAlgForKey(key.keyAgreement.externalPublicJwk, key.keyAgreement.algorithm)\n Kms.assertKeyAllowsDerive(key.keyAgreement.externalPublicJwk)\n Kms.assertSupportedKeyAgreementAlgorithm(key.keyAgreement, nodeSupportedKeyAgreementAlgorithms, this.backend)\n\n const privateJwk = await this.getKeyAsserted(agentContext, key.keyAgreement.keyId)\n Kms.assertJwkAsymmetric(privateJwk, key.keyAgreement.keyId)\n Kms.assertAllowedKeyDerivationAlgForKey(privateJwk, key.keyAgreement.algorithm)\n Kms.assertKeyAllowsDerive(privateJwk)\n Kms.assertAsymmetricJwkKeyTypeMatches(privateJwk, key.keyAgreement.externalPublicJwk)\n\n const { contentEncryptionKey, encryptedContentEncryptionKey } = await deriveEncryptionKey({\n keyAgreement: key.keyAgreement,\n encryption,\n privateJwk,\n })\n\n encryptionKey = contentEncryptionKey\n encryptedKey = encryptedContentEncryptionKey\n } else {\n throw new Kms.KeyManagementError('Unexpected key parameter for encrypt')\n }\n\n if (encryptionKey.kty !== 'oct') {\n throw new Kms.KeyManagementAlgorithmNotSupportedError(\n `kty '${encryptionKey.kty} for content encryption'`,\n this.backend\n )\n }\n\n try {\n // 2. Validate alg and use for key\n Kms.assertAllowedEncryptionAlgForKey(encryptionKey, encryption.algorithm)\n Kms.assertKeyAllowsEncrypt(encryptionKey)\n\n // 3. Perform the encryption operation\n const encrypted = await performEncrypt(encryptionKey, options.encryption, data)\n return {\n ...encrypted,\n encryptedKey,\n }\n } catch (error) {\n if (error instanceof Kms.KeyManagementError) throw error\n\n throw new Kms.KeyManagementError('Error encrypting', { cause: error })\n }\n }\n\n public async decrypt(agentContext: AgentContext, options: Kms.KmsDecryptOptions): Promise<Kms.KmsDecryptReturn> {\n const { decryption, encrypted, key } = options\n\n Kms.assertSupportedEncryptionAlgorithm(decryption, nodeSupportedEncryptionAlgorithms, this.backend)\n\n let decryptionKey: Kms.KmsJwkPrivate\n if (key.keyId) {\n decryptionKey = await this.getKeyAsserted(agentContext, key.keyId)\n } else if (key.privateJwk) {\n decryptionKey = key.privateJwk\n } else if (key.keyAgreement) {\n Kms.assertSupportedKeyAgreementAlgorithm(key.keyAgreement, nodeSupportedKeyAgreementAlgorithms, this.backend)\n Kms.assertAllowedKeyDerivationAlgForKey(key.keyAgreement.externalPublicJwk, key.keyAgreement.algorithm)\n Kms.assertKeyAllowsDerive(key.keyAgreement.externalPublicJwk)\n\n const privateJwk = await this.getKeyAsserted(agentContext, key.keyAgreement.keyId)\n Kms.assertJwkAsymmetric(privateJwk, key.keyAgreement.keyId)\n Kms.assertAllowedKeyDerivationAlgForKey(privateJwk, key.keyAgreement.algorithm)\n Kms.assertKeyAllowsDerive(privateJwk)\n Kms.assertAsymmetricJwkKeyTypeMatches(privateJwk, key.keyAgreement.externalPublicJwk)\n\n const { contentEncryptionKey } = await deriveDecryptionKey({\n keyAgreement: key.keyAgreement,\n decryption,\n privateJwk,\n })\n\n decryptionKey = contentEncryptionKey\n } else {\n throw new Kms.KeyManagementError('Unexpected key parameter for decrypt')\n }\n\n if (decryptionKey.kty !== 'oct') {\n throw new Kms.KeyManagementAlgorithmNotSupportedError(\n `kty '${decryptionKey.kty}' for content encryption`,\n this.backend\n )\n }\n\n try {\n // 2. Validate alg and use for key\n Kms.assertAllowedEncryptionAlgForKey(decryptionKey, decryption.algorithm)\n Kms.assertKeyAllowsEncrypt(decryptionKey)\n\n // 3. Perform the decryption operation\n return await performDecrypt(decryptionKey, decryption, encrypted)\n } catch (error) {\n if (error instanceof Kms.KeyManagementError) throw error\n\n throw new Kms.KeyManagementError('Error decrypting', { cause: error })\n }\n }\n\n private async getKeyAsserted(agentContext: AgentContext, keyId: string) {\n const storageKey = await this.#storage.get(agentContext, keyId)\n if (!storageKey) {\n throw new Kms.KeyManagementKeyNotFoundError(keyId, [this.backend])\n }\n\n return storageKey\n }\n\n private async assertKeyNotExists(agentContext: AgentContext, keyId: string) {\n const storageKey = await this.#storage.get(agentContext, keyId)\n\n if (storageKey) {\n throw new Kms.KeyManagementKeyExistsError(keyId, this.backend)\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"NodeKeyManagementService.mjs","names":[],"sources":["../../src/kms/NodeKeyManagementService.ts"],"sourcesContent":["import { createPrivateKey, createSecretKey, randomBytes, randomUUID } from 'node:crypto'\nimport type { AgentContext } from '@credo-ts/core'\nimport { Kms, TypedArrayEncoder } from '@credo-ts/core'\nimport {\n assertNodeSupportedEcCrv,\n assertNodeSupportedOctAlgorithm,\n assertNodeSupportedOkpCrv,\n createEcKey,\n createOctKey,\n createOkpKey,\n createRsaKey,\n} from './crypto/createKey'\nimport { performDecrypt } from './crypto/decrypt'\nimport { deriveDecryptionKey, deriveEncryptionKey, nodeSupportedKeyAgreementAlgorithms } from './crypto/deriveKey'\nimport { nodeSupportedEncryptionAlgorithms, performEncrypt } from './crypto/encrypt'\nimport { nodeSupportedJwaAlgorithm, performSign } from './crypto/sign'\nimport { performVerify } from './crypto/verify'\nimport type { NodeKeyManagementStorage } from './NodeKeyManagementStorage'\n\nexport class NodeKeyManagementService implements Kms.KeyManagementService {\n public readonly backend = 'node'\n\n #storage: NodeKeyManagementStorage\n\n public constructor(storage: NodeKeyManagementStorage) {\n this.#storage = storage\n }\n\n public isOperationSupported(_agentContext: AgentContext, operation: Kms.KmsOperation): boolean {\n if (operation.operation === 'deleteKey') return true\n if (operation.operation === 'randomBytes') return true\n\n if (operation.operation === 'createKey') {\n // TODO: probably clean to split the assert methods so we don't need try/catch here\n try {\n if (operation.type.kty === 'RSA') {\n return true\n }\n\n if (operation.type.kty === 'EC') {\n assertNodeSupportedEcCrv(operation.type)\n return true\n }\n\n if (operation.type.kty === 'OKP') {\n assertNodeSupportedOkpCrv(operation.type)\n return true\n }\n\n if (operation.type.kty === 'oct') {\n assertNodeSupportedOctAlgorithm(operation.type)\n return true\n }\n } catch {\n return false\n }\n\n return false\n }\n\n if (operation.operation === 'importKey') {\n try {\n if (operation.privateJwk.kty === 'RSA' || operation.privateJwk.kty === 'oct') {\n return true\n }\n\n if (operation.privateJwk.kty === 'EC') {\n assertNodeSupportedEcCrv({ kty: operation.privateJwk.kty, crv: operation.privateJwk.crv })\n return true\n }\n\n if (operation.privateJwk.kty === 'OKP') {\n assertNodeSupportedOkpCrv({ kty: operation.privateJwk.kty, crv: operation.privateJwk.crv })\n return true\n }\n } catch {\n return false\n }\n }\n\n if (operation.operation === 'sign' || operation.operation === 'verify') {\n return nodeSupportedJwaAlgorithm.includes(operation.algorithm)\n }\n\n if (operation.operation === 'encrypt') {\n const isSupportedEncryptionAlgorithm = nodeSupportedEncryptionAlgorithms.includes(\n operation.encryption.algorithm as (typeof nodeSupportedEncryptionAlgorithms)[number]\n )\n if (!isSupportedEncryptionAlgorithm) return false\n if (!operation.keyAgreement) return true\n\n return nodeSupportedKeyAgreementAlgorithms.includes(\n operation.keyAgreement.algorithm as (typeof nodeSupportedKeyAgreementAlgorithms)[number]\n )\n }\n\n if (operation.operation === 'decrypt') {\n const isSupportedEncryptionAlgorithm = nodeSupportedEncryptionAlgorithms.includes(\n operation.decryption.algorithm as (typeof nodeSupportedEncryptionAlgorithms)[number]\n )\n if (!isSupportedEncryptionAlgorithm) return false\n if (!operation.keyAgreement) return true\n\n return nodeSupportedKeyAgreementAlgorithms.includes(\n operation.keyAgreement.algorithm as (typeof nodeSupportedKeyAgreementAlgorithms)[number]\n )\n }\n\n return false\n }\n\n public randomBytes(_agentContext: AgentContext, options: Kms.KmsRandomBytesOptions): Kms.KmsRandomBytesReturn {\n return randomBytes(options.length)\n }\n\n public async getPublicKey(agentContext: AgentContext, keyId: string): Promise<Kms.KmsJwkPublic | null> {\n const privateJwk = await this.#storage.get(agentContext, keyId)\n if (!privateJwk) return null\n\n return Kms.publicJwkFromPrivateJwk(privateJwk)\n }\n\n public async importKey<Jwk extends Kms.KmsJwkPrivate>(\n agentContext: AgentContext,\n options: Kms.KmsImportKeyOptions<Jwk>\n ): Promise<Kms.KmsImportKeyReturn<Jwk>> {\n const { kid } = options.privateJwk\n\n if (kid) await this.assertKeyNotExists(agentContext, kid)\n\n const privateJwk = {\n ...options.privateJwk,\n kid: kid ?? randomUUID(),\n }\n\n try {\n if (privateJwk.kty === 'oct') {\n // Just check if we can create a secret key instance\n createSecretKey(TypedArrayEncoder.fromBase64Url(privateJwk.k)).export({ format: 'jwk' })\n } else if (privateJwk.kty === 'EC') {\n assertNodeSupportedEcCrv({ kty: privateJwk.kty, crv: privateJwk.crv })\n // This validates the JWK\n createPrivateKey({\n format: 'jwk',\n key: privateJwk,\n })\n } else if (privateJwk.kty === 'OKP') {\n assertNodeSupportedOkpCrv({ kty: privateJwk.kty, crv: privateJwk.crv })\n // This validates the JWK\n createPrivateKey({\n format: 'jwk',\n key: privateJwk,\n })\n } else if (privateJwk.kty === 'RSA') {\n // This validates the JWK\n createPrivateKey({\n format: 'jwk',\n key: privateJwk,\n })\n } else {\n // All kty values supported for now, but can change in the future\n // @ts-expect-error\n throw new Kms.KeyManagementAlgorithmNotSupportedError(`kty '${privateJwk.kty}'`, this.backend)\n }\n\n await this.#storage.set(agentContext, privateJwk.kid, privateJwk)\n const publicJwk = Kms.publicJwkFromPrivateJwk(privateJwk)\n\n return {\n keyId: privateJwk.kid,\n publicJwk: {\n ...publicJwk,\n kid: privateJwk.kid,\n },\n } as Kms.KmsImportKeyReturn<Jwk>\n } catch (error) {\n if (error instanceof Kms.KeyManagementError) throw error\n\n throw new Kms.KeyManagementError('Error importing key', { cause: error })\n }\n }\n\n public async deleteKey(agentContext: AgentContext, options: Kms.KmsDeleteKeyOptions): Promise<boolean> {\n return await this.#storage.delete(agentContext, options.keyId)\n }\n\n public async createKey<Type extends Kms.KmsCreateKeyType>(\n agentContext: AgentContext,\n options: Kms.KmsCreateKeyOptions<Type>\n ): Promise<Kms.KmsCreateKeyReturn<Type>> {\n const { type, keyId } = options\n\n if (keyId) await this.assertKeyNotExists(agentContext, keyId)\n\n try {\n let jwks: { publicJwk: Kms.KmsJwkPublic; privateJwk: Kms.KmsJwkPrivate }\n if (type.kty === 'EC') {\n assertNodeSupportedEcCrv(type)\n jwks = await createEcKey(type)\n } else if (type.kty === 'OKP') {\n assertNodeSupportedOkpCrv(type)\n jwks = await createOkpKey(type)\n } else if (type.kty === 'RSA') {\n jwks = await createRsaKey(type)\n } else if (type.kty === 'oct') {\n assertNodeSupportedOctAlgorithm(type)\n jwks = await createOctKey(type)\n } else {\n // @ts-expect-error\n throw new Kms.KeyManagementAlgorithmNotSupportedError(`kty '${type.kty}'`, this.backend)\n }\n\n jwks.privateJwk.kid = keyId ?? randomUUID()\n jwks.publicJwk.kid = jwks.privateJwk.kid\n\n await this.#storage.set(agentContext, jwks.privateJwk.kid, jwks.privateJwk)\n\n return {\n publicJwk: jwks.publicJwk as Kms.KmsCreateKeyReturn<Type>['publicJwk'],\n keyId: jwks.publicJwk.kid,\n }\n } catch (error) {\n if (error instanceof Kms.KeyManagementError) throw error\n\n throw new Kms.KeyManagementError('Error creating key', { cause: error })\n }\n }\n\n public async sign(agentContext: AgentContext, options: Kms.KmsSignOptions): Promise<Kms.KmsSignReturn> {\n const { keyId, algorithm, data } = options\n\n // 1. Retrieve the key\n const key = await this.getKeyAsserted(agentContext, keyId)\n\n try {\n // 2. Validate alg and use for key\n Kms.assertAllowedSigningAlgForKey(key, algorithm)\n Kms.assertKeyAllowsSign(key)\n\n // 3. Perform the signing operation\n const signature = await performSign(key, algorithm, data)\n\n return {\n signature,\n }\n } catch (error) {\n if (error instanceof Kms.KeyManagementError) throw error\n\n throw new Kms.KeyManagementError('Error signing with key', { cause: error })\n }\n }\n\n public async verify(agentContext: AgentContext, options: Kms.KmsVerifyOptions): Promise<Kms.KmsVerifyReturn> {\n const { algorithm, data, signature } = options\n\n try {\n let key: Exclude<Kms.KmsJwkPublic, Kms.KmsJwkPublicOct> | Kms.KmsJwkPrivate\n if (options.key.keyId) {\n key = await this.getKeyAsserted(agentContext, options.key.keyId)\n } else if (options.key.publicJwk?.kty === 'EC') {\n assertNodeSupportedEcCrv(options.key.publicJwk)\n key = options.key.publicJwk\n } else if (options.key.publicJwk?.kty === 'OKP') {\n assertNodeSupportedOkpCrv(options.key.publicJwk)\n key = options.key.publicJwk\n } else if (options.key.publicJwk?.kty === 'RSA') {\n key = options.key.publicJwk\n } else {\n // @ts-expect-error\n throw new Kms.KeyManagementAlgorithmNotSupportedError(`kty ${options.key.kty}`, this.backend)\n }\n\n // 2. Validate alg and use for key\n Kms.assertAllowedSigningAlgForKey(key, algorithm)\n Kms.assertKeyAllowsVerify(key)\n\n // 3. Perform the verify operation\n const verified = await performVerify(key, algorithm, data, signature)\n if (verified) {\n return {\n verified: true,\n publicJwk: Kms.publicJwkFromPrivateJwk(key),\n }\n }\n\n return {\n verified: false,\n }\n } catch (error) {\n if (error instanceof Kms.KeyManagementError) throw error\n\n throw new Kms.KeyManagementError('Error verifying with key', { cause: error })\n }\n }\n\n public async encrypt(agentContext: AgentContext, options: Kms.KmsEncryptOptions): Promise<Kms.KmsEncryptReturn> {\n const { data, encryption, key } = options\n\n Kms.assertSupportedEncryptionAlgorithm(encryption, nodeSupportedEncryptionAlgorithms, this.backend)\n\n let encryptionKey: Kms.KmsJwkPrivate\n let encryptedKey: Kms.KmsEncryptedKey | undefined\n\n if (key.keyId) {\n encryptionKey = await this.getKeyAsserted(agentContext, key.keyId)\n } else if (key.privateJwk) {\n encryptionKey = key.privateJwk\n } else if (key.keyAgreement) {\n Kms.assertAllowedKeyDerivationAlgForKey(key.keyAgreement.externalPublicJwk, key.keyAgreement.algorithm)\n Kms.assertKeyAllowsDerive(key.keyAgreement.externalPublicJwk)\n Kms.assertSupportedKeyAgreementAlgorithm(key.keyAgreement, nodeSupportedKeyAgreementAlgorithms, this.backend)\n\n const privateJwk = await this.getKeyAsserted(agentContext, key.keyAgreement.keyId)\n Kms.assertJwkAsymmetric(privateJwk, key.keyAgreement.keyId)\n Kms.assertAllowedKeyDerivationAlgForKey(privateJwk, key.keyAgreement.algorithm)\n Kms.assertKeyAllowsDerive(privateJwk)\n Kms.assertAsymmetricJwkKeyTypeMatches(privateJwk, key.keyAgreement.externalPublicJwk)\n\n const { contentEncryptionKey, encryptedContentEncryptionKey } = await deriveEncryptionKey({\n keyAgreement: key.keyAgreement,\n encryption,\n privateJwk,\n })\n\n encryptionKey = contentEncryptionKey\n encryptedKey = encryptedContentEncryptionKey\n } else {\n throw new Kms.KeyManagementError('Unexpected key parameter for encrypt')\n }\n\n if (encryptionKey.kty !== 'oct') {\n throw new Kms.KeyManagementAlgorithmNotSupportedError(\n `kty '${encryptionKey.kty} for content encryption'`,\n this.backend\n )\n }\n\n try {\n // 2. Validate alg and use for key\n Kms.assertAllowedEncryptionAlgForKey(encryptionKey, encryption.algorithm)\n Kms.assertKeyAllowsEncrypt(encryptionKey)\n\n // 3. Perform the encryption operation\n const encrypted = await performEncrypt(encryptionKey, options.encryption, data)\n return {\n ...encrypted,\n encryptedKey,\n }\n } catch (error) {\n if (error instanceof Kms.KeyManagementError) throw error\n\n throw new Kms.KeyManagementError('Error encrypting', { cause: error })\n }\n }\n\n public async decrypt(agentContext: AgentContext, options: Kms.KmsDecryptOptions): Promise<Kms.KmsDecryptReturn> {\n const { decryption, encrypted, key } = options\n\n Kms.assertSupportedEncryptionAlgorithm(decryption, nodeSupportedEncryptionAlgorithms, this.backend)\n\n let decryptionKey: Kms.KmsJwkPrivate\n if (key.keyId) {\n decryptionKey = await this.getKeyAsserted(agentContext, key.keyId)\n } else if (key.privateJwk) {\n decryptionKey = key.privateJwk\n } else if (key.keyAgreement) {\n Kms.assertSupportedKeyAgreementAlgorithm(key.keyAgreement, nodeSupportedKeyAgreementAlgorithms, this.backend)\n Kms.assertAllowedKeyDerivationAlgForKey(key.keyAgreement.externalPublicJwk, key.keyAgreement.algorithm)\n Kms.assertKeyAllowsDerive(key.keyAgreement.externalPublicJwk)\n\n const privateJwk = await this.getKeyAsserted(agentContext, key.keyAgreement.keyId)\n Kms.assertJwkAsymmetric(privateJwk, key.keyAgreement.keyId)\n Kms.assertAllowedKeyDerivationAlgForKey(privateJwk, key.keyAgreement.algorithm)\n Kms.assertKeyAllowsDerive(privateJwk)\n Kms.assertAsymmetricJwkKeyTypeMatches(privateJwk, key.keyAgreement.externalPublicJwk)\n\n const { contentEncryptionKey } = await deriveDecryptionKey({\n keyAgreement: key.keyAgreement,\n decryption,\n privateJwk,\n })\n\n decryptionKey = contentEncryptionKey\n } else {\n throw new Kms.KeyManagementError('Unexpected key parameter for decrypt')\n }\n\n if (decryptionKey.kty !== 'oct') {\n throw new Kms.KeyManagementAlgorithmNotSupportedError(\n `kty '${decryptionKey.kty}' for content encryption`,\n this.backend\n )\n }\n\n try {\n // 2. Validate alg and use for key\n Kms.assertAllowedEncryptionAlgForKey(decryptionKey, decryption.algorithm)\n Kms.assertKeyAllowsEncrypt(decryptionKey)\n\n // 3. Perform the decryption operation\n return await performDecrypt(decryptionKey, decryption, encrypted)\n } catch (error) {\n if (error instanceof Kms.KeyManagementError) throw error\n\n throw new Kms.KeyManagementError('Error decrypting', { cause: error })\n }\n }\n\n private async getKeyAsserted(agentContext: AgentContext, keyId: string) {\n const storageKey = await this.#storage.get(agentContext, keyId)\n if (!storageKey) {\n throw new Kms.KeyManagementKeyNotFoundError(keyId, [this.backend])\n }\n\n return storageKey\n }\n\n private async assertKeyNotExists(agentContext: AgentContext, keyId: string) {\n const storageKey = await this.#storage.get(agentContext, keyId)\n\n if (storageKey) {\n throw new Kms.KeyManagementKeyExistsError(keyId, this.backend)\n }\n }\n}\n"],"mappings":"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"}
@@ -1,11 +1,11 @@
1
1
  import { performSign } from "./sign.mjs";
2
- import { Kms } from "@credo-ts/core";
2
+ import { Kms, TypedArrayEncoder } from "@credo-ts/core";
3
3
  import { createDecipheriv, createSecretKey, timingSafeEqual } from "node:crypto";
4
4
  import { Buffer } from "node:buffer";
5
5
 
6
6
  //#region src/kms/crypto/decrypt.ts
7
7
  async function performDecrypt(key, dataDecryption, encrypted) {
8
- const secretKeyBytes = Buffer.from(key.k, "base64url");
8
+ const secretKeyBytes = TypedArrayEncoder.fromBase64Url(key.k);
9
9
  const nodeKey = createSecretKey(secretKeyBytes);
10
10
  if (dataDecryption.algorithm === "A128CBC" || dataDecryption.algorithm === "A256CBC") {
11
11
  const decipher = createDecipheriv(dataDecryption.algorithm === "A128CBC" ? "aes-128-cbc" : "aes-256-cbc", nodeKey, dataDecryption.iv);
@@ -46,11 +46,10 @@ async function performDecrypt(key, dataDecryption, encrypted) {
46
46
  encrypted,
47
47
  al
48
48
  ]);
49
- const hmac = await performSign({
49
+ if (!timingSafeEqual((await performSign({
50
50
  kty: "oct",
51
- k: macKey.toString("base64url")
52
- }, algSettings.hmacAlg, macData);
53
- if (!timingSafeEqual(Buffer.from(hmac).subarray(0, algSettings.keySize), dataDecryption.tag)) throw new Kms.KeyManagementError(`Error during verification of authentication tag with decryption algorithm '${dataDecryption.algorithm}'`);
51
+ k: TypedArrayEncoder.toBase64Url(macKey)
52
+ }, algSettings.hmacAlg, macData)).subarray(0, algSettings.keySize), dataDecryption.tag)) throw new Kms.KeyManagementError(`Error during verification of authentication tag with decryption algorithm '${dataDecryption.algorithm}'`);
54
53
  const decipher = createDecipheriv(algSettings.cbcAlg, encKey, dataDecryption.iv);
55
54
  return { data: Buffer.concat([decipher.update(encrypted), decipher.final()]) };
56
55
  }
@@ -1 +1 @@
1
- {"version":3,"file":"decrypt.mjs","names":[],"sources":["../../../src/kms/crypto/decrypt.ts"],"sourcesContent":["import { Buffer } from 'node:buffer'\nimport type { DecipherGCM } from 'node:crypto'\nimport { createDecipheriv, createSecretKey, timingSafeEqual } from 'node:crypto'\nimport { type AnyUint8Array, Kms, type Uint8ArrayBuffer } from '@credo-ts/core'\n\nimport { performSign } from './sign'\n\nexport async function performDecrypt(\n key: Kms.KmsJwkPrivateOct,\n dataDecryption: Kms.KmsDecryptDataDecryption,\n encrypted: AnyUint8Array\n): Promise<{ data: Uint8ArrayBuffer }> {\n const secretKeyBytes = Buffer.from(key.k, 'base64url')\n const nodeKey = createSecretKey(secretKeyBytes)\n\n // Create decipher with key and IV\n if (dataDecryption.algorithm === 'A128CBC' || dataDecryption.algorithm === 'A256CBC') {\n const nodeAlgorithm = dataDecryption.algorithm === 'A128CBC' ? 'aes-128-cbc' : 'aes-256-cbc'\n\n const decipher = createDecipheriv(nodeAlgorithm, nodeKey, dataDecryption.iv)\n\n // Get decrypted data\n const data = Buffer.concat([decipher.update(encrypted), decipher.final()])\n\n return { data }\n }\n if (\n dataDecryption.algorithm === 'A128GCM' ||\n dataDecryption.algorithm === 'A192GCM' ||\n dataDecryption.algorithm === 'A256GCM'\n ) {\n const nodeAlgorithm =\n dataDecryption.algorithm === 'A128GCM'\n ? 'aes-128-gcm'\n : dataDecryption.algorithm === 'A192GCM'\n ? 'aes-192-gcm'\n : 'aes-256-gcm'\n\n const decipher = createDecipheriv(nodeAlgorithm, nodeKey, dataDecryption.iv)\n\n // Set auth tag before decryption for authenticated modes\n decipher.setAuthTag(dataDecryption.tag)\n\n // If AAD was used during encryption, it must be provided for decryption\n if (dataDecryption.aad) {\n decipher.setAAD(dataDecryption.aad)\n }\n\n // Get decrypted data\n const data = Buffer.concat([decipher.update(encrypted), decipher.final()])\n\n return { data }\n }\n if (\n dataDecryption.algorithm === 'A128CBC-HS256' ||\n dataDecryption.algorithm === 'A192CBC-HS384' ||\n dataDecryption.algorithm === 'A256CBC-HS512'\n ) {\n // Map algorithms to their corresponding CBC and HMAC settings\n const algSettings = {\n 'A128CBC-HS256': { cbcAlg: 'aes-128-cbc', hmacAlg: 'HS256', keySize: 16 } as const,\n 'A192CBC-HS384': { cbcAlg: 'aes-192-cbc', hmacAlg: 'HS384', keySize: 24 } as const,\n 'A256CBC-HS512': { cbcAlg: 'aes-256-cbc', hmacAlg: 'HS512', keySize: 32 } as const,\n }[dataDecryption.algorithm]\n\n // Split the input key into MAC and ENC keys (MAC key is first half, ENC key is second half)\n const macKey = secretKeyBytes.subarray(0, algSettings.keySize)\n const encKey = createSecretKey(secretKeyBytes.subarray(algSettings.keySize))\n\n // Calculate authentication tag for verification\n // AL (Associated Length) is 64-bit big-endian length of AAD in bits\n const al = Buffer.alloc(8)\n const aadLength = dataDecryption.aad ? dataDecryption.aad.length * 8 : 0\n al.writeBigUInt64BE(BigInt(aadLength))\n\n // Create concatenated buffer for MAC verification\n const macData = Buffer.concat([dataDecryption.aad ?? Buffer.alloc(0), dataDecryption.iv, encrypted, al])\n\n // Verify the authentication tag\n const hmac = await performSign({ kty: 'oct', k: macKey.toString('base64url') }, algSettings.hmacAlg, macData)\n const calculatedTag = Buffer.from(hmac).subarray(0, algSettings.keySize) // Truncate to appropriate size\n\n if (!timingSafeEqual(calculatedTag, dataDecryption.tag)) {\n throw new Kms.KeyManagementError(\n `Error during verification of authentication tag with decryption algorithm '${dataDecryption.algorithm}'`\n )\n }\n\n // After verification, perform decryption\n const decipher = createDecipheriv(algSettings.cbcAlg, encKey, dataDecryption.iv)\n const data = Buffer.concat([decipher.update(encrypted), decipher.final()])\n\n return { data }\n }\n if (dataDecryption.algorithm === 'C20P') {\n const decipher: DecipherGCM = createDecipheriv('chacha20-poly1305', nodeKey, dataDecryption.iv, {\n authTagLength: 16,\n })\n\n // Set auth tag before decryption\n decipher.setAuthTag(dataDecryption.tag)\n\n // If AAD was used during encryption, it must be provided for decryption\n if (dataDecryption.aad) {\n decipher.setAAD(dataDecryption.aad)\n }\n\n // Get decrypted data\n const data = Buffer.concat([decipher.update(encrypted), decipher.final()])\n\n return { data }\n }\n\n throw new Kms.KeyManagementAlgorithmNotSupportedError(\n `JWA content decryption algorithm '${dataDecryption.algorithm}'`,\n 'node'\n )\n}\n"],"mappings":";;;;;;AAOA,eAAsB,eACpB,KACA,gBACA,WACqC;CACrC,MAAM,iBAAiB,OAAO,KAAK,IAAI,GAAG,YAAY;CACtD,MAAM,UAAU,gBAAgB,eAAe;AAG/C,KAAI,eAAe,cAAc,aAAa,eAAe,cAAc,WAAW;EAGpF,MAAM,WAAW,iBAFK,eAAe,cAAc,YAAY,gBAAgB,eAE9B,SAAS,eAAe,GAAG;AAK5E,SAAO,EAAE,MAFI,OAAO,OAAO,CAAC,SAAS,OAAO,UAAU,EAAE,SAAS,OAAO,CAAC,CAAC,EAE3D;;AAEjB,KACE,eAAe,cAAc,aAC7B,eAAe,cAAc,aAC7B,eAAe,cAAc,WAC7B;EAQA,MAAM,WAAW,iBANf,eAAe,cAAc,YACzB,gBACA,eAAe,cAAc,YAC3B,gBACA,eAEyC,SAAS,eAAe,GAAG;AAG5E,WAAS,WAAW,eAAe,IAAI;AAGvC,MAAI,eAAe,IACjB,UAAS,OAAO,eAAe,IAAI;AAMrC,SAAO,EAAE,MAFI,OAAO,OAAO,CAAC,SAAS,OAAO,UAAU,EAAE,SAAS,OAAO,CAAC,CAAC,EAE3D;;AAEjB,KACE,eAAe,cAAc,mBAC7B,eAAe,cAAc,mBAC7B,eAAe,cAAc,iBAC7B;EAEA,MAAM,cAAc;GAClB,iBAAiB;IAAE,QAAQ;IAAe,SAAS;IAAS,SAAS;IAAI;GACzE,iBAAiB;IAAE,QAAQ;IAAe,SAAS;IAAS,SAAS;IAAI;GACzE,iBAAiB;IAAE,QAAQ;IAAe,SAAS;IAAS,SAAS;IAAI;GAC1E,CAAC,eAAe;EAGjB,MAAM,SAAS,eAAe,SAAS,GAAG,YAAY,QAAQ;EAC9D,MAAM,SAAS,gBAAgB,eAAe,SAAS,YAAY,QAAQ,CAAC;EAI5E,MAAM,KAAK,OAAO,MAAM,EAAE;EAC1B,MAAM,YAAY,eAAe,MAAM,eAAe,IAAI,SAAS,IAAI;AACvE,KAAG,iBAAiB,OAAO,UAAU,CAAC;EAGtC,MAAM,UAAU,OAAO,OAAO;GAAC,eAAe,OAAO,OAAO,MAAM,EAAE;GAAE,eAAe;GAAI;GAAW;GAAG,CAAC;EAGxG,MAAM,OAAO,MAAM,YAAY;GAAE,KAAK;GAAO,GAAG,OAAO,SAAS,YAAY;GAAE,EAAE,YAAY,SAAS,QAAQ;AAG7G,MAAI,CAAC,gBAFiB,OAAO,KAAK,KAAK,CAAC,SAAS,GAAG,YAAY,QAAQ,EAEpC,eAAe,IAAI,CACrD,OAAM,IAAI,IAAI,mBACZ,8EAA8E,eAAe,UAAU,GACxG;EAIH,MAAM,WAAW,iBAAiB,YAAY,QAAQ,QAAQ,eAAe,GAAG;AAGhF,SAAO,EAAE,MAFI,OAAO,OAAO,CAAC,SAAS,OAAO,UAAU,EAAE,SAAS,OAAO,CAAC,CAAC,EAE3D;;AAEjB,KAAI,eAAe,cAAc,QAAQ;EACvC,MAAM,WAAwB,iBAAiB,qBAAqB,SAAS,eAAe,IAAI,EAC9F,eAAe,IAChB,CAAC;AAGF,WAAS,WAAW,eAAe,IAAI;AAGvC,MAAI,eAAe,IACjB,UAAS,OAAO,eAAe,IAAI;AAMrC,SAAO,EAAE,MAFI,OAAO,OAAO,CAAC,SAAS,OAAO,UAAU,EAAE,SAAS,OAAO,CAAC,CAAC,EAE3D;;AAGjB,OAAM,IAAI,IAAI,wCACZ,qCAAqC,eAAe,UAAU,IAC9D,OACD"}
1
+ {"version":3,"file":"decrypt.mjs","names":[],"sources":["../../../src/kms/crypto/decrypt.ts"],"sourcesContent":["import { Buffer } from 'node:buffer'\nimport type { DecipherGCM } from 'node:crypto'\nimport { createDecipheriv, createSecretKey, timingSafeEqual } from 'node:crypto'\nimport { Kms, TypedArrayEncoder } from '@credo-ts/core'\nimport { performSign } from './sign'\n\nexport async function performDecrypt(\n key: Kms.KmsJwkPrivateOct,\n dataDecryption: Kms.KmsDecryptDataDecryption,\n encrypted: Uint8Array\n): Promise<{ data: Uint8Array }> {\n const secretKeyBytes = TypedArrayEncoder.fromBase64Url(key.k)\n const nodeKey = createSecretKey(secretKeyBytes)\n\n // Create decipher with key and IV\n if (dataDecryption.algorithm === 'A128CBC' || dataDecryption.algorithm === 'A256CBC') {\n const nodeAlgorithm = dataDecryption.algorithm === 'A128CBC' ? 'aes-128-cbc' : 'aes-256-cbc'\n\n const decipher = createDecipheriv(nodeAlgorithm, nodeKey, dataDecryption.iv)\n\n // Get decrypted data\n const data = Buffer.concat([decipher.update(encrypted), decipher.final()])\n\n return { data }\n }\n if (\n dataDecryption.algorithm === 'A128GCM' ||\n dataDecryption.algorithm === 'A192GCM' ||\n dataDecryption.algorithm === 'A256GCM'\n ) {\n const nodeAlgorithm =\n dataDecryption.algorithm === 'A128GCM'\n ? 'aes-128-gcm'\n : dataDecryption.algorithm === 'A192GCM'\n ? 'aes-192-gcm'\n : 'aes-256-gcm'\n\n const decipher = createDecipheriv(nodeAlgorithm, nodeKey, dataDecryption.iv)\n\n // Set auth tag before decryption for authenticated modes\n decipher.setAuthTag(dataDecryption.tag)\n\n // If AAD was used during encryption, it must be provided for decryption\n if (dataDecryption.aad) {\n decipher.setAAD(dataDecryption.aad)\n }\n\n // Get decrypted data\n const data = Buffer.concat([decipher.update(encrypted), decipher.final()])\n\n return { data }\n }\n if (\n dataDecryption.algorithm === 'A128CBC-HS256' ||\n dataDecryption.algorithm === 'A192CBC-HS384' ||\n dataDecryption.algorithm === 'A256CBC-HS512'\n ) {\n // Map algorithms to their corresponding CBC and HMAC settings\n const algSettings = {\n 'A128CBC-HS256': { cbcAlg: 'aes-128-cbc', hmacAlg: 'HS256', keySize: 16 } as const,\n 'A192CBC-HS384': { cbcAlg: 'aes-192-cbc', hmacAlg: 'HS384', keySize: 24 } as const,\n 'A256CBC-HS512': { cbcAlg: 'aes-256-cbc', hmacAlg: 'HS512', keySize: 32 } as const,\n }[dataDecryption.algorithm]\n\n // Split the input key into MAC and ENC keys (MAC key is first half, ENC key is second half)\n const macKey = secretKeyBytes.subarray(0, algSettings.keySize)\n const encKey = createSecretKey(secretKeyBytes.subarray(algSettings.keySize))\n\n // Calculate authentication tag for verification\n // AL (Associated Length) is 64-bit big-endian length of AAD in bits\n const al = Buffer.alloc(8)\n const aadLength = dataDecryption.aad ? dataDecryption.aad.length * 8 : 0\n al.writeBigUInt64BE(BigInt(aadLength))\n\n // Create concatenated buffer for MAC verification\n const macData = Buffer.concat([dataDecryption.aad ?? Buffer.alloc(0), dataDecryption.iv, encrypted, al])\n\n // Verify the authentication tag\n const hmac = await performSign(\n { kty: 'oct', k: TypedArrayEncoder.toBase64Url(macKey) },\n algSettings.hmacAlg,\n macData\n )\n const calculatedTag = hmac.subarray(0, algSettings.keySize) // Truncate to appropriate size\n\n if (!timingSafeEqual(calculatedTag, dataDecryption.tag)) {\n throw new Kms.KeyManagementError(\n `Error during verification of authentication tag with decryption algorithm '${dataDecryption.algorithm}'`\n )\n }\n\n // After verification, perform decryption\n const decipher = createDecipheriv(algSettings.cbcAlg, encKey, dataDecryption.iv)\n const data = Buffer.concat([decipher.update(encrypted), decipher.final()])\n\n return { data }\n }\n if (dataDecryption.algorithm === 'C20P') {\n const decipher: DecipherGCM = createDecipheriv('chacha20-poly1305', nodeKey, dataDecryption.iv, {\n authTagLength: 16,\n })\n\n // Set auth tag before decryption\n decipher.setAuthTag(dataDecryption.tag)\n\n // If AAD was used during encryption, it must be provided for decryption\n if (dataDecryption.aad) {\n decipher.setAAD(dataDecryption.aad)\n }\n\n // Get decrypted data\n const data = Buffer.concat([decipher.update(encrypted), decipher.final()])\n\n return { data }\n }\n\n throw new Kms.KeyManagementAlgorithmNotSupportedError(\n `JWA content decryption algorithm '${dataDecryption.algorithm}'`,\n 'node'\n )\n}\n"],"mappings":";;;;;;AAMA,eAAsB,eACpB,KACA,gBACA,WAC+B;CAC/B,MAAM,iBAAiB,kBAAkB,cAAc,IAAI,EAAE;CAC7D,MAAM,UAAU,gBAAgB,eAAe;AAG/C,KAAI,eAAe,cAAc,aAAa,eAAe,cAAc,WAAW;EAGpF,MAAM,WAAW,iBAFK,eAAe,cAAc,YAAY,gBAAgB,eAE9B,SAAS,eAAe,GAAG;AAK5E,SAAO,EAAE,MAFI,OAAO,OAAO,CAAC,SAAS,OAAO,UAAU,EAAE,SAAS,OAAO,CAAC,CAAC,EAE3D;;AAEjB,KACE,eAAe,cAAc,aAC7B,eAAe,cAAc,aAC7B,eAAe,cAAc,WAC7B;EAQA,MAAM,WAAW,iBANf,eAAe,cAAc,YACzB,gBACA,eAAe,cAAc,YAC3B,gBACA,eAEyC,SAAS,eAAe,GAAG;AAG5E,WAAS,WAAW,eAAe,IAAI;AAGvC,MAAI,eAAe,IACjB,UAAS,OAAO,eAAe,IAAI;AAMrC,SAAO,EAAE,MAFI,OAAO,OAAO,CAAC,SAAS,OAAO,UAAU,EAAE,SAAS,OAAO,CAAC,CAAC,EAE3D;;AAEjB,KACE,eAAe,cAAc,mBAC7B,eAAe,cAAc,mBAC7B,eAAe,cAAc,iBAC7B;EAEA,MAAM,cAAc;GAClB,iBAAiB;IAAE,QAAQ;IAAe,SAAS;IAAS,SAAS;IAAI;GACzE,iBAAiB;IAAE,QAAQ;IAAe,SAAS;IAAS,SAAS;IAAI;GACzE,iBAAiB;IAAE,QAAQ;IAAe,SAAS;IAAS,SAAS;IAAI;GAC1E,CAAC,eAAe;EAGjB,MAAM,SAAS,eAAe,SAAS,GAAG,YAAY,QAAQ;EAC9D,MAAM,SAAS,gBAAgB,eAAe,SAAS,YAAY,QAAQ,CAAC;EAI5E,MAAM,KAAK,OAAO,MAAM,EAAE;EAC1B,MAAM,YAAY,eAAe,MAAM,eAAe,IAAI,SAAS,IAAI;AACvE,KAAG,iBAAiB,OAAO,UAAU,CAAC;EAGtC,MAAM,UAAU,OAAO,OAAO;GAAC,eAAe,OAAO,OAAO,MAAM,EAAE;GAAE,eAAe;GAAI;GAAW;GAAG,CAAC;AAUxG,MAAI,CAAC,iBAPQ,MAAM,YACjB;GAAE,KAAK;GAAO,GAAG,kBAAkB,YAAY,OAAO;GAAE,EACxD,YAAY,SACZ,QACD,EAC0B,SAAS,GAAG,YAAY,QAAQ,EAEvB,eAAe,IAAI,CACrD,OAAM,IAAI,IAAI,mBACZ,8EAA8E,eAAe,UAAU,GACxG;EAIH,MAAM,WAAW,iBAAiB,YAAY,QAAQ,QAAQ,eAAe,GAAG;AAGhF,SAAO,EAAE,MAFI,OAAO,OAAO,CAAC,SAAS,OAAO,UAAU,EAAE,SAAS,OAAO,CAAC,CAAC,EAE3D;;AAEjB,KAAI,eAAe,cAAc,QAAQ;EACvC,MAAM,WAAwB,iBAAiB,qBAAqB,SAAS,eAAe,IAAI,EAC9F,eAAe,IAChB,CAAC;AAGF,WAAS,WAAW,eAAe,IAAI;AAGvC,MAAI,eAAe,IACjB,UAAS,OAAO,eAAe,IAAI;AAMrC,SAAO,EAAE,MAFI,OAAO,OAAO,CAAC,SAAS,OAAO,UAAU,EAAE,SAAS,OAAO,CAAC,CAAC,EAE3D;;AAGjB,OAAM,IAAI,IAAI,wCACZ,qCAAqC,eAAe,UAAU,IAC9D,OACD"}
@@ -35,14 +35,14 @@ async function deriveEncryptionKey(options) {
35
35
  k: derivedKeyBytes.toString("base64url")
36
36
  } };
37
37
  const derivedKey = await subtle.importKey("raw", derivedKeyBytes, "AES-KW", true, ["wrapKey"]);
38
- const contentEncryptionKeyBytes = Buffer.from(getRandomValues(new Uint8Array(mapContentEncryptionAlgorithmToKeyLength(encryption.algorithm) >> 3)));
38
+ const contentEncryptionKeyBytes = getRandomValues(new Uint8Array(mapContentEncryptionAlgorithmToKeyLength(encryption.algorithm) >> 3));
39
39
  const contentEncryptionKey = await subtle.importKey("raw", contentEncryptionKeyBytes, "AES-KW", true, ["wrapKey"]);
40
40
  const encryptedContentEncryptionKey = await subtle.wrapKey("raw", contentEncryptionKey, derivedKey, "AES-KW");
41
41
  return {
42
- encryptedContentEncryptionKey: { encrypted: Buffer.from(encryptedContentEncryptionKey) },
42
+ encryptedContentEncryptionKey: { encrypted: new Uint8Array(encryptedContentEncryptionKey) },
43
43
  contentEncryptionKey: {
44
44
  kty: "oct",
45
- k: contentEncryptionKeyBytes.toString("base64url")
45
+ k: TypedArrayEncoder.toBase64Url(contentEncryptionKeyBytes)
46
46
  }
47
47
  };
48
48
  }
@@ -76,12 +76,12 @@ async function deriveKeyEcdhEs(options) {
76
76
  const nodeEcdhCurveName = mapCrvToNodeEcdhCurveName(options.privateJwk.crv);
77
77
  const nodeConcatKdfHash = mapCrvToHashLength(options.publicJwk.crv);
78
78
  const ecdh = createECDH(nodeEcdhCurveName);
79
- ecdh.setPrivateKey(TypedArrayEncoder.fromBase64(options.privateJwk.d));
79
+ ecdh.setPrivateKey(TypedArrayEncoder.fromBase64Url(options.privateJwk.d));
80
80
  const publicKey = Kms.PublicJwk.fromPublicJwk(options.publicJwk).publicKey;
81
81
  if (publicKey.kty === "RSA") throw new Kms.KeyManagementError("Key type RSA is not supported for ECDH-ES");
82
82
  const sharedSecret = ecdh.computeSecret(publicKey.publicKey);
83
- const algorithmData = Buffer.from(options.usageAlgorithm);
84
- const algorithmID = Buffer.concat([numberTo4ByteUint8Array(algorithmData.length), algorithmData]);
83
+ const algorithmData = TypedArrayEncoder.fromUtf8String(options.usageAlgorithm);
84
+ const algorithmID = TypedArrayEncoder.concat([numberTo4ByteUint8Array(algorithmData.length), algorithmData]);
85
85
  const apu = options.apu || Buffer.alloc(0);
86
86
  const partyUInfo = Buffer.concat([numberTo4ByteUint8Array(apu.length), apu]);
87
87
  const apv = options.apv || Buffer.alloc(0);
@@ -1 +1 @@
1
- {"version":3,"file":"deriveKey.mjs","names":[],"sources":["../../../src/kms/crypto/deriveKey.ts"],"sourcesContent":["import { Buffer } from 'node:buffer'\nimport { createECDH, createHash, getRandomValues, subtle } from 'node:crypto'\nimport { type AnyUint8Array, Kms, TypedArrayEncoder } from '@credo-ts/core'\nimport type { NodeKmsSupportedEcCrvs } from './createKey'\n\nconst nodeSupportedEcdhKeyDerivationEcCrv = [\n 'P-256',\n 'P-384',\n 'P-521',\n 'secp256k1',\n] as const satisfies NodeKmsSupportedEcCrvs[]\n\nexport const nodeSupportedKeyAgreementAlgorithms = [\n 'ECDH-ES',\n 'ECDH-ES+A128KW',\n 'ECDH-ES+A192KW',\n 'ECDH-ES+A256KW',\n] satisfies Kms.KnownJwaKeyAgreementAlgorithm[]\n\nfunction assertNodeSupportedEcdhKeyDerivationCrv<Jwk extends Kms.KmsJwkPrivateAsymmetric | Kms.KmsJwkPublicAsymmetric>(\n jwk: Jwk\n): asserts jwk is Jwk & { kty: 'OKP' | 'EC'; crv: (typeof nodeSupportedEcdhKeyDerivationEcCrv)[number] | 'X25519' } {\n if (\n (jwk.kty === 'OKP' && jwk.crv !== 'X25519') ||\n (jwk.kty === 'EC' && !(nodeSupportedEcdhKeyDerivationEcCrv as string[]).includes(jwk.crv))\n ) {\n throw new Kms.KeyManagementAlgorithmNotSupportedError(\n `key derivation with crv '${jwk.crv}' for kty '${jwk.kty}'`,\n 'node'\n )\n }\n}\n\ntype NodeSupportedKeyAgreementDecryptOptions = Kms.KmsKeyAgreementDecryptOptions & {\n algorithm: (typeof nodeSupportedKeyAgreementAlgorithms)[number]\n}\ntype NodeSupportedKeyAgreementEncryptOptions = Kms.KmsKeyAgreementEncryptOptions & {\n algorithm: (typeof nodeSupportedKeyAgreementAlgorithms)[number]\n}\n\nexport async function deriveEncryptionKey(options: {\n keyAgreement: NodeSupportedKeyAgreementEncryptOptions\n privateJwk: Kms.KmsJwkPrivateAsymmetric\n encryption: Kms.KmsEncryptDataEncryption\n}) {\n const { keyAgreement, encryption, privateJwk } = options\n\n assertNodeSupportedEcdhKeyDerivationCrv(keyAgreement.externalPublicJwk)\n assertNodeSupportedEcdhKeyDerivationCrv(privateJwk)\n\n const keyLength =\n keyAgreement.algorithm === 'ECDH-ES'\n ? mapContentEncryptionAlgorithmToKeyLength(encryption.algorithm)\n : keyAgreement.algorithm === 'ECDH-ES+A128KW'\n ? 128\n : keyAgreement.algorithm === 'ECDH-ES+A192KW'\n ? 192\n : 256\n\n const derivedKeyBytes = await deriveKeyEcdhEs({\n keyLength,\n usageAlgorithm: keyAgreement.algorithm === 'ECDH-ES' ? encryption.algorithm : keyAgreement.algorithm,\n privateJwk,\n publicJwk: keyAgreement.externalPublicJwk,\n apu: keyAgreement.apu,\n apv: keyAgreement.apv,\n })\n\n if (keyAgreement.algorithm === 'ECDH-ES') {\n return {\n // TODO: will be more efficient to return node key instance\n contentEncryptionKey: {\n kty: 'oct',\n k: derivedKeyBytes.toString('base64url'),\n } as const,\n }\n }\n\n // Key wrapping\n const derivedKey = await subtle.importKey('raw', derivedKeyBytes, 'AES-KW', true, ['wrapKey'])\n const contentEncryptionKeyBytes = Buffer.from(\n getRandomValues(new Uint8Array(mapContentEncryptionAlgorithmToKeyLength(encryption.algorithm) >> 3))\n )\n const contentEncryptionKey = await subtle.importKey('raw', contentEncryptionKeyBytes, 'AES-KW', true, ['wrapKey'])\n const encryptedContentEncryptionKey = await subtle.wrapKey('raw', contentEncryptionKey, derivedKey, 'AES-KW')\n\n return {\n encryptedContentEncryptionKey: {\n encrypted: Buffer.from(encryptedContentEncryptionKey),\n } satisfies Kms.KmsEncryptedKey,\n contentEncryptionKey: {\n kty: 'oct',\n k: contentEncryptionKeyBytes.toString('base64url'),\n } as const,\n }\n}\n\nexport async function deriveDecryptionKey(options: {\n keyAgreement: NodeSupportedKeyAgreementDecryptOptions\n privateJwk: Kms.KmsJwkPrivateAsymmetric\n decryption: Kms.KmsDecryptDataDecryption\n}) {\n const { keyAgreement, decryption, privateJwk } = options\n\n assertNodeSupportedEcdhKeyDerivationCrv(keyAgreement.externalPublicJwk)\n assertNodeSupportedEcdhKeyDerivationCrv(privateJwk)\n\n const keyLength =\n keyAgreement.algorithm === 'ECDH-ES'\n ? mapContentEncryptionAlgorithmToKeyLength(decryption.algorithm)\n : keyAgreement.algorithm === 'ECDH-ES+A128KW'\n ? 128\n : keyAgreement.algorithm === 'ECDH-ES+A192KW'\n ? 192\n : 256\n\n const derivedKeyBytes = await deriveKeyEcdhEs({\n keyLength,\n usageAlgorithm: keyAgreement.algorithm === 'ECDH-ES' ? decryption.algorithm : keyAgreement.algorithm,\n privateJwk: privateJwk,\n publicJwk: keyAgreement.externalPublicJwk,\n apu: keyAgreement.apu,\n apv: keyAgreement.apv,\n })\n\n if (keyAgreement.algorithm === 'ECDH-ES') {\n return {\n // TODO: will be more efficient to return node key instance\n contentEncryptionKey: {\n kty: 'oct',\n k: derivedKeyBytes.toString('base64url'),\n } as const,\n }\n }\n\n // Key wrapping\n const derivedKey = await subtle.importKey('raw', derivedKeyBytes, 'AES-KW', true, ['wrapKey'])\n\n const contentEncryptionKey = await subtle.unwrapKey(\n 'raw',\n keyAgreement.encryptedKey.encrypted,\n derivedKey,\n 'AES-KW',\n // algorithm used is irrelevant\n { hash: 'SHA-256', name: 'HMAC' },\n true,\n ['decrypt']\n )\n\n return {\n contentEncryptionKey: (await subtle.exportKey('jwk', contentEncryptionKey)) as Kms.KmsJwkPrivate,\n }\n}\n\n/**\n * Derive a key using ECDH and Concat KDF\n */\nasync function deriveKeyEcdhEs(options: {\n keyLength: number\n /**\n * This is only used for the AlgorithmID in KDF\n */\n usageAlgorithm: string\n apv?: AnyUint8Array\n apu?: AnyUint8Array\n privateJwk: Kms.KmsJwkPrivateEc | Kms.KmsJwkPrivateOkp\n publicJwk: Kms.KmsJwkPublicEc | Kms.KmsJwkPublicOkp\n}): Promise<Buffer> {\n // const privateKey = createPrivateKey({ format: 'jwk', key: options.privateJwk })\n // const publicKey = createPublicKey({ format: 'jwk', key: options.publicJwk })\n\n // Create ECDH instance based on curve\n const nodeEcdhCurveName = mapCrvToNodeEcdhCurveName(options.privateJwk.crv)\n const nodeConcatKdfHash = mapCrvToHashLength(options.publicJwk.crv)\n\n const ecdh = createECDH(nodeEcdhCurveName)\n\n // Set private key\n ecdh.setPrivateKey(TypedArrayEncoder.fromBase64(options.privateJwk.d))\n\n const publicKey = Kms.PublicJwk.fromPublicJwk(options.publicJwk).publicKey\n if (publicKey.kty === 'RSA') {\n throw new Kms.KeyManagementError('Key type RSA is not supported for ECDH-ES')\n }\n\n // Compute shared secret\n const sharedSecret = ecdh.computeSecret(publicKey.publicKey)\n\n // Prepare AlgorithmID for KDF (Datalen || Data)\n const algorithmData = Buffer.from(options.usageAlgorithm) // ASCII representation of alg\n const algorithmID = Buffer.concat([\n numberTo4ByteUint8Array(algorithmData.length), // Datalen: 32-bit big-endian counter\n algorithmData, // Data: ASCII representation of algorithm\n ])\n\n // Prepare PartyUInfo with proper length prefix\n const apu = options.apu || Buffer.alloc(0)\n const partyUInfo = Buffer.concat([\n numberTo4ByteUint8Array(apu.length), // Datalen: 32-bit big-endian counter\n apu, // Data: PartyUInfo value\n ])\n\n // Prepare PartyVInfo with proper length prefix\n const apv = options.apv || Buffer.alloc(0)\n const partyVInfo = Buffer.concat([\n numberTo4ByteUint8Array(apv.length), // Datalen: 32-bit big-endian counter\n apv, // Data: PartyVInfo value\n ])\n\n // Prepare otherInfo for KDF\n const otherInfo = Buffer.concat([\n algorithmID, // AlgorithmID: Datalen || Data\n partyUInfo, // PartyUInfo: Datalen || Data\n partyVInfo, // PartyVInfo: Datalen || Data\n numberTo4ByteUint8Array(options.keyLength), // SuppPubInfo: 32-bit big-endian rep of keydatalen\n Buffer.alloc(0), // SuppPrivInfo (empty octet sequence)\n ])\n\n // Derive final key using Concat KDF\n return concatKDF(sharedSecret, options.keyLength, nodeConcatKdfHash, otherInfo)\n}\n\nfunction numberTo4ByteUint8Array(number: number) {\n const buffer = new ArrayBuffer(4)\n const view = new DataView(buffer)\n view.setUint32(0, number)\n return new Uint8Array(buffer)\n}\n\n/**\n * Implements Concat KDF as per NIST SP 800-56A\n */\nfunction concatKDF(secret: Buffer, length: number, hashLength: ConcatKdfHashLength, otherInfo: Buffer): Buffer {\n const reps = Math.ceil((length >> 3) / (hashLength >> 3))\n const output = Buffer.alloc(reps * (hashLength >> 3))\n\n for (let i = 0; i < reps; i++) {\n const counter = Buffer.alloc(4 + secret.length + otherInfo.length)\n counter.writeUInt32BE(i + 1)\n counter.set(secret, 4)\n counter.set(otherInfo, 4 + secret.length)\n\n createHash(`sha${hashLength}`)\n .update(counter)\n .digest()\n .copy(output, (i * hashLength) >> 3)\n }\n\n return output.subarray(0, length >> 3)\n}\n\nfunction mapCrvToNodeEcdhCurveName(crv: Kms.KmsJwkPublicEc['crv'] | Kms.KmsJwkPublicOkp['crv']) {\n switch (crv) {\n case 'P-256':\n return 'prime256v1'\n case 'P-384':\n return 'secp384r1'\n case 'P-521':\n return 'secp521r1'\n case 'secp256k1':\n return 'secp256k1'\n case 'X25519':\n return 'x25519'\n default:\n throw new Kms.KeyManagementAlgorithmNotSupportedError(`crv '${crv}' for ECDH-ES`, 'node')\n }\n}\n\ntype ConcatKdfHashLength = ReturnType<typeof mapCrvToHashLength>\nfunction mapCrvToHashLength(crv: Kms.KmsJwkPublicEc['crv'] | Kms.KmsJwkPublicOkp['crv']) {\n switch (crv) {\n case 'secp256k1':\n case 'X25519':\n case 'P-256':\n return 256\n case 'P-384':\n return 384\n case 'P-521':\n return 512\n default:\n throw new Kms.KeyManagementAlgorithmNotSupportedError(`crv '${crv}' for ECDH-ES`, 'node')\n }\n}\n\n// TODO: might be worthwhile to add this to core?\n// TODO: we might want to have a separate definition per algorithm\n// defines things such as required key length.\nfunction mapContentEncryptionAlgorithmToKeyLength(\n encryptionAlgorithm: Kms.KnownJwaContentEncryptionAlgorithm | Kms.KnownJwaKeyEncryptionAlgorithm\n): number {\n switch (encryptionAlgorithm) {\n case 'A128CBC':\n case 'A128GCM':\n case 'A128KW':\n return 128\n case 'A192KW':\n return 192\n case 'A128CBC-HS256':\n case 'A256CBC':\n case 'A256GCM':\n case 'C20P':\n case 'XC20P':\n case 'A256KW':\n return 256\n\n case 'A192CBC-HS384':\n case 'A192GCM':\n return 384\n case 'A256CBC-HS512':\n return 512\n case 'XSALSA20-POLY1305':\n return 256\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"deriveKey.mjs","names":[],"sources":["../../../src/kms/crypto/deriveKey.ts"],"sourcesContent":["import { Buffer } from 'node:buffer'\nimport { createECDH, createHash, getRandomValues, subtle } from 'node:crypto'\nimport { Kms, TypedArrayEncoder } from '@credo-ts/core'\nimport type { NodeKmsSupportedEcCrvs } from './createKey'\n\nconst nodeSupportedEcdhKeyDerivationEcCrv = [\n 'P-256',\n 'P-384',\n 'P-521',\n 'secp256k1',\n] as const satisfies NodeKmsSupportedEcCrvs[]\n\nexport const nodeSupportedKeyAgreementAlgorithms = [\n 'ECDH-ES',\n 'ECDH-ES+A128KW',\n 'ECDH-ES+A192KW',\n 'ECDH-ES+A256KW',\n] satisfies Kms.KnownJwaKeyAgreementAlgorithm[]\n\nfunction assertNodeSupportedEcdhKeyDerivationCrv<Jwk extends Kms.KmsJwkPrivateAsymmetric | Kms.KmsJwkPublicAsymmetric>(\n jwk: Jwk\n): asserts jwk is Jwk & { kty: 'OKP' | 'EC'; crv: (typeof nodeSupportedEcdhKeyDerivationEcCrv)[number] | 'X25519' } {\n if (\n (jwk.kty === 'OKP' && jwk.crv !== 'X25519') ||\n (jwk.kty === 'EC' && !(nodeSupportedEcdhKeyDerivationEcCrv as string[]).includes(jwk.crv))\n ) {\n throw new Kms.KeyManagementAlgorithmNotSupportedError(\n `key derivation with crv '${jwk.crv}' for kty '${jwk.kty}'`,\n 'node'\n )\n }\n}\n\ntype NodeSupportedKeyAgreementDecryptOptions = Kms.KmsKeyAgreementDecryptOptions & {\n algorithm: (typeof nodeSupportedKeyAgreementAlgorithms)[number]\n}\ntype NodeSupportedKeyAgreementEncryptOptions = Kms.KmsKeyAgreementEncryptOptions & {\n algorithm: (typeof nodeSupportedKeyAgreementAlgorithms)[number]\n}\n\nexport async function deriveEncryptionKey(options: {\n keyAgreement: NodeSupportedKeyAgreementEncryptOptions\n privateJwk: Kms.KmsJwkPrivateAsymmetric\n encryption: Kms.KmsEncryptDataEncryption\n}) {\n const { keyAgreement, encryption, privateJwk } = options\n\n assertNodeSupportedEcdhKeyDerivationCrv(keyAgreement.externalPublicJwk)\n assertNodeSupportedEcdhKeyDerivationCrv(privateJwk)\n\n const keyLength =\n keyAgreement.algorithm === 'ECDH-ES'\n ? mapContentEncryptionAlgorithmToKeyLength(encryption.algorithm)\n : keyAgreement.algorithm === 'ECDH-ES+A128KW'\n ? 128\n : keyAgreement.algorithm === 'ECDH-ES+A192KW'\n ? 192\n : 256\n\n const derivedKeyBytes = await deriveKeyEcdhEs({\n keyLength,\n usageAlgorithm: keyAgreement.algorithm === 'ECDH-ES' ? encryption.algorithm : keyAgreement.algorithm,\n privateJwk,\n publicJwk: keyAgreement.externalPublicJwk,\n apu: keyAgreement.apu,\n apv: keyAgreement.apv,\n })\n\n if (keyAgreement.algorithm === 'ECDH-ES') {\n return {\n // TODO: will be more efficient to return node key instance\n contentEncryptionKey: {\n kty: 'oct',\n k: derivedKeyBytes.toString('base64url'),\n } as const,\n }\n }\n\n // Key wrapping\n const derivedKey = await subtle.importKey('raw', derivedKeyBytes, 'AES-KW', true, ['wrapKey'])\n const contentEncryptionKeyBytes = getRandomValues(\n new Uint8Array(mapContentEncryptionAlgorithmToKeyLength(encryption.algorithm) >> 3)\n )\n const contentEncryptionKey = await subtle.importKey('raw', contentEncryptionKeyBytes, 'AES-KW', true, ['wrapKey'])\n const encryptedContentEncryptionKey = await subtle.wrapKey('raw', contentEncryptionKey, derivedKey, 'AES-KW')\n\n return {\n encryptedContentEncryptionKey: {\n encrypted: new Uint8Array(encryptedContentEncryptionKey),\n } satisfies Kms.KmsEncryptedKey,\n contentEncryptionKey: {\n kty: 'oct',\n k: TypedArrayEncoder.toBase64Url(contentEncryptionKeyBytes),\n } as const,\n }\n}\n\nexport async function deriveDecryptionKey(options: {\n keyAgreement: NodeSupportedKeyAgreementDecryptOptions\n privateJwk: Kms.KmsJwkPrivateAsymmetric\n decryption: Kms.KmsDecryptDataDecryption\n}) {\n const { keyAgreement, decryption, privateJwk } = options\n\n assertNodeSupportedEcdhKeyDerivationCrv(keyAgreement.externalPublicJwk)\n assertNodeSupportedEcdhKeyDerivationCrv(privateJwk)\n\n const keyLength =\n keyAgreement.algorithm === 'ECDH-ES'\n ? mapContentEncryptionAlgorithmToKeyLength(decryption.algorithm)\n : keyAgreement.algorithm === 'ECDH-ES+A128KW'\n ? 128\n : keyAgreement.algorithm === 'ECDH-ES+A192KW'\n ? 192\n : 256\n\n const derivedKeyBytes = await deriveKeyEcdhEs({\n keyLength,\n usageAlgorithm: keyAgreement.algorithm === 'ECDH-ES' ? decryption.algorithm : keyAgreement.algorithm,\n privateJwk: privateJwk,\n publicJwk: keyAgreement.externalPublicJwk,\n apu: keyAgreement.apu,\n apv: keyAgreement.apv,\n })\n\n if (keyAgreement.algorithm === 'ECDH-ES') {\n return {\n // TODO: will be more efficient to return node key instance\n contentEncryptionKey: {\n kty: 'oct',\n k: derivedKeyBytes.toString('base64url'),\n } as const,\n }\n }\n\n // Key wrapping\n const derivedKey = await subtle.importKey('raw', derivedKeyBytes, 'AES-KW', true, ['wrapKey'])\n\n const contentEncryptionKey = await subtle.unwrapKey(\n 'raw',\n keyAgreement.encryptedKey.encrypted,\n derivedKey,\n 'AES-KW',\n // algorithm used is irrelevant\n { hash: 'SHA-256', name: 'HMAC' },\n true,\n ['decrypt']\n )\n\n return {\n contentEncryptionKey: (await subtle.exportKey('jwk', contentEncryptionKey)) as Kms.KmsJwkPrivate,\n }\n}\n\n/**\n * Derive a key using ECDH and Concat KDF\n */\nasync function deriveKeyEcdhEs(options: {\n keyLength: number\n /**\n * This is only used for the AlgorithmID in KDF\n */\n usageAlgorithm: string\n apv?: Uint8Array\n apu?: Uint8Array\n privateJwk: Kms.KmsJwkPrivateEc | Kms.KmsJwkPrivateOkp\n publicJwk: Kms.KmsJwkPublicEc | Kms.KmsJwkPublicOkp\n}): Promise<Buffer> {\n // const privateKey = createPrivateKey({ format: 'jwk', key: options.privateJwk })\n // const publicKey = createPublicKey({ format: 'jwk', key: options.publicJwk })\n\n // Create ECDH instance based on curve\n const nodeEcdhCurveName = mapCrvToNodeEcdhCurveName(options.privateJwk.crv)\n const nodeConcatKdfHash = mapCrvToHashLength(options.publicJwk.crv)\n\n const ecdh = createECDH(nodeEcdhCurveName)\n\n // Set private key\n ecdh.setPrivateKey(TypedArrayEncoder.fromBase64Url(options.privateJwk.d))\n\n const publicKey = Kms.PublicJwk.fromPublicJwk(options.publicJwk).publicKey\n if (publicKey.kty === 'RSA') {\n throw new Kms.KeyManagementError('Key type RSA is not supported for ECDH-ES')\n }\n\n // Compute shared secret\n const sharedSecret = ecdh.computeSecret(publicKey.publicKey)\n\n // Prepare AlgorithmID for KDF (Datalen || Data)\n const algorithmData = TypedArrayEncoder.fromUtf8String(options.usageAlgorithm) // ASCII representation of alg\n const algorithmID = TypedArrayEncoder.concat([\n numberTo4ByteUint8Array(algorithmData.length), // Datalen: 32-bit big-endian counter\n algorithmData, // Data: ASCII representation of algorithm\n ])\n\n // Prepare PartyUInfo with proper length prefix\n const apu = options.apu || Buffer.alloc(0)\n const partyUInfo = Buffer.concat([\n numberTo4ByteUint8Array(apu.length), // Datalen: 32-bit big-endian counter\n apu, // Data: PartyUInfo value\n ])\n\n // Prepare PartyVInfo with proper length prefix\n const apv = options.apv || Buffer.alloc(0)\n const partyVInfo = Buffer.concat([\n numberTo4ByteUint8Array(apv.length), // Datalen: 32-bit big-endian counter\n apv, // Data: PartyVInfo value\n ])\n\n // Prepare otherInfo for KDF\n const otherInfo = Buffer.concat([\n algorithmID, // AlgorithmID: Datalen || Data\n partyUInfo, // PartyUInfo: Datalen || Data\n partyVInfo, // PartyVInfo: Datalen || Data\n numberTo4ByteUint8Array(options.keyLength), // SuppPubInfo: 32-bit big-endian rep of keydatalen\n Buffer.alloc(0), // SuppPrivInfo (empty octet sequence)\n ])\n\n // Derive final key using Concat KDF\n return concatKDF(sharedSecret, options.keyLength, nodeConcatKdfHash, otherInfo)\n}\n\nfunction numberTo4ByteUint8Array(number: number) {\n const buffer = new ArrayBuffer(4)\n const view = new DataView(buffer)\n view.setUint32(0, number)\n return new Uint8Array(buffer)\n}\n\n/**\n * Implements Concat KDF as per NIST SP 800-56A\n */\nfunction concatKDF(secret: Buffer, length: number, hashLength: ConcatKdfHashLength, otherInfo: Buffer): Buffer {\n const reps = Math.ceil((length >> 3) / (hashLength >> 3))\n const output = Buffer.alloc(reps * (hashLength >> 3))\n\n for (let i = 0; i < reps; i++) {\n const counter = Buffer.alloc(4 + secret.length + otherInfo.length)\n counter.writeUInt32BE(i + 1)\n counter.set(secret, 4)\n counter.set(otherInfo, 4 + secret.length)\n\n createHash(`sha${hashLength}`)\n .update(counter)\n .digest()\n .copy(output, (i * hashLength) >> 3)\n }\n\n return output.subarray(0, length >> 3)\n}\n\nfunction mapCrvToNodeEcdhCurveName(crv: Kms.KmsJwkPublicEc['crv'] | Kms.KmsJwkPublicOkp['crv']) {\n switch (crv) {\n case 'P-256':\n return 'prime256v1'\n case 'P-384':\n return 'secp384r1'\n case 'P-521':\n return 'secp521r1'\n case 'secp256k1':\n return 'secp256k1'\n case 'X25519':\n return 'x25519'\n default:\n throw new Kms.KeyManagementAlgorithmNotSupportedError(`crv '${crv}' for ECDH-ES`, 'node')\n }\n}\n\ntype ConcatKdfHashLength = ReturnType<typeof mapCrvToHashLength>\nfunction mapCrvToHashLength(crv: Kms.KmsJwkPublicEc['crv'] | Kms.KmsJwkPublicOkp['crv']) {\n switch (crv) {\n case 'secp256k1':\n case 'X25519':\n case 'P-256':\n return 256\n case 'P-384':\n return 384\n case 'P-521':\n return 512\n default:\n throw new Kms.KeyManagementAlgorithmNotSupportedError(`crv '${crv}' for ECDH-ES`, 'node')\n }\n}\n\n// TODO: might be worthwhile to add this to core?\n// TODO: we might want to have a separate definition per algorithm\n// defines things such as required key length.\nfunction mapContentEncryptionAlgorithmToKeyLength(\n encryptionAlgorithm: Kms.KnownJwaContentEncryptionAlgorithm | Kms.KnownJwaKeyEncryptionAlgorithm\n): number {\n switch (encryptionAlgorithm) {\n case 'A128CBC':\n case 'A128GCM':\n case 'A128KW':\n return 128\n case 'A192KW':\n return 192\n case 'A128CBC-HS256':\n case 'A256CBC':\n case 'A256GCM':\n case 'C20P':\n case 'XC20P':\n case 'A256KW':\n return 256\n\n case 'A192CBC-HS384':\n case 'A192GCM':\n return 384\n case 'A256CBC-HS512':\n return 512\n case 'XSALSA20-POLY1305':\n return 256\n }\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { performSign } from "./sign.mjs";
2
- import { Kms } from "@credo-ts/core";
2
+ import { Kms, TypedArrayEncoder } from "@credo-ts/core";
3
3
  import { createCipheriv, createSecretKey, randomBytes } from "node:crypto";
4
4
  import { Buffer } from "node:buffer";
5
5
 
@@ -16,7 +16,7 @@ const nodeSupportedEncryptionAlgorithms = [
16
16
  "C20P"
17
17
  ];
18
18
  async function performEncrypt(key, dataEncryption, data) {
19
- const secretKeyBytes = Buffer.from(key.k, "base64url");
19
+ const secretKeyBytes = TypedArrayEncoder.fromBase64Url(key.k);
20
20
  const nodeKey = createSecretKey(secretKeyBytes);
21
21
  if (dataEncryption.algorithm === "A128CBC" || dataEncryption.algorithm === "A256CBC") {
22
22
  const nodeAlgorithm = dataEncryption.algorithm === "A128CBC" ? "aes-128-cbc" : "aes-256-cbc";
@@ -59,13 +59,12 @@ async function performEncrypt(key, dataEncryption, data) {
59
59
  encrypted,
60
60
  al
61
61
  ]);
62
- const hmac = await performSign({
63
- kty: "oct",
64
- k: macKey.toString("base64url")
65
- }, algSettings.hmacAlg, macData);
66
62
  return {
67
63
  encrypted,
68
- tag: Buffer.from(hmac).subarray(0, algSettings.keySize),
64
+ tag: (await performSign({
65
+ kty: "oct",
66
+ k: TypedArrayEncoder.toBase64Url(macKey)
67
+ }, algSettings.hmacAlg, macData)).subarray(0, algSettings.keySize),
69
68
  iv
70
69
  };
71
70
  }
@@ -1 +1 @@
1
- {"version":3,"file":"encrypt.mjs","names":[],"sources":["../../../src/kms/crypto/encrypt.ts"],"sourcesContent":["import { Buffer } from 'node:buffer'\nimport type { CipherGCM } from 'node:crypto'\nimport { createCipheriv, createSecretKey, randomBytes } from 'node:crypto'\nimport { type AnyUint8Array, Kms, type Uint8ArrayBuffer } from '@credo-ts/core'\n\nimport { performSign } from './sign'\n\nexport const nodeSupportedEncryptionAlgorithms = [\n 'A128CBC',\n 'A256CBC',\n 'A128CBC-HS256',\n 'A192CBC-HS384',\n 'A256CBC-HS512',\n 'A128GCM',\n 'A192GCM',\n 'A256GCM',\n 'C20P',\n] as const satisfies Kms.KnownJwaContentEncryptionAlgorithm[]\n\nexport async function performEncrypt(\n key: Kms.KmsJwkPrivateOct,\n dataEncryption: Kms.KmsEncryptDataEncryption,\n data: AnyUint8Array\n): Promise<{ encrypted: Uint8ArrayBuffer; tag?: Uint8ArrayBuffer; iv: AnyUint8Array }> {\n const secretKeyBytes = Buffer.from(key.k, 'base64url')\n const nodeKey = createSecretKey(secretKeyBytes)\n\n // Create cipher with key and IV\n if (dataEncryption.algorithm === 'A128CBC' || dataEncryption.algorithm === 'A256CBC') {\n const nodeAlgorithm = dataEncryption.algorithm === 'A128CBC' ? 'aes-128-cbc' : 'aes-256-cbc'\n\n // IV should be exactly 16 bytes (128 bits) for CBC mode\n const iv = dataEncryption.iv ?? randomBytes(16)\n\n const cipher = createCipheriv(nodeAlgorithm, nodeKey, iv)\n\n // Get encrypted data\n const encrypted = Buffer.concat([cipher.update(data), cipher.final()])\n\n return { encrypted, iv }\n }\n if (\n dataEncryption.algorithm === 'A128CBC-HS256' ||\n dataEncryption.algorithm === 'A192CBC-HS384' ||\n dataEncryption.algorithm === 'A256CBC-HS512'\n ) {\n // Map algorithms to their corresponding CBC and HMAC settings\n const algSettings = {\n 'A128CBC-HS256': { cbcAlg: 'aes-128-cbc', hmacAlg: 'HS256', keySize: 16 } as const,\n 'A192CBC-HS384': { cbcAlg: 'aes-192-cbc', hmacAlg: 'HS384', keySize: 24 } as const,\n 'A256CBC-HS512': { cbcAlg: 'aes-256-cbc', hmacAlg: 'HS512', keySize: 32 } as const,\n }[dataEncryption.algorithm]\n\n // IV should be exactly 16 bytes (128 bits) for CBC mode\n const iv = dataEncryption.iv ?? randomBytes(16)\n\n // Split the input key into MAC and ENC keys (MAC key is first half, ENC key is second half)\n const macKey = secretKeyBytes.subarray(0, algSettings.keySize)\n const encKey = createSecretKey(secretKeyBytes.subarray(algSettings.keySize))\n\n // Perform encryption\n const cipher = createCipheriv(algSettings.cbcAlg, encKey, iv)\n const encrypted = Buffer.concat([cipher.update(data), cipher.final()])\n\n // Calculate authentication tag\n // AL (Associated Length) is 64-bit big-endian length of AAD in bits\n const al = Buffer.alloc(8)\n const aadLength = dataEncryption.aad ? dataEncryption.aad.length * 8 : 0\n al.writeBigUInt64BE(BigInt(aadLength))\n\n // Create concatenated buffer for MAC calculation\n const macData = Buffer.concat([\n // If AAD exists, include it first, otherwise empty buffer\n dataEncryption.aad ?? Buffer.alloc(0),\n iv, // Initial Vector\n encrypted, // Ciphertext\n al, // Associated Length (AL)\n ])\n\n const hmac = await performSign({ kty: 'oct', k: macKey.toString('base64url') }, algSettings.hmacAlg, macData)\n const tag = Buffer.from(hmac).subarray(0, algSettings.keySize) // Truncate to appropriate size\n\n return { encrypted, tag, iv }\n }\n if (\n dataEncryption.algorithm === 'A128GCM' ||\n dataEncryption.algorithm === 'A192GCM' ||\n dataEncryption.algorithm === 'A256GCM'\n ) {\n const nodeAlgorithm =\n dataEncryption.algorithm === 'A128GCM'\n ? 'aes-128-gcm'\n : dataEncryption.algorithm === 'A192GCM'\n ? 'aes-192-gcm'\n : 'aes-256-gcm'\n\n // IV should be exactly 12 bytes (96 bits) for GCM\n const iv = dataEncryption.iv ?? randomBytes(12)\n\n const cipher = createCipheriv(nodeAlgorithm, nodeKey, iv)\n\n // If AAD is provided, update the cipher with it before encryption\n if (dataEncryption.aad) {\n cipher.setAAD(dataEncryption.aad)\n }\n\n // Get encrypted data\n const encrypted = Buffer.concat([cipher.update(data), cipher.final()])\n\n // Get auth tag - must be saved to verify decryption\n const tag = cipher.getAuthTag() as Uint8ArrayBuffer\n\n return {\n encrypted,\n tag,\n iv,\n }\n }\n if (dataEncryption.algorithm === 'C20P') {\n // IV should be exactly 12 bytes (96 bits) for C20P\n const iv = dataEncryption.iv ?? randomBytes(12)\n\n const cipher: CipherGCM = createCipheriv('chacha20-poly1305', nodeKey, iv, {\n authTagLength: 16,\n })\n\n // If AAD is provided, update the cipher with it before encryption\n if (dataEncryption.aad) {\n cipher.setAAD(dataEncryption.aad)\n }\n\n // Get encrypted data\n const encrypted = Buffer.concat([cipher.update(data), cipher.final()])\n\n // Get auth tag - must be saved to verify decryption\n const tag = cipher.getAuthTag() as Uint8ArrayBuffer\n\n return {\n encrypted,\n tag,\n iv,\n }\n }\n\n throw new Kms.KeyManagementAlgorithmNotSupportedError(\n `JWA content encryption algorithm '${dataEncryption.algorithm}'`,\n 'node'\n )\n}\n"],"mappings":";;;;;;AAOA,MAAa,oCAAoC;CAC/C;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD;AAED,eAAsB,eACpB,KACA,gBACA,MACqF;CACrF,MAAM,iBAAiB,OAAO,KAAK,IAAI,GAAG,YAAY;CACtD,MAAM,UAAU,gBAAgB,eAAe;AAG/C,KAAI,eAAe,cAAc,aAAa,eAAe,cAAc,WAAW;EACpF,MAAM,gBAAgB,eAAe,cAAc,YAAY,gBAAgB;EAG/E,MAAM,KAAK,eAAe,MAAM,YAAY,GAAG;EAE/C,MAAM,SAAS,eAAe,eAAe,SAAS,GAAG;AAKzD,SAAO;GAAE,WAFS,OAAO,OAAO,CAAC,OAAO,OAAO,KAAK,EAAE,OAAO,OAAO,CAAC,CAAC;GAElD;GAAI;;AAE1B,KACE,eAAe,cAAc,mBAC7B,eAAe,cAAc,mBAC7B,eAAe,cAAc,iBAC7B;EAEA,MAAM,cAAc;GAClB,iBAAiB;IAAE,QAAQ;IAAe,SAAS;IAAS,SAAS;IAAI;GACzE,iBAAiB;IAAE,QAAQ;IAAe,SAAS;IAAS,SAAS;IAAI;GACzE,iBAAiB;IAAE,QAAQ;IAAe,SAAS;IAAS,SAAS;IAAI;GAC1E,CAAC,eAAe;EAGjB,MAAM,KAAK,eAAe,MAAM,YAAY,GAAG;EAG/C,MAAM,SAAS,eAAe,SAAS,GAAG,YAAY,QAAQ;EAC9D,MAAM,SAAS,gBAAgB,eAAe,SAAS,YAAY,QAAQ,CAAC;EAG5E,MAAM,SAAS,eAAe,YAAY,QAAQ,QAAQ,GAAG;EAC7D,MAAM,YAAY,OAAO,OAAO,CAAC,OAAO,OAAO,KAAK,EAAE,OAAO,OAAO,CAAC,CAAC;EAItE,MAAM,KAAK,OAAO,MAAM,EAAE;EAC1B,MAAM,YAAY,eAAe,MAAM,eAAe,IAAI,SAAS,IAAI;AACvE,KAAG,iBAAiB,OAAO,UAAU,CAAC;EAGtC,MAAM,UAAU,OAAO,OAAO;GAE5B,eAAe,OAAO,OAAO,MAAM,EAAE;GACrC;GACA;GACA;GACD,CAAC;EAEF,MAAM,OAAO,MAAM,YAAY;GAAE,KAAK;GAAO,GAAG,OAAO,SAAS,YAAY;GAAE,EAAE,YAAY,SAAS,QAAQ;AAG7G,SAAO;GAAE;GAAW,KAFR,OAAO,KAAK,KAAK,CAAC,SAAS,GAAG,YAAY,QAAQ;GAErC;GAAI;;AAE/B,KACE,eAAe,cAAc,aAC7B,eAAe,cAAc,aAC7B,eAAe,cAAc,WAC7B;EACA,MAAM,gBACJ,eAAe,cAAc,YACzB,gBACA,eAAe,cAAc,YAC3B,gBACA;EAGR,MAAM,KAAK,eAAe,MAAM,YAAY,GAAG;EAE/C,MAAM,SAAS,eAAe,eAAe,SAAS,GAAG;AAGzD,MAAI,eAAe,IACjB,QAAO,OAAO,eAAe,IAAI;AASnC,SAAO;GACL,WANgB,OAAO,OAAO,CAAC,OAAO,OAAO,KAAK,EAAE,OAAO,OAAO,CAAC,CAAC;GAOpE,KAJU,OAAO,YAAY;GAK7B;GACD;;AAEH,KAAI,eAAe,cAAc,QAAQ;EAEvC,MAAM,KAAK,eAAe,MAAM,YAAY,GAAG;EAE/C,MAAM,SAAoB,eAAe,qBAAqB,SAAS,IAAI,EACzE,eAAe,IAChB,CAAC;AAGF,MAAI,eAAe,IACjB,QAAO,OAAO,eAAe,IAAI;AASnC,SAAO;GACL,WANgB,OAAO,OAAO,CAAC,OAAO,OAAO,KAAK,EAAE,OAAO,OAAO,CAAC,CAAC;GAOpE,KAJU,OAAO,YAAY;GAK7B;GACD;;AAGH,OAAM,IAAI,IAAI,wCACZ,qCAAqC,eAAe,UAAU,IAC9D,OACD"}
1
+ {"version":3,"file":"encrypt.mjs","names":[],"sources":["../../../src/kms/crypto/encrypt.ts"],"sourcesContent":["import { Buffer } from 'node:buffer'\nimport type { CipherGCM } from 'node:crypto'\nimport { createCipheriv, createSecretKey, randomBytes } from 'node:crypto'\nimport { Kms, TypedArrayEncoder } from '@credo-ts/core'\nimport { performSign } from './sign'\n\nexport const nodeSupportedEncryptionAlgorithms = [\n 'A128CBC',\n 'A256CBC',\n 'A128CBC-HS256',\n 'A192CBC-HS384',\n 'A256CBC-HS512',\n 'A128GCM',\n 'A192GCM',\n 'A256GCM',\n 'C20P',\n] as const satisfies Kms.KnownJwaContentEncryptionAlgorithm[]\n\nexport async function performEncrypt(\n key: Kms.KmsJwkPrivateOct,\n dataEncryption: Kms.KmsEncryptDataEncryption,\n data: Uint8Array\n): Promise<{ encrypted: Uint8Array; tag?: Uint8Array; iv: Uint8Array }> {\n const secretKeyBytes = TypedArrayEncoder.fromBase64Url(key.k)\n const nodeKey = createSecretKey(secretKeyBytes)\n\n // Create cipher with key and IV\n if (dataEncryption.algorithm === 'A128CBC' || dataEncryption.algorithm === 'A256CBC') {\n const nodeAlgorithm = dataEncryption.algorithm === 'A128CBC' ? 'aes-128-cbc' : 'aes-256-cbc'\n\n // IV should be exactly 16 bytes (128 bits) for CBC mode\n const iv = dataEncryption.iv ?? randomBytes(16)\n\n const cipher = createCipheriv(nodeAlgorithm, nodeKey, iv)\n\n // Get encrypted data\n const encrypted = Buffer.concat([cipher.update(data), cipher.final()])\n\n return { encrypted, iv }\n }\n if (\n dataEncryption.algorithm === 'A128CBC-HS256' ||\n dataEncryption.algorithm === 'A192CBC-HS384' ||\n dataEncryption.algorithm === 'A256CBC-HS512'\n ) {\n // Map algorithms to their corresponding CBC and HMAC settings\n const algSettings = {\n 'A128CBC-HS256': { cbcAlg: 'aes-128-cbc', hmacAlg: 'HS256', keySize: 16 } as const,\n 'A192CBC-HS384': { cbcAlg: 'aes-192-cbc', hmacAlg: 'HS384', keySize: 24 } as const,\n 'A256CBC-HS512': { cbcAlg: 'aes-256-cbc', hmacAlg: 'HS512', keySize: 32 } as const,\n }[dataEncryption.algorithm]\n\n // IV should be exactly 16 bytes (128 bits) for CBC mode\n const iv = dataEncryption.iv ?? randomBytes(16)\n\n // Split the input key into MAC and ENC keys (MAC key is first half, ENC key is second half)\n const macKey = secretKeyBytes.subarray(0, algSettings.keySize)\n const encKey = createSecretKey(secretKeyBytes.subarray(algSettings.keySize))\n\n // Perform encryption\n const cipher = createCipheriv(algSettings.cbcAlg, encKey, iv)\n const encrypted = Buffer.concat([cipher.update(data), cipher.final()])\n\n // Calculate authentication tag\n // AL (Associated Length) is 64-bit big-endian length of AAD in bits\n const al = Buffer.alloc(8)\n const aadLength = dataEncryption.aad ? dataEncryption.aad.length * 8 : 0\n al.writeBigUInt64BE(BigInt(aadLength))\n\n // Create concatenated buffer for MAC calculation\n const macData = Buffer.concat([\n // If AAD exists, include it first, otherwise empty buffer\n dataEncryption.aad ?? Buffer.alloc(0),\n iv, // Initial Vector\n encrypted, // Ciphertext\n al, // Associated Length (AL)\n ])\n\n const hmac = await performSign(\n { kty: 'oct', k: TypedArrayEncoder.toBase64Url(macKey) },\n algSettings.hmacAlg,\n macData\n )\n const tag = hmac.subarray(0, algSettings.keySize) // Truncate to appropriate size\n\n return { encrypted, tag, iv }\n }\n if (\n dataEncryption.algorithm === 'A128GCM' ||\n dataEncryption.algorithm === 'A192GCM' ||\n dataEncryption.algorithm === 'A256GCM'\n ) {\n const nodeAlgorithm =\n dataEncryption.algorithm === 'A128GCM'\n ? 'aes-128-gcm'\n : dataEncryption.algorithm === 'A192GCM'\n ? 'aes-192-gcm'\n : 'aes-256-gcm'\n\n // IV should be exactly 12 bytes (96 bits) for GCM\n const iv = dataEncryption.iv ?? randomBytes(12)\n\n const cipher = createCipheriv(nodeAlgorithm, nodeKey, iv)\n\n // If AAD is provided, update the cipher with it before encryption\n if (dataEncryption.aad) {\n cipher.setAAD(dataEncryption.aad)\n }\n\n // Get encrypted data\n const encrypted = Buffer.concat([cipher.update(data), cipher.final()])\n\n // Get auth tag - must be saved to verify decryption\n const tag = cipher.getAuthTag() as Uint8Array\n\n return {\n encrypted,\n tag,\n iv,\n }\n }\n if (dataEncryption.algorithm === 'C20P') {\n // IV should be exactly 12 bytes (96 bits) for C20P\n const iv = dataEncryption.iv ?? randomBytes(12)\n\n const cipher: CipherGCM = createCipheriv('chacha20-poly1305', nodeKey, iv, {\n authTagLength: 16,\n })\n\n // If AAD is provided, update the cipher with it before encryption\n if (dataEncryption.aad) {\n cipher.setAAD(dataEncryption.aad)\n }\n\n // Get encrypted data\n const encrypted = Buffer.concat([cipher.update(data), cipher.final()])\n\n // Get auth tag - must be saved to verify decryption\n const tag = cipher.getAuthTag() as Uint8Array\n\n return {\n encrypted,\n tag,\n iv,\n }\n }\n\n throw new Kms.KeyManagementAlgorithmNotSupportedError(\n `JWA content encryption algorithm '${dataEncryption.algorithm}'`,\n 'node'\n )\n}\n"],"mappings":";;;;;;AAMA,MAAa,oCAAoC;CAC/C;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD;AAED,eAAsB,eACpB,KACA,gBACA,MACsE;CACtE,MAAM,iBAAiB,kBAAkB,cAAc,IAAI,EAAE;CAC7D,MAAM,UAAU,gBAAgB,eAAe;AAG/C,KAAI,eAAe,cAAc,aAAa,eAAe,cAAc,WAAW;EACpF,MAAM,gBAAgB,eAAe,cAAc,YAAY,gBAAgB;EAG/E,MAAM,KAAK,eAAe,MAAM,YAAY,GAAG;EAE/C,MAAM,SAAS,eAAe,eAAe,SAAS,GAAG;AAKzD,SAAO;GAAE,WAFS,OAAO,OAAO,CAAC,OAAO,OAAO,KAAK,EAAE,OAAO,OAAO,CAAC,CAAC;GAElD;GAAI;;AAE1B,KACE,eAAe,cAAc,mBAC7B,eAAe,cAAc,mBAC7B,eAAe,cAAc,iBAC7B;EAEA,MAAM,cAAc;GAClB,iBAAiB;IAAE,QAAQ;IAAe,SAAS;IAAS,SAAS;IAAI;GACzE,iBAAiB;IAAE,QAAQ;IAAe,SAAS;IAAS,SAAS;IAAI;GACzE,iBAAiB;IAAE,QAAQ;IAAe,SAAS;IAAS,SAAS;IAAI;GAC1E,CAAC,eAAe;EAGjB,MAAM,KAAK,eAAe,MAAM,YAAY,GAAG;EAG/C,MAAM,SAAS,eAAe,SAAS,GAAG,YAAY,QAAQ;EAC9D,MAAM,SAAS,gBAAgB,eAAe,SAAS,YAAY,QAAQ,CAAC;EAG5E,MAAM,SAAS,eAAe,YAAY,QAAQ,QAAQ,GAAG;EAC7D,MAAM,YAAY,OAAO,OAAO,CAAC,OAAO,OAAO,KAAK,EAAE,OAAO,OAAO,CAAC,CAAC;EAItE,MAAM,KAAK,OAAO,MAAM,EAAE;EAC1B,MAAM,YAAY,eAAe,MAAM,eAAe,IAAI,SAAS,IAAI;AACvE,KAAG,iBAAiB,OAAO,UAAU,CAAC;EAGtC,MAAM,UAAU,OAAO,OAAO;GAE5B,eAAe,OAAO,OAAO,MAAM,EAAE;GACrC;GACA;GACA;GACD,CAAC;AASF,SAAO;GAAE;GAAW,MAPP,MAAM,YACjB;IAAE,KAAK;IAAO,GAAG,kBAAkB,YAAY,OAAO;IAAE,EACxD,YAAY,SACZ,QACD,EACgB,SAAS,GAAG,YAAY,QAAQ;GAExB;GAAI;;AAE/B,KACE,eAAe,cAAc,aAC7B,eAAe,cAAc,aAC7B,eAAe,cAAc,WAC7B;EACA,MAAM,gBACJ,eAAe,cAAc,YACzB,gBACA,eAAe,cAAc,YAC3B,gBACA;EAGR,MAAM,KAAK,eAAe,MAAM,YAAY,GAAG;EAE/C,MAAM,SAAS,eAAe,eAAe,SAAS,GAAG;AAGzD,MAAI,eAAe,IACjB,QAAO,OAAO,eAAe,IAAI;AASnC,SAAO;GACL,WANgB,OAAO,OAAO,CAAC,OAAO,OAAO,KAAK,EAAE,OAAO,OAAO,CAAC,CAAC;GAOpE,KAJU,OAAO,YAAY;GAK7B;GACD;;AAEH,KAAI,eAAe,cAAc,QAAQ;EAEvC,MAAM,KAAK,eAAe,MAAM,YAAY,GAAG;EAE/C,MAAM,SAAoB,eAAe,qBAAqB,SAAS,IAAI,EACzE,eAAe,IAChB,CAAC;AAGF,MAAI,eAAe,IACjB,QAAO,OAAO,eAAe,IAAI;AASnC,SAAO;GACL,WANgB,OAAO,OAAO,CAAC,OAAO,OAAO,KAAK,EAAE,OAAO,OAAO,CAAC,CAAC;GAOpE,KAJU,OAAO,YAAY;GAK7B;GACD;;AAGH,OAAM,IAAI,IAAI,wCACZ,qCAAqC,eAAe,UAAU,IAC9D,OACD"}
@@ -6,7 +6,7 @@ import { promisify } from "node:util";
6
6
  const sign$1 = promisify(sign);
7
7
  function performSign(key, algorithm, data) {
8
8
  const nodeAlgorithm = mapJwaSignatureAlgorithmToNode(algorithm);
9
- const nodeKey = key.kty === "oct" ? createSecretKey(TypedArrayEncoder.fromBase64(key.k)) : createPrivateKey({
9
+ const nodeKey = key.kty === "oct" ? createSecretKey(TypedArrayEncoder.fromBase64Url(key.k)) : createPrivateKey({
10
10
  format: "jwk",
11
11
  key
12
12
  });
@@ -1 +1 @@
1
- {"version":3,"file":"sign.mjs","names":["sign","_sign"],"sources":["../../../src/kms/crypto/sign.ts"],"sourcesContent":["import { sign as _sign, constants, createHmac, createPrivateKey, createSecretKey } from 'node:crypto'\nimport { promisify } from 'node:util'\nimport type { AnyUint8Array, CanBePromise, Uint8ArrayBuffer } from '@credo-ts/core'\nimport { Kms, TypedArrayEncoder } from '@credo-ts/core'\n\nconst sign = promisify(_sign)\n\nexport function performSign(\n key: Kms.KmsJwkPrivate,\n algorithm: Kms.KnownJwaSignatureAlgorithm,\n data: AnyUint8Array\n): CanBePromise<Uint8ArrayBuffer> {\n const nodeAlgorithm = mapJwaSignatureAlgorithmToNode(algorithm)\n const nodeKey =\n key.kty === 'oct' ? createSecretKey(TypedArrayEncoder.fromBase64(key.k)) : createPrivateKey({ format: 'jwk', key })\n\n switch (key.kty) {\n case 'RSA':\n case 'OKP': {\n const nodeKeyInput = algorithm.startsWith('PS')\n ? // For RSA-PSS, we need to set padding\n {\n key: nodeKey,\n padding: constants.RSA_PKCS1_PSS_PADDING,\n saltLength: Number.parseInt(algorithm.slice(2), 10) / 8,\n }\n : nodeKey\n\n return sign(nodeAlgorithm, data, nodeKeyInput) as Promise<Uint8ArrayBuffer>\n }\n case 'EC': {\n // Node returns EC signatures as DER encoded, but we need raw\n return sign(nodeAlgorithm, data, nodeKey).then((derSignature) =>\n Kms.derEcSignatureToRaw(derSignature, key.crv)\n ) as Promise<Uint8ArrayBuffer>\n }\n case 'oct': {\n return createHmac(nodeAlgorithm as string, nodeKey)\n .update(data)\n .digest() as Uint8ArrayBuffer\n }\n default:\n // @ts-expect-error\n throw new Kms.KeyManagementAlgorithmNotSupportedError(`kty '${key.kty}'`, 'node')\n }\n}\n\nexport const nodeSupportedJwaAlgorithm = [\n 'RS256',\n 'PS256',\n 'HS256',\n 'ES256',\n 'ES256K',\n 'RS384',\n 'PS384',\n 'HS384',\n 'ES384',\n 'RS512',\n 'PS512',\n 'HS512',\n 'ES512',\n 'EdDSA',\n 'Ed25519',\n] as const satisfies Kms.KnownJwaSignatureAlgorithm[]\n\nexport function mapJwaSignatureAlgorithmToNode(algorithm: Kms.KnownJwaSignatureAlgorithm) {\n switch (algorithm) {\n case 'RS256':\n case 'PS256':\n case 'HS256':\n case 'ES256':\n case 'ES256K':\n return 'sha256'\n case 'RS384':\n case 'PS384':\n case 'HS384':\n case 'ES384':\n return 'sha384'\n case 'RS512':\n case 'PS512':\n case 'HS512':\n case 'ES512':\n return 'sha512'\n // For EdDSA it's derived based on the key\n case 'EdDSA':\n case 'Ed25519':\n return undefined\n default:\n throw new Kms.KeyManagementAlgorithmNotSupportedError(`JWA algorithm '${algorithm}'`, 'node')\n }\n}\n"],"mappings":";;;;;AAKA,MAAMA,SAAO,UAAUC,KAAM;AAE7B,SAAgB,YACd,KACA,WACA,MACgC;CAChC,MAAM,gBAAgB,+BAA+B,UAAU;CAC/D,MAAM,UACJ,IAAI,QAAQ,QAAQ,gBAAgB,kBAAkB,WAAW,IAAI,EAAE,CAAC,GAAG,iBAAiB;EAAE,QAAQ;EAAO;EAAK,CAAC;AAErH,SAAQ,IAAI,KAAZ;EACE,KAAK;EACL,KAAK,MAUH,QAAOD,OAAK,eAAe,MATN,UAAU,WAAW,KAAK,GAE3C;GACE,KAAK;GACL,SAAS,UAAU;GACnB,YAAY,OAAO,SAAS,UAAU,MAAM,EAAE,EAAE,GAAG,GAAG;GACvD,GACD,QAE0C;EAEhD,KAAK,KAEH,QAAOA,OAAK,eAAe,MAAM,QAAQ,CAAC,MAAM,iBAC9C,IAAI,oBAAoB,cAAc,IAAI,IAAI,CAC/C;EAEH,KAAK,MACH,QAAO,WAAW,eAAyB,QAAQ,CAChD,OAAO,KAAK,CACZ,QAAQ;EAEb,QAEE,OAAM,IAAI,IAAI,wCAAwC,QAAQ,IAAI,IAAI,IAAI,OAAO;;;AAIvF,MAAa,4BAA4B;CACvC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD;AAED,SAAgB,+BAA+B,WAA2C;AACxF,SAAQ,WAAR;EACE,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK,SACH,QAAO;EACT,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK,QACH,QAAO;EACT,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK,QACH,QAAO;EAET,KAAK;EACL,KAAK,UACH;EACF,QACE,OAAM,IAAI,IAAI,wCAAwC,kBAAkB,UAAU,IAAI,OAAO"}
1
+ {"version":3,"file":"sign.mjs","names":["sign","_sign"],"sources":["../../../src/kms/crypto/sign.ts"],"sourcesContent":["import { sign as _sign, constants, createHmac, createPrivateKey, createSecretKey } from 'node:crypto'\nimport { promisify } from 'node:util'\nimport type { CanBePromise } from '@credo-ts/core'\nimport { Kms, TypedArrayEncoder } from '@credo-ts/core'\n\nconst sign = promisify(_sign)\n\nexport function performSign(\n key: Kms.KmsJwkPrivate,\n algorithm: Kms.KnownJwaSignatureAlgorithm,\n data: Uint8Array\n): CanBePromise<Uint8Array> {\n const nodeAlgorithm = mapJwaSignatureAlgorithmToNode(algorithm)\n const nodeKey =\n key.kty === 'oct'\n ? createSecretKey(TypedArrayEncoder.fromBase64Url(key.k))\n : createPrivateKey({ format: 'jwk', key })\n\n switch (key.kty) {\n case 'RSA':\n case 'OKP': {\n const nodeKeyInput = algorithm.startsWith('PS')\n ? // For RSA-PSS, we need to set padding\n {\n key: nodeKey,\n padding: constants.RSA_PKCS1_PSS_PADDING,\n saltLength: Number.parseInt(algorithm.slice(2), 10) / 8,\n }\n : nodeKey\n\n return sign(nodeAlgorithm, data, nodeKeyInput) as Promise<Uint8Array>\n }\n case 'EC': {\n // Node returns EC signatures as DER encoded, but we need raw\n return sign(nodeAlgorithm, data, nodeKey).then((derSignature) => Kms.derEcSignatureToRaw(derSignature, key.crv))\n }\n case 'oct': {\n return createHmac(nodeAlgorithm as string, nodeKey)\n .update(data)\n .digest()\n }\n default:\n // @ts-expect-error\n throw new Kms.KeyManagementAlgorithmNotSupportedError(`kty '${key.kty}'`, 'node')\n }\n}\n\nexport const nodeSupportedJwaAlgorithm = [\n 'RS256',\n 'PS256',\n 'HS256',\n 'ES256',\n 'ES256K',\n 'RS384',\n 'PS384',\n 'HS384',\n 'ES384',\n 'RS512',\n 'PS512',\n 'HS512',\n 'ES512',\n 'EdDSA',\n 'Ed25519',\n] as const satisfies Kms.KnownJwaSignatureAlgorithm[]\n\nexport function mapJwaSignatureAlgorithmToNode(algorithm: Kms.KnownJwaSignatureAlgorithm) {\n switch (algorithm) {\n case 'RS256':\n case 'PS256':\n case 'HS256':\n case 'ES256':\n case 'ES256K':\n return 'sha256'\n case 'RS384':\n case 'PS384':\n case 'HS384':\n case 'ES384':\n return 'sha384'\n case 'RS512':\n case 'PS512':\n case 'HS512':\n case 'ES512':\n return 'sha512'\n // For EdDSA it's derived based on the key\n case 'EdDSA':\n case 'Ed25519':\n return undefined\n default:\n throw new Kms.KeyManagementAlgorithmNotSupportedError(`JWA algorithm '${algorithm}'`, 'node')\n }\n}\n"],"mappings":";;;;;AAKA,MAAMA,SAAO,UAAUC,KAAM;AAE7B,SAAgB,YACd,KACA,WACA,MAC0B;CAC1B,MAAM,gBAAgB,+BAA+B,UAAU;CAC/D,MAAM,UACJ,IAAI,QAAQ,QACR,gBAAgB,kBAAkB,cAAc,IAAI,EAAE,CAAC,GACvD,iBAAiB;EAAE,QAAQ;EAAO;EAAK,CAAC;AAE9C,SAAQ,IAAI,KAAZ;EACE,KAAK;EACL,KAAK,MAUH,QAAOD,OAAK,eAAe,MATN,UAAU,WAAW,KAAK,GAE3C;GACE,KAAK;GACL,SAAS,UAAU;GACnB,YAAY,OAAO,SAAS,UAAU,MAAM,EAAE,EAAE,GAAG,GAAG;GACvD,GACD,QAE0C;EAEhD,KAAK,KAEH,QAAOA,OAAK,eAAe,MAAM,QAAQ,CAAC,MAAM,iBAAiB,IAAI,oBAAoB,cAAc,IAAI,IAAI,CAAC;EAElH,KAAK,MACH,QAAO,WAAW,eAAyB,QAAQ,CAChD,OAAO,KAAK,CACZ,QAAQ;EAEb,QAEE,OAAM,IAAI,IAAI,wCAAwC,QAAQ,IAAI,IAAI,IAAI,OAAO;;;AAIvF,MAAa,4BAA4B;CACvC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD;AAED,SAAgB,+BAA+B,WAA2C;AACxF,SAAQ,WAAR;EACE,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK,SACH,QAAO;EACT,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK,QACH,QAAO;EACT,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK,QACH,QAAO;EAET,KAAK;EACL,KAAK,UACH;EACF,QACE,OAAM,IAAI,IAAI,wCAAwC,kBAAkB,UAAU,IAAI,OAAO"}
@@ -2,13 +2,12 @@ import { mapJwaSignatureAlgorithmToNode } from "./sign.mjs";
2
2
  import { Kms, TypedArrayEncoder } from "@credo-ts/core";
3
3
  import { constants, createHmac, createPublicKey, createSecretKey, timingSafeEqual, verify } from "node:crypto";
4
4
  import { promisify } from "node:util";
5
- import { Buffer } from "node:buffer";
6
5
 
7
6
  //#region src/kms/crypto/verify.ts
8
7
  const verify$1 = promisify(verify);
9
8
  function performVerify(key, algorithm, data, signature) {
10
9
  const nodeAlgorithm = mapJwaSignatureAlgorithmToNode(algorithm);
11
- const nodeKey = key.kty === "oct" ? createSecretKey(TypedArrayEncoder.fromBase64(key.k)) : createPublicKey({
10
+ const nodeKey = key.kty === "oct" ? createSecretKey(TypedArrayEncoder.fromBase64Url(key.k)) : createPublicKey({
12
11
  format: "jwk",
13
12
  key
14
13
  });
@@ -20,7 +19,7 @@ function performVerify(key, algorithm, data, signature) {
20
19
  saltLength: Number.parseInt(algorithm.slice(2), 10) / 8
21
20
  } : nodeKey, signature);
22
21
  case "EC": return verify$1(nodeAlgorithm, data, nodeKey, Kms.rawEcSignatureToDer(signature, key.crv));
23
- case "oct": return timingSafeEqual(createHmac(nodeAlgorithm, nodeKey).update(data).digest(), Buffer.from(signature));
22
+ case "oct": return timingSafeEqual(createHmac(nodeAlgorithm, nodeKey).update(data).digest(), signature);
24
23
  default: throw new Kms.KeyManagementAlgorithmNotSupportedError(`kty '${key.kty}'`, "node");
25
24
  }
26
25
  }
@@ -1 +1 @@
1
- {"version":3,"file":"verify.mjs","names":["verify","_verify"],"sources":["../../../src/kms/crypto/verify.ts"],"sourcesContent":["import { Buffer } from 'node:buffer'\nimport {\n verify as _verify,\n constants,\n createHmac,\n createPublicKey,\n createSecretKey,\n timingSafeEqual,\n} from 'node:crypto'\nimport { promisify } from 'node:util'\nimport { type AnyUint8Array, type CanBePromise, Kms, TypedArrayEncoder } from '@credo-ts/core'\n\nimport { mapJwaSignatureAlgorithmToNode } from './sign'\n\nconst verify = promisify(_verify)\n\nexport function performVerify(\n key: Kms.KmsJwkPrivate | Kms.KmsJwkPublicEc | Kms.KmsJwkPublicOkp | Kms.KmsJwkPublicRsa,\n algorithm: Kms.KnownJwaSignatureAlgorithm,\n data: AnyUint8Array,\n signature: AnyUint8Array\n): CanBePromise<boolean> {\n const nodeAlgorithm = mapJwaSignatureAlgorithmToNode(algorithm)\n const nodeKey =\n key.kty === 'oct' ? createSecretKey(TypedArrayEncoder.fromBase64(key.k)) : createPublicKey({ format: 'jwk', key })\n\n switch (key.kty) {\n case 'RSA':\n case 'OKP': {\n const nodeKeyInput = algorithm.startsWith('PS')\n ? // For RSA-PSS, we need to set padding\n {\n key: nodeKey,\n padding: constants.RSA_PKCS1_PSS_PADDING,\n saltLength: Number.parseInt(algorithm.slice(2), 10) / 8,\n }\n : nodeKey\n\n return verify(nodeAlgorithm, data, nodeKeyInput, signature)\n }\n case 'EC': {\n // Node expects DER encoded signature, but we input raw\n return verify(nodeAlgorithm, data, nodeKey, Kms.rawEcSignatureToDer(signature, key.crv))\n }\n case 'oct': {\n const expectedHmac = createHmac(nodeAlgorithm as string, nodeKey)\n .update(data)\n .digest()\n\n return timingSafeEqual(expectedHmac, Buffer.from(signature))\n }\n default:\n // @ts-expect-error\n throw new Kms.KeyManagementAlgorithmNotSupportedError(`kty '${key.kty}'`, 'node')\n }\n}\n"],"mappings":";;;;;;;AAcA,MAAMA,WAAS,UAAUC,OAAQ;AAEjC,SAAgB,cACd,KACA,WACA,MACA,WACuB;CACvB,MAAM,gBAAgB,+BAA+B,UAAU;CAC/D,MAAM,UACJ,IAAI,QAAQ,QAAQ,gBAAgB,kBAAkB,WAAW,IAAI,EAAE,CAAC,GAAG,gBAAgB;EAAE,QAAQ;EAAO;EAAK,CAAC;AAEpH,SAAQ,IAAI,KAAZ;EACE,KAAK;EACL,KAAK,MAUH,QAAOD,SAAO,eAAe,MATR,UAAU,WAAW,KAAK,GAE3C;GACE,KAAK;GACL,SAAS,UAAU;GACnB,YAAY,OAAO,SAAS,UAAU,MAAM,EAAE,EAAE,GAAG,GAAG;GACvD,GACD,SAE6C,UAAU;EAE7D,KAAK,KAEH,QAAOA,SAAO,eAAe,MAAM,SAAS,IAAI,oBAAoB,WAAW,IAAI,IAAI,CAAC;EAE1F,KAAK,MAKH,QAAO,gBAJc,WAAW,eAAyB,QAAQ,CAC9D,OAAO,KAAK,CACZ,QAAQ,EAE0B,OAAO,KAAK,UAAU,CAAC;EAE9D,QAEE,OAAM,IAAI,IAAI,wCAAwC,QAAQ,IAAI,IAAI,IAAI,OAAO"}
1
+ {"version":3,"file":"verify.mjs","names":["verify","_verify"],"sources":["../../../src/kms/crypto/verify.ts"],"sourcesContent":["import {\n verify as _verify,\n constants,\n createHmac,\n createPublicKey,\n createSecretKey,\n timingSafeEqual,\n} from 'node:crypto'\nimport { promisify } from 'node:util'\nimport { type CanBePromise, Kms, TypedArrayEncoder } from '@credo-ts/core'\n\nimport { mapJwaSignatureAlgorithmToNode } from './sign'\n\nconst verify = promisify(_verify)\n\nexport function performVerify(\n key: Kms.KmsJwkPrivate | Kms.KmsJwkPublicEc | Kms.KmsJwkPublicOkp | Kms.KmsJwkPublicRsa,\n algorithm: Kms.KnownJwaSignatureAlgorithm,\n data: Uint8Array,\n signature: Uint8Array\n): CanBePromise<boolean> {\n const nodeAlgorithm = mapJwaSignatureAlgorithmToNode(algorithm)\n const nodeKey =\n key.kty === 'oct'\n ? createSecretKey(TypedArrayEncoder.fromBase64Url(key.k))\n : createPublicKey({ format: 'jwk', key })\n\n switch (key.kty) {\n case 'RSA':\n case 'OKP': {\n const nodeKeyInput = algorithm.startsWith('PS')\n ? // For RSA-PSS, we need to set padding\n {\n key: nodeKey,\n padding: constants.RSA_PKCS1_PSS_PADDING,\n saltLength: Number.parseInt(algorithm.slice(2), 10) / 8,\n }\n : nodeKey\n\n return verify(nodeAlgorithm, data, nodeKeyInput, signature)\n }\n case 'EC': {\n // Node expects DER encoded signature, but we input raw\n return verify(nodeAlgorithm, data, nodeKey, Kms.rawEcSignatureToDer(signature, key.crv))\n }\n case 'oct': {\n const expectedHmac = createHmac(nodeAlgorithm as string, nodeKey)\n .update(data)\n .digest()\n\n return timingSafeEqual(expectedHmac, signature)\n }\n default:\n // @ts-expect-error\n throw new Kms.KeyManagementAlgorithmNotSupportedError(`kty '${key.kty}'`, 'node')\n }\n}\n"],"mappings":";;;;;;AAaA,MAAMA,WAAS,UAAUC,OAAQ;AAEjC,SAAgB,cACd,KACA,WACA,MACA,WACuB;CACvB,MAAM,gBAAgB,+BAA+B,UAAU;CAC/D,MAAM,UACJ,IAAI,QAAQ,QACR,gBAAgB,kBAAkB,cAAc,IAAI,EAAE,CAAC,GACvD,gBAAgB;EAAE,QAAQ;EAAO;EAAK,CAAC;AAE7C,SAAQ,IAAI,KAAZ;EACE,KAAK;EACL,KAAK,MAUH,QAAOD,SAAO,eAAe,MATR,UAAU,WAAW,KAAK,GAE3C;GACE,KAAK;GACL,SAAS,UAAU;GACnB,YAAY,OAAO,SAAS,UAAU,MAAM,EAAE,EAAE,GAAG,GAAG;GACvD,GACD,SAE6C,UAAU;EAE7D,KAAK,KAEH,QAAOA,SAAO,eAAe,MAAM,SAAS,IAAI,oBAAoB,WAAW,IAAI,IAAI,CAAC;EAE1F,KAAK,MAKH,QAAO,gBAJc,WAAW,eAAyB,QAAQ,CAC9D,OAAO,KAAK,CACZ,QAAQ,EAE0B,UAAU;EAEjD,QAEE,OAAM,IAAI,IAAI,wCAAwC,QAAQ,IAAI,IAAI,IAAI,OAAO"}
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  ".": "./build/index.mjs",
5
5
  "./package.json": "./package.json"
6
6
  },
7
- "version": "0.7.0-alpha-20260218222221",
7
+ "version": "0.7.0-alpha-20260401141348",
8
8
  "files": [
9
9
  "build"
10
10
  ],
@@ -26,13 +26,13 @@
26
26
  "express": "^5.2.1",
27
27
  "rxjs": "^7.8.2",
28
28
  "ws": "^8.19.0",
29
- "@credo-ts/core": "0.7.0-alpha-20260218222221",
30
- "@credo-ts/didcomm": "0.7.0-alpha-20260218222221"
29
+ "@credo-ts/core": "0.7.0-alpha-20260401141348",
30
+ "@credo-ts/didcomm": "0.7.0-alpha-20260401141348"
31
31
  },
32
32
  "devDependencies": {
33
33
  "@types/node": "^20.19.31",
34
34
  "@types/ws": "^8.18.1",
35
- "nock": "^14.0.10",
35
+ "nock": "^14.0.11",
36
36
  "typescript": "~5.9.3"
37
37
  },
38
38
  "scripts": {