2.9 KiB
2.9 KiB
handle/registry
Purpose
Process-wide registry for RSA key-handle providers. Every HSM, KMS, OS
keychain, or PKCS#11 bridge registers a provider once at startup; the
registry resolves opaque RsaKeyHandle values to the matching provider
at call time and dispatches resolve / sign / decrypt operations
through it. Decouples consumer code from any specific hardware
backend.
Features
- Single in-process registry keyed by provider name
- Idempotent re-registration of the same provider value
- Conflicting registration of a different provider under the same name
rejects with
INVALID_KEY signWithHandle/decryptWithHandlemirror theRsaCryptoEnginesurface so handle consumers and engine consumers share the same scheme-options shapeunregisterKeyHandleProviderexposed for test cleanup
Usage: Basic Example
import {
registerKeyHandleProvider,
signWithHandle,
} from "@suaveplan/crypto-rsa/handle";
registerKeyHandleProvider(myHsmProvider);
const sig = await signWithHandle(
{ provider: "my-hsm", id: "key-1" },
message,
{ scheme: "pkcs1v15", hash: "SHA-256" }
);
Usage: Advanced Example
For test setups that need a clean registry per test:
import {
registerKeyHandleProvider,
unregisterKeyHandleProvider,
SoftwareRsaKeyHandleProvider,
} from "@suaveplan/crypto-rsa/handle";
beforeEach(() => {
registerKeyHandleProvider(new SoftwareRsaKeyHandleProvider());
});
afterEach(() => {
unregisterKeyHandleProvider("software");
});
API Reference
registerKeyHandleProvider(provider)
provider: RsaKeyHandleProvider- throws
CryptoRsaError(CRYPTO_RSA.INVALID_KEY)on conflicting registration of a different provider under the same name
unregisterKeyHandleProvider(name)
name: string
resolveKeyHandle(handle): Promise<RsaPublicKey | RsaPrivateKey>
- throws
CryptoRsaError(CRYPTO_RSA.INVALID_KEY)when no provider is registered under the handle'sprovidername
signWithHandle(handle, message, options): Promise<Uint8Array>
decryptWithHandle(handle, ciphertext, options): Promise<Uint8Array>
Implementation Notes
- The registry is a module-level
Map<string, RsaKeyHandleProvider>. The chosen scope is process-lifetime; if cross-process or per-vault isolation is required, callers must wrap their own dispatch layer. - Idempotent registration of the same provider value (object identity comparison) is a no-op so that import-once-then-register patterns work without per-import side effects.
- Conflicting registration (two different provider objects with the same name) raises a typed error instead of silently winning — this is to detect copy-paste mistakes between adapters during integration.
- Handle resolution failures throw
INVALID_KEYbecause from the caller's perspective the supplied handle was not valid (the underlying cause — provider unregistered, id unknown — is captured in the error context).