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,88 @@
# engines/sodium-sign-engine
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
`sodiumSignEngine` implements the `SignEngine` interface from `@suaveplan/crypto` using libsodium's Ed25519 signing primitives. Ed25519 is a deterministic signature scheme based on the Edwards-curve digital signature algorithm — it provides strong security guarantees, fast verification, and small key and signature sizes.
This engine replaces the noble-curves default in performance-sensitive or server-side scenarios where the libsodium WASM path is preferred for its maturity and NIST/IETF certification heritage.
## Features
- Ed25519 keypair generation via `crypto_sign_keypair` — uses libsodium's internal secure entropy.
- Detached signature creation via `crypto_sign_detached` — signature is separate from the message.
- Detached signature verification via `crypto_sign_verify_detached` — returns boolean, never throws on invalid signatures.
- 32-byte public keys, 64-byte secret keys (includes seed), 64-byte signatures.
- Conforms to `SignEngine` from `@suaveplan/crypto/engines` — drop-in for the noble default.
## Usage: Basic Example
```ts
import { sodiumReady } from "@suaveplan/crypto-sodium/init";
import { sodiumSignEngine } from "@suaveplan/crypto-sodium/engines/sign";
await sodiumReady();
const kp = sodiumSignEngine.generateKeypair();
const msg = new TextEncoder().encode("sign this");
const sig = sodiumSignEngine.sign(kp.secretKey, msg);
const valid = sodiumSignEngine.verify(kp.publicKey, sig, msg);
console.log(valid); // true
```
## Usage: Advanced Example
Using `sodiumSignEngine` as a pluggable engine with `@suaveplan/crypto`:
```ts
import { sodiumReady } from "@suaveplan/crypto-sodium/init";
import { sodiumSignEngine } from "@suaveplan/crypto-sodium/engines/sign";
import type { SignEngine } from "@suaveplan/crypto/engines";
await sodiumReady();
function signDocument(
engine: SignEngine,
secretKey: Uint8Array,
document: Uint8Array
): Uint8Array {
return engine.sign(secretKey, document);
}
const kp = sodiumSignEngine.generateKeypair();
const doc = new TextEncoder().encode("legal document text");
const sig = signDocument(sodiumSignEngine, kp.secretKey, doc);
// Verify on the receiving side:
const ok = sodiumSignEngine.verify(kp.publicKey, sig, doc);
```
## API Reference
### `sodiumSignEngine: SignEngine`
Singleton engine object.
### `generateKeypair(byteSource?: ByteSource): SignKeypair`
Generates a fresh Ed25519 keypair. The `byteSource` parameter is accepted for interface compatibility but ignored — libsodium manages its own CSPRNG.
**Returns:** `{ publicKey: Uint8Array (32 bytes), secretKey: Uint8Array (64 bytes) }`
### `sign(secretKey: Uint8Array, message: Uint8Array): Uint8Array`
Produces a 64-byte detached Ed25519 signature over `message`.
### `verify(publicKey: Uint8Array, signature: Uint8Array, message: Uint8Array): boolean`
Verifies a detached signature. Returns `false` rather than throwing on any verification failure (wrong key, tampered sig, wrong message). Exceptions from libsodium are caught and mapped to `false`.
## Implementation Notes
libsodium's `crypto_sign_keypair()` returns `{ publicKey, privateKey }` — note the property is named `privateKey` in the TS bindings despite being the full 64-byte secret key (seed + public key concatenated). The engine remaps this to `secretKey` to match the `SignKeypair` interface.
The `byteSource` parameter is not forwarded to libsodium because libsodium's WASM module manages entropy internally. Callers cannot substitute an alternative random source for key generation via this engine.
`verify` wraps `crypto_sign_verify_detached` in a try/catch because libsodium throws for structurally malformed inputs (e.g., a signature buffer that is not 64 bytes), mapping those to `false` for consistency with the `SignEngine` contract.