Repository navigation
[_]: feature/user mail keystroke - #47
Merged
Merged
Conversation
patricioxavier8
approved these changes
Sep 14, 2026
sg-gs
reviewed
Sep 22, 2026
sg-gs
reviewed
Sep 22, 2026
sg-gs
approved these changes
Sep 22, 2026
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.
We call the Mail API at
GET /users/me/mail-account/keysto fetch the user's mail keystore, which holds both halves of the account's key pair:encryptionPrivateKeydecrypts incoming mail — the bodies of the messages in Inbox and every other folder. It arrives encrypted, and unwrapping it is what this PR is about.publicKeyencrypts outgoing mail for the account itself, so the user can still read their own Sent messages and drafts. Recipients' keys come from a separate lookup; this one is only ever the user's own.The Mail API returns the account's private key encrypted, and the bridge daemon expects it decrypted. This adds the unwrapping, which is the client's job by design so the daemon never sees the mnemonic.
The chain mirrors
openEncryptionKeystorein internxt/crypto, the library the web client uses to create the keystore — it has to match byte for byte or the key will not open:Why the BLAKE3 C sources are vendored
The keystore key is derived with BLAKE3 in
derive_keymode. That is a separate mode with its own internal flags, not a hash of the context concatenated with the material, so it cannot be emulated. CryptoKit does not ship BLAKE3, so we vendor the reference implementation written by the algorithm's own authors instead.Files are unmodified from https://github.com/BLAKE3-team/BLAKE3 at tag
1.8.7:Tests - validation
12 tests, no hand-written expectations: the 35 official BLAKE3 vectors in both modes, the 24 official BIP-0039 vectors, and a keystore generated by
internxt-cryptothat this code unwraps to the same 32 bytes — which validates BIP39, BLAKE3, the AAD and the IV layout in one assertion.