Repository navigation
feat(chat): encrypt DM text end to end - #913
Merged
Merged
Conversation
E2eePolicy now asks shared-core's ChatEncryptionPolicy, which carries the @Flipcash user id, so the app's own nil constant and its injection seam go. Both DM types count as direct messages. The conversation doesn't say which member is self, so each member is checked as the peer; self is never @Flipcash, so only the @Flipcash chat fails. A member without a user id has no key to encrypt to and keeps the chat in plaintext. Needs a SharedCoreKit build with ChatCipher (code-android-app#1616); until it's released, build with FLIPCASH_SHARED_CORE_LOCAL.
Text and Reply(Text) in a DM are sealed into EncryptedContent when ChatEncryptionPolicy says so. EncryptedChatClient wraps FlipClient so send, retry and edit all encrypt, and every message read back from the server (fetch, delta, stream) is decrypted before it reaches the store. The server's echo of a sent message is decrypted the same way. The peer's key comes from Resolver.Resolve(user_id) and is kept per user. Decrypted text is stored next to the ciphertext (schema 43). A message that fails to open keeps its cause, which picks the unavailable hint: an unknown scheme or type asks to update Flipcash, an auth failure asks the sender to send it again, or asks you to try again for your own message. A message whose key couldn't be fetched is hidden from the transcript and the chat-list preview until a later load decrypts it. ENCRYPTION_NOT_ALLOWED leaves a retryable failed bubble and drops the cached chat, so the retry reads use_e2ee again. The transcript gets an Encrypted marker before the first loaded encrypted message, placed from the messages rather than use_e2ee; tapping it opens the DM learn-more sheet. The notification service extension decrypts the push body, fetching the message by id when the push carries only that, and keeps the server's body on any failure. The quick reply from the notification encrypts.
The NSE target has no tests, so the rule that swaps in a decrypted body moves to NotificationPayload.decryptedBody in FlipcashCore. Tests pin it: plaintext only for an encrypted message that decrypted to text, and nil (keep the server's body) when the message is missing, was never encrypted, or failed to decrypt. chatMessageID gets tests for embedded, id-only, and absent message references.
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.
Phase 2 of E2EE DMs, on top of the UI from #909. Text and replies in a DM are now encrypted with shared-core's
ChatCipher(code-payments/code-android-app#1616).Changes
ChatCipher.E2eePolicyasks shared-core'sChatEncryptionPolicy, which carries the @Flipcash user id, so the app's own constant and its test seam are gone. The @Flipcash chat never encrypts.EncryptedChatClientwrapsFlipClient. Send, retry and edit seal Text and Reply(Text) intoEncryptedContentwhen the policy says so. Every message read back (fetch, delta, stream, and the server's echo of a send) is decrypted before it reaches the store.Resolver.Resolve(user_id)and is kept per user. Resolving your own user id returns your owner key, which is what makes this the right source.ENCRYPTION_NOT_ALLOWEDleaves a failed bubble you can retry, and drops the cached chat so the retry readsuse_e2eeagain.use_e2ee. Tapping it opens the DM learn-more sheet.Media is out of scope.