Repository navigation
Add supabase_chat_seal: permissive (MIT) E2EE for closed-source apps - #4
Merged
Merged
Conversation
The Signal-based supabase_chat_e2ee depends on libsignal_protocol_dart, which is GPL-3.0 — unusable in a closed-source app (distribution forces the whole app open-source). This adds a permissively licensed alternative with the same verified-E2EE API. - Sealed box over X25519 ECDH -> HKDF-SHA256 -> AES-256-GCM via the Apache-2.0 cryptography package (+ crypto BSD-3 for safety numbers). No copyleft deps. - SealIdentity / SealManager / SealedChatRoom mirror the e2ee API surface; PublicKeyDirectory (Supabase + in-memory), TrustStore, 60-digit SafetyNumber. - Strict requireVerified mode, IdentityChangedException on key swap, sender self-readback via the static pairwise key. - 9 backend-free round-trip tests + a runnable console demo (seal_demo.dart). - SQL migration 0003 (e2ee_public_keys directory). - Trade-off vs Signal: no forward secrecy. Documented throughout; root README now presents both options side by side, chosen by license.
- Prominent GPL-3.0 warning at the top of supabase_chat_e2ee: distributing it (incl. app stores) requires open-sourcing the whole app; closed-source apps must use supabase_chat_seal instead. - Root README: a license-compatibility table across all packages showing which are closed-source safe and why supabase_chat_e2ee is not.
example/lib/two_users.dart boots two independent anonymous clients into one shared room and renders both panes in a single window, so presence (online), typing, send status (sending/sent), and read receipts (unread badge clearing) are all visible propagating live between the two users. Rewrites the example README (was the default Flutter placeholder) to document both entrypoints.
example/lib/encrypted_two_users.dart: two users chat end-to-end encrypted via supabase_chat_seal, and a bottom panel renders the exact ciphertext stored in messages.encrypted — showing the humans read plaintext while Supabase only ever holds an opaque blob. Each pane shows the verified safety number, presence, and typing. Adds supabase_chat_seal to the example deps and documents the demo.
example/lib/encrypted_device.dart: one anonymous user per device, paired with a one-time ID handshake (create on one, join on the other), chatting E2E-encrypted via supabase_chat_seal. A toolbar toggle reveals the ciphertext stored in messages.encrypted. Documents the two-emulator run in the example README.
Bulk inserting room_members with differing key sets (owner row carried keys the member rows lacked) made PostgREST reject the insert with PGRST102, breaking every room creation that included members. Build all rows with the same keys (room_id, user_id, role).
- README: device migration & passphrase-encrypted key-backup recipe (the identity key is the master key; no server-side recovery) - README: forward-secrecy / dynamic-key trade-off vs supabase_chat_e2ee (Double Ratchet is the GPL path; static pairwise key here, by design) - README: 'what E2EE can't do' matrix (server search/restore impossible; local plaintext export is fine) - add macOS platform target so the example runs on desktop - gitignore Supabase CLI local state (.temp/.branches/.env)
…e2ee GPL-3.0 supabase_chat_ui hard-depended on the GPL supabase_chat_e2ee via EncryptedChatView, so importing the (MIT) widgets transitively pulled libsignal and forced GPL on consumers — even for plain, unencrypted chat. - supabase_chat_ui: drop the e2ee dependency; remove the GPL-coupled EncryptedChatView; split out the presentational EncryptedChatBanner (no crypto dep, works above either E2EE flavor). - supabase_chat_e2ee: relicense MIT -> GPL-3.0 so the pub.dev badge matches the obligation it links (libsignal is GPL-3.0); ship the EncryptedChatView as a copy-paste recipe in its README. - README/CHANGELOGs: correct the license table (e2ee is GPL-3.0; the other four packages are MIT and closed-source-safe).
The pub.dev name supabase_chat_ui is already taken by another author, so rename our Flutter widgets package to the available supabase_chat_widgets (dir, pubspec, library file, imports/exports, workspace path, and all docs).
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.
Why
supabase_chat_e2eegives the strongest crypto (Signal Protocol, forward secrecy) but depends onlibsignal_protocol_dart, which is GPL-3.0. Shipping a GPL-3.0 dependency (App Store / Play Store = distribution) forces the entire app open-source — so it can't be used in a closed-source app.This adds
supabase_chat_seal, a permissively licensed alternative with the same verified-E2EE API.What
cryptographypackage (+cryptoBSD-3 for safety numbers). No copyleft dependencies → safe for closed-source apps.SealIdentity,SealManager,SealedChatRoom,PublicKeyDirectory(Supabase + in-memory),TrustStore, 60-digitSafetyNumber.requireVerifiedmode,IdentityChangedExceptionon a directory key swap (MITM), and sender self-readback via the static pairwise key.0003_e2ee_public_keys.sql.Trade-off
No forward secrecy (static pairwise key) — documented throughout. The root README now presents both E2EE options side by side, chosen by license.
supabase_chat_seal(new)supabase_chat_e2eeVerified
dart analyze packages→ No issues founddart format→ 0 of 59 changeddart run example/seal_demo.dart→ full walkthrough, matching safety numbers, ciphertext-only storage, tamper rejection