UNPKG

@credo-ts/core

Version:

<p align="center"> <br /> <img alt="Credo Logo" src="https://github.com/openwallet-foundation/credo-ts/blob/c7886cb8377ceb8ee4efe8d264211e561a75072d/images/credo-logo.png" height="250px" /> </p> <h1 align="center"><b>Credo - Core</b></h1

218 lines (217 loc) • 10.6 kB
import { AgentContext } from "../../agent/context/AgentContext.mjs"; import { injectable } from "../../plugins/index.mjs"; import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.151.0/helpers/esm/decorateMetadata.mjs"; import __decorate from "../../_virtual/_@oxc-project_runtime@0.151.0/helpers/esm/decorate.mjs"; import "../../agent/index.mjs"; import { KeyManagementError } from "./error/KeyManagementError.mjs"; import { KeyManagementKeyNotFoundError } from "./error/KeyManagementKeyNotFoundError.mjs"; import { getJwkHumanDescription } from "./jwk/humanDescription.mjs"; import { createKeyTypeForSigningAlgorithm } from "./jwk/alg/signing.mjs"; import { zParseWithErrorHandling } from "../../utils/zod.mjs"; import "./jwk/index.mjs"; import { KeyManagementModuleConfig } from "./KeyManagementModuleConfig.mjs"; import { zKmsEncryptOptions } from "./options/KmsEncryptOptions.mjs"; import { getKmsOperationHumanDescription } from "./options/KmsOperation.mjs"; import "./options/index.mjs"; import { zWithBackend } from "./options/backend.mjs"; import { zKmsCreateKeyForSignatureAlgorithmOptions, zKmsCreateKeyOptions } from "./options/KmsCreateKeyOptions.mjs"; import { zKmsDecryptOptions } from "./options/KmsDecryptOptions.mjs"; import { zKmsDeleteKeyOptions } from "./options/KmsDeleteKeyOptions.mjs"; import { zKmsGetPublicKeyOptions } from "./options/KmsGetPublicKeyOptions.mjs"; import { zKmsImportKeyOptions } from "./options/KmsImportKeyOptions.mjs"; import { zKmsRandomBytesOptions } from "./options/KmsRandomBytesOptions.mjs"; import { zKmsSignOptions } from "./options/KmsSignOptions.mjs"; import { zKmsVerifyOptions } from "./options/KmsVerifyOptions.mjs"; //#region src/modules/kms/KeyManagementApi.ts let KeyManagementApi = class KeyManagementApi { constructor(keyManagementConfig, agentContext) { this.keyManagementConfig = keyManagementConfig; this.agentContext = agentContext; } /** * Whether an operation is supported. * * @returns a list of backends that support the operation. In case * no backends are supported it returns an empty array */ supportedBackendsForOperation(operation) { const supportedBackends = []; for (const kms of this.keyManagementConfig.backends) if (kms.isOperationSupported(this.agentContext, operation)) supportedBackends.push(kms.backend); return supportedBackends; } /** * Create a key. */ async createKey(options) { const { backend, ...kmsOptions } = zParseWithErrorHandling(zWithBackend(zKmsCreateKeyOptions), options, "Invalid options provided to createKey method"); const key = await this.getKms(this.agentContext, backend, { operation: "createKey", type: options.type }).createKey(this.agentContext, kmsOptions); key.publicJwk.kid = key.keyId; this.agentContext.config.logger.debug(`Created key ${getJwkHumanDescription(key.publicJwk)} with key id '${key.keyId}'`); return key; } /** * Create a key. */ async createKeyForSignatureAlgorithm(options) { const { backend, algorithm, ...kmsOptions } = zParseWithErrorHandling(zWithBackend(zKmsCreateKeyForSignatureAlgorithmOptions), options, "Invalid options provided to createKeyForSignatureAlgorithm method"); const type = createKeyTypeForSigningAlgorithm(algorithm); const key = await this.getKms(this.agentContext, backend, { operation: "createKey", type }).createKey(this.agentContext, { ...kmsOptions, type }); key.publicJwk.kid = key.keyId; return key; } /** * Sign using a key. */ async sign(options) { const { backend, ...kmsOptions } = zParseWithErrorHandling(zWithBackend(zKmsSignOptions), options, "Invalid options provided to sign method"); const operation = { operation: "sign", algorithm: options.algorithm }; return await (backend ? this.getKms(this.agentContext, backend, operation) : (await this.getKmsForOperationAndKeyId(this.agentContext, options.keyId, operation)).kms).sign(this.agentContext, kmsOptions); } /** * Verify using a key. */ async verify(options) { const { backend, ...kmsOptions } = zParseWithErrorHandling(zWithBackend(zKmsVerifyOptions), options, "Invalid options provided to verify method"); const operation = { operation: "verify", algorithm: options.algorithm }; const keyId = options.key.keyId; return await (backend || !keyId ? this.getKms(this.agentContext, backend, operation) : (await this.getKmsForOperationAndKeyId(this.agentContext, keyId, operation)).kms).verify(this.agentContext, kmsOptions); } /** * Encrypt. */ async encrypt(options) { const { backend, ...kmsOptions } = zParseWithErrorHandling(zWithBackend(zKmsEncryptOptions), options, "Invalid options provided to encrypt method"); const operation = { operation: "encrypt", encryption: options.encryption, keyAgreement: options.key.keyAgreement }; const keyId = routingKeyId(options.key); return await (backend || !keyId ? this.getKms(this.agentContext, backend, operation) : (await this.getKmsForOperationAndKeyId(this.agentContext, keyId, operation)).kms).encrypt(this.agentContext, kmsOptions); } /** * Decrypt. */ async decrypt(options) { const { backend, ...kmsOptions } = zParseWithErrorHandling(zWithBackend(zKmsDecryptOptions), options, "Invalid options provided to decrypt method"); const operation = { operation: "decrypt", decryption: options.decryption, keyAgreement: options.key.keyAgreement }; const keyId = routingKeyId(options.key); return await (backend || !keyId ? this.getKms(this.agentContext, backend, operation) : (await this.getKmsForOperationAndKeyId(this.agentContext, keyId, operation)).kms).decrypt(this.agentContext, kmsOptions); } /** * Import a key. */ async importKey(options) { const { backend, ...kmsOptions } = zParseWithErrorHandling(zWithBackend(zKmsImportKeyOptions), options, "Invalid options provided to importKey method"); const operation = { operation: "importKey", privateJwk: options.privateJwk }; const key = await this.getKms(this.agentContext, backend, operation).importKey(this.agentContext, kmsOptions); this.agentContext.config.logger.trace(`Imported key ${getJwkHumanDescription(key.publicJwk)} with key id '${key.keyId}'`); return key; } /** * Get a public key. */ async getPublicKey(options) { const { backend, keyId } = zParseWithErrorHandling(zWithBackend(zKmsGetPublicKeyOptions), options, "Invalid options provided to getPublicKey method"); if (backend) { if (!await this.getKms(this.agentContext, backend).getPublicKey(this.agentContext, keyId)) throw new KeyManagementKeyNotFoundError(keyId, [backend]); } const { publicKey } = await this.getKmsForOperationAndKeyId(this.agentContext, options.keyId); return publicKey; } /** * Delete a key. */ async deleteKey(options) { const { backend, ...kmsOptions } = zParseWithErrorHandling(zWithBackend(zKmsDeleteKeyOptions), options, "Invalid options provided to deleteKey method"); return await this.getKms(this.agentContext, backend, { operation: "deleteKey" }).deleteKey(this.agentContext, kmsOptions); } /** * Generate random bytes */ randomBytes(options) { const { backend, ...kmsOptions } = zParseWithErrorHandling(zWithBackend(zKmsRandomBytesOptions), options, "Invalid options provided to randomBytes method"); return this.getKms(this.agentContext, backend, { operation: "randomBytes" }).randomBytes(this.agentContext, kmsOptions); } /** * Get the kms associated with a specific `keyId`. * * This uses a naive approach of fetching the key for each configured kms * until it finds the registered key. * * In the future this approach might be optimized based on: * - caching * - keeping a registry * - backend specific key prefixes */ async getKmsForOperationAndKeyId(agentContext, keyId, operation) { for (const kms of this.keyManagementConfig.backends) { if (operation && !kms.isOperationSupported(agentContext, operation)) continue; const publicKey = await kms.getPublicKey(this.agentContext, keyId); if (publicKey) return { publicKey, kms }; } throw new KeyManagementKeyNotFoundError(keyId, this.keyManagementConfig.backends.map((b) => b.backend), operation ? `The key may exist in one of the key management services in which case the key management service does not support the ${getKmsOperationHumanDescription(operation)}` : void 0); } /** * Get the kms backend for a specific operation. * * If a backend is provided, it will be checked if the backend supports * the operation. Otherwise the default backend (the `defaultBackend` from * the `KeyManagementModuleConfig`, or the first registered backend if no * `defaultBackend` was configured) will be used if it supports the operation. * If the default backend does not support the operation, the first other * backend that supports the operation will be used and a warning will be logged. */ getKms(agentContext, backend, operation) { const backends = this.keyManagementConfig.backends; if (backend) { const kms = backends.find((kms) => kms.backend === backend); if (!kms) { const availableBackends = backends.map((kms) => `'${kms.backend}'`); throw new KeyManagementError(`No key management service is configured for backend '${backend}'. Available backends are ${availableBackends.join(", ")}`); } if (operation && !kms.isOperationSupported(agentContext, operation)) throw new KeyManagementError(`Key management service backend '${backend}' does not support ${getKmsOperationHumanDescription(operation)}`); return kms; } if (backends.length > 0) { const defaultKms = this.keyManagementConfig.defaultBackend; if (!operation || defaultKms.isOperationSupported(agentContext, operation)) return defaultKms; const fallbackKms = backends.find((kms) => kms !== defaultKms && kms.isOperationSupported(agentContext, operation)); if (fallbackKms) return fallbackKms; } throw new KeyManagementError(operation ? `No key management service backend found that supports ${getKmsOperationHumanDescription(operation)}` : "No key management service backend found."); } }; KeyManagementApi = __decorate([injectable(), __decorateMetadata("design:paramtypes", [typeof KeyManagementModuleConfig === "undefined" ? Object : KeyManagementModuleConfig, typeof AgentContext === "undefined" ? Object : AgentContext])], KeyManagementApi); function routingKeyId(key) { if (key.keyId) return key.keyId; if (key.keyAgreement && "keyId" in key.keyAgreement) return key.keyAgreement.keyId; } //#endregion export { KeyManagementApi }; //# sourceMappingURL=KeyManagementApi.mjs.map