Repository navigation
feat: encrypted device token storage (AndroidKeyStore AES-GCM) - #7
Merged
Merged
Conversation
AES-256-GCM key in AndroidKeyStore (StrongBox first, then TEE or software), no user authentication or unlocked-device requirement so background sync can read it. File in noBackupFilesDir via AtomicFile: version byte, IV, ciphertext; associated data binds context string and format version. A missing key or failed decryption yields StoredToken.Unreadable, to be handled like a 401.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #4
What
Stores the
dcd_...device token encrypted, as agreed in #4 (variant A).KeystoreTokenCipher: AES-256-GCM key in AndroidKeyStore, with a 12-byte IV generated randomly by the Keystore. No user-authentication or unlocked-device requirement, so the background sync can read it. StrongBox is tried first; otherwise the key goes to the TEE or software. That fallback also covers devices that report a broken StrongBox viaProviderException.DeviceTokenStore: writesnoBackupFilesDir/device_token.binviaAtomicFile. The file holds a format version byte, then IV ‖ ciphertext. The associated data isorg.daycompass.android/device-tokenplus the format version.load()returnsNone,Present(token)orUnreadable.Unreadablecovers a missing key, failed authentication, a truncated or empty file and an unknown version; handle it like a 401 (keep the buffer, re-pair, no retry).save()fails it throws and writes nothing.clear()deletes the file and keeps the key.Security-relevant
DeviceTokengainsinternal fun plaintextForEncryptedStorage(), the second and only other way to the plaintext besides theAuthorizationheader. The returned bytes are wiped after encryption.androidx.core1.18.0 is now declared directly, forAtomicFile. It was already a transitive dependency. Verification metadata gains only POM/module files of versions that lose conflict resolution, and no new JARs.Tests
The JVM tests use a software AES-GCM cipher with a key generated at runtime in place of the Keystore. They cover:
toStringdoes not reveal the tokenKeystoreTokenCipheritself has not been exercised on a device or emulator yet.