Files
skills/docs/security-stack/crypto/crypto-rsa/src/handle/registry.md
2026-05-29 08:20:56 +01:00

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 / decryptWithHandle mirror the RsaCryptoEngine surface so handle consumers and engine consumers share the same scheme-options shape
  • unregisterKeyHandleProvider exposed 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's provider name

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_KEY because from the caller's perspective the supplied handle was not valid (the underlying cause — provider unregistered, id unknown — is captured in the error context).