fileverse/docs/crypto-comparison.md

4.6 KiB
Raw Blame History

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) 07KB
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).