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,81 @@
# engines/sodium-agree-engine
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
`sodiumAgreeEngine` implements the `AgreeEngine` interface from `@suaveplan/crypto` using libsodium's X25519 Diffie-Hellman key agreement. X25519 is the modern industry-standard ECDH scheme used in TLS 1.3, Signal, Noise Protocol, and WireGuard.
The engine produces a raw 32-byte shared secret from two Curve25519 keypairs. Callers are responsible for deriving a symmetric key from this shared secret — use `cryptoKdf` or a KDF such as HKDF for this purpose.
## Features
- X25519 keypair generation via `crypto_kx_keypair` — Curve25519 points compatible with `crypto_scalarmult`.
- Diffie-Hellman shared secret via `crypto_scalarmult` — raw X25519 output, 32 bytes.
- Conforms to `AgreeEngine` from `@suaveplan/crypto/engines` — pluggable into any higher-level key-exchange protocol.
- `sodiumReady()` must be awaited before first use.
## Usage: Basic Example
```ts
import { sodiumReady } from "@suaveplan/crypto-sodium/init";
import { sodiumAgreeEngine } from "@suaveplan/crypto-sodium/engines/agree";
await sodiumReady();
const alice = sodiumAgreeEngine.generateKeypair();
const bob = sodiumAgreeEngine.generateKeypair();
const aliceShared = sodiumAgreeEngine.agree(alice.secretKey, bob.publicKey);
const bobShared = sodiumAgreeEngine.agree(bob.secretKey, alice.publicKey);
// aliceShared deepEquals bobShared — both parties derived the same secret
```
## Usage: Advanced Example
Combining X25519 agree with KDF for a symmetric key:
```ts
import { sodiumReady } from "@suaveplan/crypto-sodium/init";
import { sodiumAgreeEngine } from "@suaveplan/crypto-sodium/engines/agree";
import { cryptoKdf } from "@suaveplan/crypto-sodium/primitives/kdf";
await sodiumReady();
const alice = sodiumAgreeEngine.generateKeypair();
const bob = sodiumAgreeEngine.generateKeypair();
// Raw shared secret — not safe to use directly as a key
const rawSecret = sodiumAgreeEngine.agree(alice.secretKey, bob.publicKey);
// Derive a 32-byte encryption key via KDF
const encKey = await cryptoKdf(rawSecret, 1, "EncryptN", 32);
```
## API Reference
### `sodiumAgreeEngine: AgreeEngine`
Singleton engine object.
### `generateKeypair(byteSource?: ByteSource): AgreeKeypair`
Generates a fresh Curve25519 keypair. `byteSource` is accepted for interface compatibility but ignored.
**Returns:** `{ publicKey: Uint8Array (32 bytes), secretKey: Uint8Array (32 bytes) }`
### `agree(mySecret: Uint8Array, theirPublic: Uint8Array): Uint8Array`
Performs X25519 Diffie-Hellman.
**Returns:** 32-byte raw shared secret.
## Implementation Notes
`crypto_kx_keypair` produces Curve25519 keypairs that are fully compatible with `crypto_scalarmult`. The `crypto_kx_*` family includes session-key derivation helpers, but this engine uses `crypto_scalarmult` directly to return the raw shared secret, giving callers full control over key derivation.
The raw X25519 output is a group element, not a uniformly random key. It MUST be passed through a KDF before use in a symmetric cipher. See `cryptoKdf` in `@suaveplan/crypto-sodium/primitives/kdf` for the libsodium-native option.
`byteSource` is not forwarded to libsodium for the same reason as in `sodiumSignEngine` — libsodium's WASM manages entropy internally.