Skip to content

Comments

CSPP Phase 2: Database encryption & migration#597

Draft
praveenperera wants to merge 12 commits intomasterfrom
cspp-phase-2-encryption
Draft

CSPP Phase 2: Database encryption & migration#597
praveenperera wants to merge 12 commits intomasterfrom
cspp-phase-2-encryption

Conversation

@praveenperera
Copy link
Contributor

Summary

  • Encrypt all redb databases (main + per-wallet) at rest using EncryptedBackend (XChaCha20-Poly1305 block-level AEAD)
  • Encrypt all BDK SQLite databases using SQLCipher
  • Migrate existing plaintext databases on first launch with crash recovery
  • Backward compatible: fresh installs create encrypted, upgrades migrate automatically

Commits

  1. Create encrypted backend for redbEncryptedBackend implementing redb::StorageBackend with per-block encryption, block-index AAD, and COVE magic header
  2. Wire EncryptedBackend into database init — Fix compile error, add open_or_create_database() helper with backward compatibility for plaintext legacy DBs
  3. Add redb migration (plaintext → encrypted) — Generic copy_table helper, main DB migration (7 tables), per-wallet migration (5 tables), crash recovery via atomic rename
  4. Encrypt BDK SQLite with SQLCipher — Add rusqlite with bundled-sqlcipher-vendored-openssl, apply PRAGMA key in BdkStore::try_new()
  5. Add BDK SQLite migration (plaintext → SQLCipher)sqlcipher_export based migration, crash recovery, wired into app startup

Startup sequence (after all changes)

App::new():
  1. logging::init()
  2. Derive encryption key (Cspp → MasterKey → sensitive_data_key)
  3. set_encryption_key(key)
  4. recover_interrupted_migrations()        // redb crash recovery
  5. migrate_main_database_if_needed()       // redb plaintext → encrypted
  6. migrate_wallet_databases_if_needed()    // redb per-wallet
  7. recover_interrupted_bdk_migrations()    // BDK crash recovery
  8. migrate_bdk_databases_if_needed()       // BDK plaintext → SQLCipher
  9. ... rest of App::new() ...

CSPP Phase 2 progress

Closes #589, closes #591, closes #592, closes #590, closes #559, closes #560

Remaining phase 2 issue: #561 (cloud backup config flags to GlobalConfig)

Test plan

  • cargo test -p cove — 111 tests pass (encrypted backend, migration, BDK migration, crash recovery)
  • just fmt && just clippy — clean
  • Fresh install: databases created encrypted from the start
  • Upgrade path: existing plaintext databases migrated on first launch
  • Crash during migration: recovered on next launch

- Fix compile error: use master_key.sensitive_data_key() instead of
  cspp.sensitive_data_key()
- Add open_or_create_database() helper that handles encrypted, plaintext,
  and new database files
- Simplify database.rs and wallet_data.rs to use the new helper
- Add backward compatibility for legacy plaintext databases
@coderabbitai
Copy link

coderabbitai bot commented Feb 19, 2026

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch cspp-phase-2-encryption

Tip

Issue Planner is now in beta. Read the docs and try it out! Share your feedback on Discord.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

…validation

- Add .bak-only recovery path for interrupted migrations where only backup remains
- Replace silent `let _ = remove_file()` with logged error handling across all migration files
- Fix SQL injection via single-quote in file paths during BDK migration
- Switch EncryptedBackend to parking_lot::Mutex, promote write_disk_block assert to release
- Add partial-block truncation detection in read_disk_block
- Change open_or_create_database to return Result, propagate errors through wallet_data
- Replace .flatten() on directory iterators with explicit error logging
- Add post-migration verification (reopen + read check) before atomic swap
- Improve panic messages at app startup for migration failures
- Fix set_encryption_key doc comment, add sync_data eventual=true explanation
- Fix WalletDataDb::new_test to return TempDir so it survives test lifetime
Replace io::Result with DatabaseError in open_or_create_database and
propagate through Database::init instead of .expect()ing at every step.
Add EncryptionKeyNotSet, BackendOpen, and CorruptBlock variants to
distinguish error categories. Improve migration panic messages in
App::new with path/phase context and full error chains via {e:#}.
Restrict test-only helpers to test builds: remove the test-only reset_cache from the generic Cspp impl and add a Cspp<MockStore>::reset_cache inside the tests module so it is only available for tests. Also relocate WalletDataDb::new_test into a #[cfg(test)] impl block at the bottom of the file to avoid exposing test helper code in non-test builds. These changes keep production APIs clean of test utilities.
Use FileExt::read_exact_at/write_all_at instead of seek+read/write,
eliminating the need for a mutex to protect the shared file position.
Also add create_or_open to handle TOCTOU race, and fix sync_data
write barrier to always fsync.
@praveenperera praveenperera force-pushed the cspp-phase-2-encryption branch from 875a192 to 1785828 Compare February 23, 2026 18:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant