# handle/software ## Purpose Reference `RsaKeyHandleProvider` wrapping in-memory `RsaPrivateKey` values. Implements the same interface as a real HSM bridge but with zero hardware dependency, so consumers can develop and test handle-based code paths without an HSM. Production workloads typically replace this with their own provider (PKCS#11, AWS KMS, Apple Keychain via `@suaveplan/macos-keychain`, etc.). ## Features - Implements every `RsaKeyHandleProvider` method - Stores keys in a process-local `Map` keyed by handle id - Sign / decrypt route through `nobleEngine` so semantics match the rest of the package exactly - `register(id, key)` returns the matching `RsaKeyHandle` for ergonomic test setups ## Usage: Basic Example ```ts import { registerKeyHandleProvider, signWithHandle, } from "@suaveplan/crypto-rsa/handle"; import { SoftwareRsaKeyHandleProvider } from "@suaveplan/crypto-rsa/handle"; const provider = new SoftwareRsaKeyHandleProvider(); registerKeyHandleProvider(provider); const handle = provider.register("test-key", privateKey); const sig = await signWithHandle(handle, message, { scheme: "pkcs1v15", hash: "SHA-256", }); ``` ## Usage: Advanced Example Use the software provider to drive integration tests that exercise the handle-based code path of a downstream consumer (e.g. a JWS signer that accepts `RsaKeyHandle` instead of an in-memory key): ```ts import { SoftwareRsaKeyHandleProvider } from "@suaveplan/crypto-rsa/handle"; import { registerKeyHandleProvider } from "@suaveplan/crypto-rsa/handle"; const provider = new SoftwareRsaKeyHandleProvider(); registerKeyHandleProvider(provider); const handle = provider.register("k1", testKey); // Downstream consumer uses the handle exactly as it would an HSM key. const jws = await jwsSigner.sign(payload, handle); ``` ## API Reference ### `class SoftwareRsaKeyHandleProvider` - `name: "software"` (readonly) - `register(id: string, key: RsaPrivateKey): RsaKeyHandle` - `resolve(handle): Promise` - `sign(handle, message, options): Promise` - `decrypt(handle, ciphertext, options): Promise` ## Implementation Notes - The provider is class-based (vs the module-singleton style of `nobleEngine`) so consumers can spin up multiple instances for parallel-test isolation. Each instance has its own internal Map. - Sign/decrypt delegate to `nobleEngine` directly — this provider is a pure JS reference; HSM-backed providers replace these methods with the appropriate `crypto.subtle` / PKCS#11 / KMS API calls. - The "handle id missing" failure throws a plain `Error` (NOT a `CryptoRsaError`) because the caller is the registry layer; the registry maps it to a typed error before reaching application code.