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,78 @@
# 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<string, RsaPrivateKey>` 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<RsaPrivateKey>`
- `sign(handle, message, options): Promise<Uint8Array>`
- `decrypt(handle, ciphertext, options): Promise<Uint8Array>`
## 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.