How it works
Encrypted where you work. Stored where it can’t be read.
SealedGit splits a code host into three parts and gives the keys to only one of them: your team’s devices. This page follows a change from your editor to your teammate’s, and shows what each part holds on the way.
- Your devices
- Hold every key. Encrypt and decrypt.
- The host
- Stores and serves ciphertext. Holds no key.
- The accounts service
- Email identity and invitations. No repository keys.
- Security level
- NIST Category 5, post-quantum
01
Three parts, one key holder
SealedGit is three pieces of software, run in three places. Only one of them ever holds a key that opens a repository.
Your computer
The tools and the app
shub, sgit, git-remote-sgit and the SealedGit app. They keep the repository keys on this computer and do all of the encrypting and decrypting.
The host
sealedgit-server
Stores encrypted git bundles, opaque MLS framing and hash-chained RefHeads, and serves them to members. It never has a key.
Identity
sealedgit-accounts
Signup and email confirmation, password resets, invitations, and the sign-in the host trusts (OIDC). It holds no repository keys.
Who holds what
- Repository keysMembers’ devices, and nowhere else.
- Code, commit messages, issues, pull requests, reviews, release notesMembers’ devices in plaintext. The host, as ciphertext.
- Handles, repository names, membership, push sizes and timesThe host. What the host can see
- Email addresses and password hashesThe accounts service. The host holds neither.
02
Enrolling a device
Signing in, in the app or with shub auth email-login, enrols the computer as a device. It generates the device’s MLS key package there: an ML-KEM-1024 key that group secrets are encrypted to, and an ML-DSA-87 key the device signs with. The private halves never leave the computer.
The public key package goes to the host, so that members can add this device to repositories. Its fingerprint is the device’s safety number, which the login prints and which the person admitting you compares.
shub auth email-login --email you@example.com --password '…'
Signed in as you <you@example.com>.
Enrolled device 'default' (safety number 48 29 11 70 3a 56 09 c2).
03
Creating a repository
shub repo create makes the repository’s MLS group on your computer, with your device as its only member, at epoch 0. The host records the repository’s name and that you are a member. A description, if you give one, is encrypted.
From then on, the group’s current epoch is what every key for the repository comes from. The host relays the group’s MLS messages between devices without being able to read them or take part.
04
A push, step by step
Everything before the last step happens on your computer.
-
Git bundles your commits
sgit pushhands the push to your own git, which runsgit-remote-sgitfor thesgit://remote. The helper bundles the commits the host doesn’t have yet. -
The bundle is sealed
The helper derives a key for this push from the group’s current epoch and seals the bundle with a key-committing AEAD built on SHA-512. Commit messages are inside the bundle, so they are sealed with the code.
Key-committing means a sealed push opens under exactly one key, into exactly one result.
-
A new RefHead is signed
Where your branches and tags now point is recorded in a RefHead, encrypted, signed with your device’s ML-DSA-87 key, and chained by SHA-512 hash to the RefHead before it. Members can tell if the host drops or reorders pushes.
-
The host stores ciphertext
The host appends the RefHead if it follows the one it already has, and stores the bundle. It learns how large the push was and when it arrived.
05
A pull
sgit pull or sgit fetch asks the host for everything after the last RefHead your device has. Your device checks each RefHead’s signature and its link to the one before, decrypts the bundles with the epoch keys it holds, and hands git ordinary objects.
From there it is git: merges, rebases and --ff-only happen on your machine, exactly as they would with any other remote.
06
Adding someone
The host can pass along an invitation. Only a member’s device can let someone in.
-
Invite a member
The accounts service records an invitation for an email address and sends a link. No keys change hands.
-
Accept the invitee
They sign up or sign in, and accept. Signing in enrols their device and publishes its key package.
-
Compare both of you
You compare their safety number over a channel you already trust, so a key substituted by the host would show.
-
Admit a member’s device
Your device makes an MLS Commit that adds their key package, pinned to the digest you compared. The group moves to a new epoch, and a Welcome that only their device can open carries them its secrets.
What they can read of the past depends on the grant. A full-history grant opens the whole history. A forward-only grant starts them at a snapshot of the tree as it is when they join, using dual key regression to open that window and nothing before it.
07
Removing someone
Removal is also an MLS Commit from a member’s device. The group moves to a new epoch whose secrets reach every device except the removed one, so nothing pushed afterwards opens for it.
Removal looks forward. What their device already fetched and decrypted, it keeps. If they could read secrets in the repository, rotate those secrets.
08
The cryptography
Every algorithm is a published standard. The post-quantum ones use the parameter sets NIST places in security category 5, the highest of its five: breaking them should take at least as much work as a key search on AES-256.
MLS_
- Key encapsulation
- ML-KEM-1024
- Signatures
- ML-DSA-87
- AEAD
- AES-256-GCM
- Hash
- SHA-512
| Algorithm | Standard | Strength | What it does here |
|---|---|---|---|
| ML-KEM-1024 | FIPS 203 | NIST Category 5 | Carries each epoch’s secrets to members’ devices in the repository’s MLS group. |
| ML-DSA-87 | FIPS 204 | NIST Category 5 | Signs MLS messages, device key packages and RefHeads, so the host can’t forge any of them. |
| AES-256-GCM | FIPS 197, SP 800-38D | 256-bit key | Encrypts the group’s MLS messages: issues, pull requests, reviews and release notes. |
| SHA-512, HKDF, HMAC | FIPS 180-4, FIPS 198-1, RFC 5869 | 512-bit hash | Chains RefHeads, derives per-push keys, and seals pushes in the key-committing AEAD. |
AES-256 is the yardstick category 5 is defined by, so the symmetric encryption is held to the same level as the post-quantum key exchange and signatures.
Check the binary you run
shub crypto report prints the ciphersuite and AEAD actually linked into the program on your computer.
shub crypto report
MLS ciphersuite MLS_256_MLKEM1024_AES256GCM_SHA512_MLDSA87
MLS backend vendored OpenMLS (draft-ietf-mls-pq-ciphersuites)
transport AEAD hkdf-sha512-pad+HMAC-SHA-512-256
NIST standardised these algorithms. The implementations SealedGit links are open-source Rust libraries, not a FIPS 140-validated module.
See it for yourself
Push something the host can’t read.
Install the CLI, create an account, and watch the host receive only ciphertext.