-
-
Notifications
You must be signed in to change notification settings - Fork 2
Closed
Description
Background
Currently, SafeSecretKey
holds the decrypted Data Encryption Key (DEK) directly inside a DirectByteBuffer
. While this avoids heap leaks and provides a performance advantage over Java heap storage, the presence of a raw DEK in native memory is still a potential vulnerability. Attackers with memory inspection tools could locate and extract the key, especially in rooted or compromised environments.
Goal
Strengthen in-memory key protection by masking the DEK inside native memory. The masked form should be useless without its corresponding mask, making runtime attacks significantly harder.
Proposed Solution
Instead of storing the raw DEK directly, we will store a masked DEK:
val maskedKey = decryptedKey xor mask
val decryptedKey = maskedKey xor mask
Mask Construction
- The
mask
is derived asSHA-256(encryptedDEK)
. encryptedDEK
is the ciphertext of the original DEK stored innoBackupFilesDir
, encrypted via aCipherProvider
.- This mask is deterministic, instance-bound, and never written to disk.
Lifecycle Changes
- On construction: the decrypted DEK is XOR-ed with the mask and stored off-heap.
- On
getEncoded()
: the masked key is XOR-ed with the mask to produce a clone of the original DEK. - On
releaseHeapCopy()
: the clone is wiped from the heap after use. - On
destroy()
: both the masked key and the mask are zeroed out from native memory.
Considerations
- All operations are constant-time and thread-safe.
- The mask is not re-generated or time-based, simplifying implementation and ensuring stability across reads.
- Implementation is backward-compatible, with no changes to encrypted file format or key derivation.
Benefits
- Full backward compatibility.
- No runtime or disk format migration required.
- Dramatically raises the bar for in-memory attacks, while keeping performance overhead negligible.
Metadata
Metadata
Assignees
Labels
Projects
Status
Done