Encryption Algorithms and Key Derivation Functions in ClosedClaw: A Technical Deep Dive
ClosedClaw utilizes XChaCha20-Poly1305 for authenticated encryption and Argon2id for secure key derivation, implemented via the @noble/ciphers and @noble/hashes libraries to protect data at rest.
ClosedClaw’s end-to-end encryption layer relies on modern, audited cryptographic primitives to secure sensitive payloads. This article examines the specific encryption algorithms and key derivation functions (KDFs) implemented in the repository’s security stack, analyzing how src/security/crypto.ts orchestrates XChaCha20-Poly1305 and Argon2id to provide authenticated confidentiality for stored data.
XChaCha20-Poly1305: The Authenticated Encryption Standard
The primary encryption algorithm is XChaCha20-Poly1305, an extended-nonce variant of ChaCha20-Poly1305 that uses a 192-bit (24-byte) nonce. In src/security/crypto.ts, the implementation imports from @noble/ciphers/chacha, specifically using the xchacha20poly1305 constructor for all encryption and decryption operations.
This algorithm provides authenticated encryption with associated data (AEAD), ensuring both confidentiality and integrity of stored payloads. The 192-bit nonce eliminates the risk of collision when using random nonces, a critical safety improvement over the standard 64-bit nonce ChaCha20-Poly1305 variant.
Argon2id: Memory-Hard Key Derivation
For key derivation, ClosedClaw employs Argon2id, the recommended hybrid variant of the Argon2 KDF that provides resistance against both GPU cracking attacks and side-channel analysis. The deriveKey function in src/security/crypto.ts imports the implementation from @noble/hashes/argon2.
KDF parameters—including memory cost, iteration count, parallelism factor, and output key length—are strictly defined in src/security/encryption-types.ts via the EncryptionConfig interface and the DEFAULT_ENCRYPTION_CONFIG constant. These tunable parameters allow the system to balance security margins with performance constraints across different hardware environments.
Security Stack Implementation
Encryption Flow and Key Hierarchy
The security stack follows a deterministic sequence implemented across the core files:
randomBytesgenerates a 32-byte salt and 24-byte nonce for each encryption operation.- The user's passphrase feeds into
deriveKeyalongside these parameters and the Argon2id configuration, producing a 256-bit symmetric key. - This key encrypts plaintext via XChaCha20-Poly1305, generating an authenticated ciphertext envelope.
- The final payload includes the ciphertext, KDF parameters, salt, nonce, and optional key rotation metadata.
Core Source Files
src/security/crypto.ts: Contains theencrypt(),decrypt(),deriveKey(), andgenerateKeyId()implementations that constitute the low-level cryptographic API.src/security/encryption-types.ts: Defines TypeScript interfaces for algorithm specifications, KDF parameter structures, and the payload envelope format.src/security/encrypted-store.ts: High-level wrapper providing transparent JSON file encryption using the primitives above, handling serialization and storage I/O.src/security/skill-signing.ts: Implements Ed25519 signatures for skill authentication, operating independently from the encryption-at-rest stack.
Practical Usage Example
The following TypeScript demonstrates the complete encryption workflow using the actual API surface:
import {
encrypt,
decrypt,
deriveKey,
generateKeyId,
DEFAULT_ENCRYPTION_CONFIG,
} from "./src/security/crypto.js";
import type { EncryptionConfig } from "./src/security/encryption-types.js";
/* 1️⃣ Derive a symmetric key from a passphrase (Argon2id) */
const passphrase = "my‑strong‑password";
const salt = crypto.getRandomValues(new Uint8Array(32));
const kdfParams = DEFAULT_ENCRYPTION_CONFIG.kdfParams; // memory, iterations, …
const key = deriveKey({ passphrase, salt, kdfParams });
/* 2️⃣ Encrypt a message (XChaCha20‑Poly1305) */
const plaintext = "Sensitive data that must be stored securely.";
const encrypted = encrypt({
plaintext,
passphrase,
config: DEFAULT_ENCRYPTION_CONFIG,
keyId: generateKeyId(),
});
/* 3️⃣ Decrypt the payload */
const recovered = decrypt({ payload: encrypted, passphrase });
console.assert(recovered === plaintext);
The encrypted-store.ts module utilizes this same API to transparently encrypt and decrypt JSON persistence files, ensuring all data at rest is protected by these primitives.
Summary
- ClosedClaw implements XChaCha20-Poly1305 via
@noble/ciphers/chachafor authenticated encryption, utilizing 192-bit nonces to prevent collision vulnerabilities. - Argon2id from
@noble/hashes/argon2handles secure key derivation functions with memory-hard parameters defined inencryption-types.ts. - The
deriveKeyfunction insrc/security/crypto.tsproduces 256-bit symmetric keys from user passphrases combined with 32-byte random salts. - Encrypted payloads include the ciphertext, nonce, salt, and KDF parameters in a structured envelope managed by the core crypto module.
- Ed25519 signatures in
skill-signing.tsprovide complementary signing capabilities distinct from the encryption layer.
Frequently Asked Questions
Does ClosedClaw use AES-256 for encryption?
No. According to the source code in src/security/crypto.ts, ClosedClaw exclusively uses XChaCha20-Poly1305 for symmetric encryption. This modern stream cipher eliminates timing side-channels present in AES software implementations and supports safer nonce handling with its extended 192-bit nonce space, reducing the complexity of nonce management schemes.
What Argon2id parameters does ClosedClaw use for key derivation?
The specific memory cost, iterations, and parallelism settings are encapsulated in DEFAULT_ENCRYPTION_CONFIG within src/security/encryption-types.ts. These parameters feed into the deriveKey function to tune the memory-hard property of Argon2id, allowing the system to adapt to target security levels and hardware constraints without modifying the core cryptographic implementation.
How does ClosedClaw handle nonce generation?
The implementation generates a 24-byte (192-bit) random nonce using randomBytes for every encryption operation in src/security/crypto.ts. This extended nonce size, specific to XChaCha20-Poly1305, allows for safer random nonce generation without requiring complex stateful nonce-management schemes, as the probability of collision becomes statistically negligible even with billions of encrypted messages.
Where is the encrypted data stored in ClosedClaw?
The src/security/encrypted-store.ts module provides the storage abstraction, transparently reading and writing JSON files encrypted with the XChaCha20-Poly1305 and Argon2id stack. This module utilizes the same encrypt and decrypt functions exposed in crypto.ts to ensure consistent cryptographic handling across the application, managing the serialization of KDF parameters and metadata alongside the ciphertext.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →