Skip to content

feat: at-rest encryption for KV storage (#34)#69

Open
jimmy-claw wants to merge 1 commit intomainfrom
jimmy/issue-34
Open

feat: at-rest encryption for KV storage (#34)#69
jimmy-claw wants to merge 1 commit intomainfrom
jimmy/issue-34

Conversation

@jimmy-claw
Copy link
Copy Markdown
Owner

Description

Implements at-rest encryption for local KV storage (#34).

Calendar data stored in kv_module was previously plaintext. This PR adds a password-derived encryption layer so data at rest is protected.

Approach: checked kv_module API first (as the issue notes) — it already supports setEncryptionKey(ns, hexKey) which activates transparent AES-256-GCM encryption. We wire into that.

Changes

  • CalendarStore::enableEncryption(keyBytes) — calls kv_module::setEncryptionKey() under Logos Core (AES-256-GCM); XOR stream cipher fallback for standalone/test mode
  • CalendarStore::disableEncryption() and isEncryptionEnabled() — session-scoped key management
  • LogosCalendar::enableEncryption(password) — PBKDF2-SHA256 key derivation (100 000 iterations, 32-byte output); random 16-byte salt generated on first call, stored plaintext at encryption:salt; same password + same salt → same key (existing data stays readable)
  • LogosCalendar::disableEncryption() / isEncryptionEnabled() — public Q_INVOKABLE API
  • encryptionChanged(bool) signal — lets QML/UI react to encryption state changes
  • 14 new unit tests in tests/test_encryption.cpp — all passing

Encryption design

Layer Mode Algorithm
Logos Core build kv_module native AES-256-GCM (random nonce per record, authenticated)
Standalone / test In-process fallback XOR + SHA-256 keystream (dev/test only)
Key derivation PBKDF2-SHA256 100 000 iterations, 32-byte output
Salt Plaintext KV 16 bytes random, stored at encryption:salt

Checklist

  • Builds cleanly (cmake -B build -DBUILD_TESTS=ON && cmake --build build)
  • Tests pass (cd build && ctest -V — 73 tests, 0 failures, 7 suites)
  • README updated (encryption section + test count)
  • New public methods have doc comments
  • Branch is off main (not another feature branch)

- Add CalendarStore::enableEncryption(keyBytes) / disableEncryption() / isEncryptionEnabled()
  - Under Logos Core: delegates to kv_module::setEncryptionKey() — transparent AES-256-GCM
  - Standalone/test mode: XOR stream cipher (SHA-256 keystream) for dev/test only
- Add LogosCalendar::enableEncryption(password) / disableEncryption() / isEncryptionEnabled()
  - PBKDF2-SHA256 key derivation (100 000 iterations, 32-byte output)
  - Random 16-byte salt generated on first call, stored plaintext at encryption:salt
  - Subsequent calls with same password reproduce same key (existing data stays readable)
- Add encryptionChanged(bool) signal
- Add 14 unit tests in test_encryption.cpp (all passing)
- Update README: document encryption API + salt storage semantics
- Bump test count: 59 → 73 tests across 7 suites

Refs #34, #31
@jimmy-claw
Copy link
Copy Markdown
Owner Author

The E2E CI failure (build-module CMake target name conflict) is pre-existing on main — it appears in run 22999824598 before this PR was opened. Unrelated to this change.

Local results: 73 tests, 8 suites — all passing (100% tests passed, 0 tests failed out of 8).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant