first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,93 @@
# 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
```ts
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:
```ts
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).