# Crypto Comparison: @fileverse/crypto vs rSpace DocCrypto vs MIT Primitives ## Overview Three options for the encryption layer: 1. **Keep DocCrypto** — rSpace's existing AES-256-GCM + HKDF implementation 2. **Adopt @fileverse/crypto** — Drop-in AGPL library with ECIES, NaCl, Argon2id 3. **Build from MIT primitives** — Same capabilities as Fileverse but without AGPL ## Primitive-Level Comparison ### Symmetric Encryption | | DocCrypto | @fileverse/crypto | MIT Build | |--|-----------|-------------------|-----------| | Algorithm | AES-256-GCM | XSalsa20-Poly1305 (NaCl SecretBox) | Either | | Implementation | Web Crypto API | TweetNaCl.js | Web Crypto or TweetNaCl | | Key size | 256 bits | 256 bits | 256 bits | | Nonce | 96 bits (random) | 192 bits (random) | Depends on choice | | Auth tag | 128 bits | 128 bits (Poly1305) | Depends on choice | | Bundle size | 0 (native) | ~7KB (tweetnacl) | 0–7KB | | Performance | Fastest (hardware) | Fast (pure JS) | Fastest if Web Crypto | **Analysis:** AES-256-GCM via Web Crypto is faster (hardware acceleration) and adds 0 bundle size. NaCl SecretBox is simpler to use correctly (larger nonce = less collision risk). For rStack, Web Crypto AES-256-GCM is the better choice — it's already battle-tested in DocCrypto. ### Asymmetric Encryption (Gap in DocCrypto) | | DocCrypto | @fileverse/crypto | MIT Build | |--|-----------|-------------------|-----------| | ECIES | Not implemented | ✅ (secp256k1) | Noble curves | | RSA | Not implemented | ✅ (envelope) | Web Crypto | | Key exchange | Not implemented | ECDH shared secret | Noble/StableLib x25519 | **Analysis:** This is the main gap. DocCrypto only does symmetric encryption — it can't share encryption keys between users without a trusted server. ECIES allows encrypting a document key so only a specific collaborator's private key can decrypt it. ### Key Derivation | | DocCrypto | @fileverse/crypto | MIT Build | |--|-----------|-------------------|-----------| | HKDF | ✅ (Web Crypto) | ✅ (StableLib) | Web Crypto | | Argon2id | Not implemented | ✅ (argon2-browser WASM) | argon2-browser | | Key hierarchy | Master → Space → Doc | Flat | Custom | **Analysis:** DocCrypto's key hierarchy is more sophisticated. Fileverse derives keys per-operation. For rStack, keep DocCrypto's hierarchy and add Argon2id for password-protected sharing. ## Recommendation ### Extend DocCrypto with MIT Primitives ```typescript // Additions to rspace-online/shared/local-first/crypto.ts import { x25519 } from '@noble/curves/ed25519' import { hkdf } from '@noble/hashes/hkdf' import { sha256 } from '@noble/hashes/sha256' import argon2 from 'argon2-browser' class DocCrypto { // ... existing AES-256-GCM + HKDF methods ... // NEW: Key exchange for multi-user collaboration static async deriveSharedSecret( myPrivateKey: Uint8Array, theirPublicKey: Uint8Array ): Promise { const shared = x25519.getSharedSecret(myPrivateKey, theirPublicKey) return this.importKey(shared) } // NEW: Encrypt document key for a specific collaborator static async encryptKeyForUser( docKey: Uint8Array, recipientPublicKey: Uint8Array, senderPrivateKey: Uint8Array ): Promise { const sharedSecret = x25519.getSharedSecret(senderPrivateKey, recipientPublicKey) const wrappingKey = hkdf(sha256, sharedSecret, null, 'rstack-key-wrap', 32) // Encrypt docKey with wrappingKey using existing AES-256-GCM return this.encrypt(wrappingKey, docKey) } // NEW: Password-protected note sharing static async deriveKeyFromPassword( password: string, salt: Uint8Array ): Promise { const result = await argon2.hash({ pass: password, salt: salt, type: argon2.ArgonType.Argon2id, hashLen: 32, time: 3, mem: 65536, parallelism: 1, }) return this.importKey(result.hash) } } ``` ### Dependencies (All MIT) ```json { "@noble/curves": "^1.4.0", "@noble/hashes": "^1.4.0", "argon2-browser": "^1.18.0" } ``` ### Bundle Size Impact | Package | Size (min+gzip) | |---------|----------------| | @noble/curves (x25519 only) | ~8KB | | @noble/hashes (sha256+hkdf) | ~4KB | | argon2-browser (WASM) | ~30KB | | **Total** | **~42KB** | vs `@fileverse/crypto` full package: ~45KB (similar, but with AGPL) ## Interoperability If we build from the same MIT primitives Fileverse uses, we maintain the option to: - Decrypt content encrypted by Fileverse apps - Share encrypted documents with Fileverse users - Participate in Fileverse collaboration rooms The key is using compatible curve parameters (secp256k1 or x25519) and matching the encryption format (nonce || ciphertext || tag).