first commit
This commit is contained in:
@@ -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.
|
||||
Reference in New Issue
Block a user