[Code Review] XChaCha20-Poly1305 + Ed25519 sync protocol — correct crypto usage?

⚓ Rust    📅 2026-02-23    👤 surdeus    👁️ 5      

surdeus

[Code Review] SYNC-0: XChaCha20-Poly1305 + Ed25519 pack/grant protocol — looking for feedback on crypto usage

Hi,

I'm building a local-first medical scheduling app (PraxisTools) with an end-to-end encrypted folder-based sync protocol (no server, iCloud/Dropbox as untrusted transport).

I'd appreciate a review of my crypto usage — specifically whether I'm using XChaCha20-Poly1305, Ed25519 and BLAKE3 correctly and securely.

What the protocol does:

  • Devices pair offline via signed .ptgrant files (Ed25519, sealed group key via X25519)
  • Each device writes encrypted packs (XChaCha20-Poly1305) with device signature over (header || ciphertext || tag)
  • Header is AAD, includes msg_type for domain separation
  • Nonces are random (OsRng), stored in pack header, no reuse via durable draft + atomic rename
  • BLAKE3 for pack_hash and chain integrity
  • Checkpoints are ADMIN-only, same crypto pattern

Crates used:

  • ed25519-dalek, x25519-dalek, chacha20poly1305, blake3, zeroize

What I want reviewed (not the full codebase):

  1. Is my AAD construction correct? (header_jcs as AAD)
  2. Is domain separation via msg_type in JCS header sufficient?
  3. Any nonce-reuse risk I'm missing despite the durable-draft pattern?
  4. Is my Ed25519 signing correct — signing over header_jcs || ciphertext || tag?
  5. Any obvious misuse of the crates?

Code is ~400 lines of relevant crypto, no PII, deterministic test vectors included.

I can share the relevant module as a Gist if there's interest. Happy to answer questions about the protocol design.

Thanks in advance!

Full review package (GAP analysis, line references, reviewer checklist):

1 post - 1 participant

Read full topic

🏷️ Rust_feed