4.6 KiB
Crypto Comparison: @fileverse/crypto vs rSpace DocCrypto vs MIT Primitives
Overview
Three options for the encryption layer:
- Keep DocCrypto — rSpace's existing AES-256-GCM + HKDF implementation
- Adopt @fileverse/crypto — Drop-in AGPL library with ECIES, NaCl, Argon2id
- 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
// 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<CryptoKey> {
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<Uint8Array> {
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<CryptoKey> {
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)
{
"@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).