# engines/sodium-auth-box-engine _(no submodules)_ ## Purpose `sodiumAuthBoxEngine` implements the `AuthBoxEngine` interface from `@suaveplan/crypto` using libsodium's `crypto_box_easy` and `crypto_box_open_easy`. This construction provides authenticated key-exchange encryption: both the sender and recipient are authenticated because the shared secret is derived from a static X25519 DH between sender's secret and recipient's public key, then used to encrypt with XSalsa20-Poly1305. Unlike `sodiumSealedBoxEngine`, the sender's public key is not included in the ciphertext — the recipient must already know who sent the message (i.e., possess the sender's public key independently). ## Features - Mutually authenticated encryption using `crypto_box_easy` / `crypto_box_open_easy`. - XSalsa20-Poly1305 authenticated encryption via X25519 key agreement. - 24-byte explicit nonce required from caller. - 16-byte MAC overhead in the ciphertext. - Throws `SodiumError` on authentication failure during `open`. - Conforms to `AuthBoxEngine` from `@suaveplan/crypto/engines`. ## Usage: Basic Example ```ts import { sodiumReady } from "@suaveplan/crypto-sodium/init"; import { sodiumAgreeEngine } from "@suaveplan/crypto-sodium/engines/agree"; import { sodiumAuthBoxEngine } from "@suaveplan/crypto-sodium/engines/auth-box"; await sodiumReady(); const alice = sodiumAgreeEngine.generateKeypair(); const bob = sodiumAgreeEngine.generateKeypair(); const nonce = crypto.getRandomValues(new Uint8Array(24)); const msg = new TextEncoder().encode("authenticated message"); // Alice sends to Bob const ct = sodiumAuthBoxEngine.seal( alice.secretKey, bob.publicKey, msg, nonce ); // Bob receives from Alice const pt = sodiumAuthBoxEngine.open( alice.publicKey, bob.secretKey, ct, nonce ); console.log(new TextDecoder().decode(pt)); // "authenticated message" ``` ## Usage: Advanced Example Bidirectional messaging channel with distinct nonce counters per direction: ```ts import { sodiumReady } from "@suaveplan/crypto-sodium/init"; import { sodiumAgreeEngine } from "@suaveplan/crypto-sodium/engines/agree"; import { sodiumAuthBoxEngine } from "@suaveplan/crypto-sodium/engines/auth-box"; await sodiumReady(); const alice = sodiumAgreeEngine.generateKeypair(); const bob = sodiumAgreeEngine.generateKeypair(); function incrementNonce(nonce: Uint8Array): Uint8Array { const n = nonce.slice(); for (let i = n.length - 1; i >= 0; i--) { if (++n[i]) break; } return n; } let aliceNonce = new Uint8Array(24); const ct1 = sodiumAuthBoxEngine.seal( alice.secretKey, bob.publicKey, new TextEncoder().encode("msg 1"), aliceNonce ); aliceNonce = incrementNonce(aliceNonce); ``` ## API Reference ### `sodiumAuthBoxEngine: AuthBoxEngine` Singleton engine. ### `seal(senderSecret, recipientPublic, plaintext, nonce): Uint8Array` Encrypts `plaintext` using `crypto_box_easy`. Returns ciphertext with 16-byte MAC prepended. **Parameters:** - `senderSecret` — sender's 32-byte secret key. - `recipientPublic` — recipient's 32-byte public key. - `plaintext` — message bytes. - `nonce` — 24-byte nonce (must be unique per message under the same keypair). ### `open(senderPublic, recipientSecret, ciphertext, nonce): Uint8Array` Decrypts and authenticates. Both keys must correspond to the same exchange as `seal`. **Throws:** `SodiumError` (`SODIUM.INIT.FAILED`) if MAC verification fails. ## Implementation Notes `crypto_box_easy` computes `Curve25519(senderSecret, recipientPublic)` as the shared secret and uses HSalsa20 as KDF before XSalsa20-Poly1305. Nonces must be 24 bytes. The nonce management strategy (random, counter, or derived) is left to the caller — each (keypair, nonce) pair must be used at most once for confidentiality. The MAC overhead is 16 bytes (`crypto_box_MACBYTES`). The nonce must be transmitted alongside the ciphertext; a common convention is to prepend it to the ciphertext.