Files
skills/docs/security-stack/crypto/crypto-sodium/src/engines/sodium-agree-engine/sodium-agree-engine.md
2026-05-29 08:20:56 +01:00

3.2 KiB

engines/sodium-agree-engine

(no submodules)

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

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:

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.