# engines/sodium-sign-engine _(no submodules)_ ## 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.