trackslash
VAULT-47 P2

Encryption 8: turn on encryption by converting the plain store

0
Sub-issue of VAULT-22 P2 Add an optional password to the app lock

Description

Sub-issue 8 of the on-device encryption design (VAULT-26, docs/on-device-encryption.md, "Migration: plain to encrypted"). VAULT-22's password setup calls this.

The change:

  • Add a state file and journal for the conversion.
  • Check preconditions before converting:
    • the pending rehash stores are empty
    • failed-open archive folders are handled
    • the store loaded normally
  • Convert with verification, and recover at launch if the app was interrupted.
  • Switch the store session to the encrypted store.

The plain SQLite store is only deleted after the encrypted copy is committed.

Tests: a crash at every step, and conversions from older SwiftData schema fixtures.

Linked issues

0

GitHub

0

No branches or pull requests linked.

Comments

1
Bradley

Done in https://github.com/badbundle/vault-app/pull/644 (merged as 39bea383).

What it adds:

  • VaultStorageState: the state file holding the mode, the journal and the device's unlock deadline. No file means plain.
  • VaultEncryptionConverter:
    • Preconditions: the store opened normally, the pending rehash files are empty, failed-open archives are deleted only with confirmation, and vaultTooLarge is checked before anything is written.
    • Setup: calibrates Argon2id, chooses a random real slot and its ten duressSlots, and resets the attempt counter.
    • Verification: runs the full unlock path against the temp file and compares every record.
    • Commit: only after verification does it commit through the journal, delete SQLite (with -wal and -shm), the rehash files and the archives, and switch the session.
  • VaultStorageRecovery: resolves every journal state at launch.

Rules:

  • The commit point is the journal's rename.
  • Undo only removes a file this call wrote, after confirming the journal isn't committed.
  • Recovery never deletes SQLite unless vault-slots.v1 exists and parses.
  • A second conversion is refused.
  • A lock during the conversion wins.
  • QuickType and widget clearing is journaled (clearingSystemSurfaces) and re-run at launch.

Extensions:

  • In encrypted mode, the app starts locked and never opens SQLite.
  • AutoFill and widgets go through GuardedPlainVaultStore, which checks the mode on every call. Their writes take vault-slots.lock, which the conversion holds until it commits.
  • The plain store is now releasable.

Tests:

  • A failure and a crash at every step, including combined faults, each followed by recovery.
  • Concurrent calls.
  • V1, V2 and V3 schema fixtures, including rehash entries, undecodable items and archives, compared through retrieve, search and tags.
  • Each precondition refusing.
  • An end-to-end unlock.

Review: a security review found one blocker (a failed conversion's undo could delete the only copy) and five should-fixes. All were fixed and re-reviewed. The remaining nits are in VAULT-48's PR.