How DevSafe encrypts
your code.
Every git bundle is encrypted on your machine before it touches any network. The key never leaves. The storage provider never sees plaintext. This page explains exactly how that works.
Cipher: AES-256-GCM
DevSafe uses AES-256-GCM, a nonce-unique AEAD cipher (Authenticated Encryption with Associated Data). That means every encryption operation produces both ciphertext and an authentication tag. If anyone tampers with even one bit of the encrypted data, decryption fails immediately. There is no silent corruption.
Each encryption uses a 96-bit random nonce generated per NIST SP 800-38D. A nonce is a number used exactly once. Fresh randomness for every operation means no two encryptions ever reuse the same nonce with the same key. This is what makes the scheme "nonce-unique AEAD."
On modern CPUs, AES-256-GCM runs on dedicated hardware instructions called AES-NI. DevSafe detects and uses these instructions automatically. The result: encryption adds negligible overhead. A 10 GB git bundle encrypts in roughly 3 seconds.
Plain AES (without a mode like GCM) encrypts data but does not authenticate it. An attacker could flip bits in the ciphertext and you would decrypt garbage without knowing. GCM bundles encryption and authentication into a single pass, so tampering is always detected.
Key derivation: HKDF-SHA256
DevSafe never uses your master key directly. Instead, it derives a unique key for every repository and every git bundle using HKDF-SHA256 (HMAC-based Key Derivation Function). This creates a two-level key hierarchy that prevents cross-repo key reuse.
The key hierarchy
Here is what each level does:
- Master key is your root secret. It is generated once on your machine during
devsafe key new. It never leaves the machine. It is never sent over any network. - Per-repo key is derived from the master key and a unique repository identifier. Each repository gets its own key. Compromising one repo key does not expose any other repository.
- Per-bundle key is derived from the repo key, a sequence number, and a timestamp. Every individual git bundle gets its own unique encryption key. Even within a single repository, no two bundles share a key.
This two-level hierarchy means that even if an attacker recovers a single per-bundle key (through some hypothetical side channel), they cannot derive any other key in the system. They cannot move "up" the hierarchy from a bundle key to a repo key, and they cannot move "sideways" to other bundles.
Envelope format
DevSafe encrypts two types of data, each with its own envelope format:
- Committed bundles contain the full git history (commits, branches, tags). These are created by
git bundle createand represent the complete state of a repository at a point in time. - Working-state snapshots capture uncommitted work: your staging area, modified files, untracked files, stashes, and in-progress operations like rebases or merges.
Both types use the same master key and the same AES-256-GCM cipher. The difference is in the nonce derivation. A type field is included in the HKDF input when deriving per-bundle keys. This guarantees that committed bundles and working-state snapshots occupy completely separate nonce spaces, even when they share the same repo key and sequence number.
// type = "bundle" or "snapshot" // This prevents cross-type nonce collision bundle_key = HKDF-SHA256( key = repo_key, info = type || sequence || timestamp ) nonce = random_bytes(12) // 96 bits, fresh every time ciphertext, tag = AES-256-GCM(bundle_key, nonce, plaintext)
The encrypted envelope stores the nonce, authentication tag, type field, and ciphertext together as a single blob. On decryption, DevSafe re-derives the key, reads the nonce from the envelope, and decrypts. If the authentication tag does not match, decryption is rejected. No partial or corrupted data is ever returned.
Streaming encryption
Git repositories can be large. A monorepo might produce a git bundle measured in gigabytes. DevSafe does not load the entire bundle into memory before encrypting. Instead, it uses streaming encryption.
The plaintext is read in chunks. Each chunk is encrypted independently using AES-256-GCM with its own nonce derived from the chunk index. The encrypted chunks are written to the output stream as they are produced. This means memory usage stays constant regardless of bundle size.
On machines with AES-NI hardware support (which includes virtually all modern x86 and ARM processors), the streaming encryption runs at near-disk-speed. The bottleneck is typically disk I/O or network upload, not encryption.
$ devsafe backup large-monorepo --verbose → creating git bundle (14.2 GB)... → encrypting in streaming mode (AES-NI detected) ✓ encrypted 14.2 GB in 4.1s (3.46 GB/s) ✓ uploading to user-owned storage... ✓ backup complete, sequence 00047
What we never do
DevSafe's encryption model is defined as much by what it refuses to do as by what it does. These are not guidelines. They are hard constraints enforced in the code.
- Keys never leave the machine. Your master key is generated locally and stays locally. It is never transmitted to DevSafe servers, to your storage provider, or to anyone else. Period.
- No server-side decryption. Your user-owned storage provider receives only encrypted blobs. They cannot decrypt your data. DevSafe has no server that holds your key. There is no API endpoint that accepts a key. The architecture makes server-side decryption impossible, not just policy-prohibited.
- No key escrow. We do not hold a copy of your key "just in case." If you lose your key, your backups are unrecoverable. That is the correct behavior for a zero-knowledge system. See Key custody for how to protect your recovery phrase.
- No "just this once." There is no flag, no environment variable, no hidden option to skip encryption or transmit a key. The code does not contain a bypass. This is not a policy decision that could be reversed in a future update. The architecture makes unencrypted backup impossible.
- No plaintext metadata leakage. Repository names, file paths, commit messages, and branch names are all inside the encrypted envelope. Your storage provider sees structured key names (like
a1b2c3/bundle/000012.enc) but nothing about the content.
This is not a limitation. It is the guarantee. A system where the vendor can recover your key is a system where the vendor (or anyone who compromises the vendor) can read your code. DevSafe chooses permanent data loss over key compromise. Back up your recovery phrase. Learn how.
Verify it yourself
You do not need to trust this page. DevSafe includes a built-in audit command that reports exactly which cipher, key derivation, and nonce strategy are in use for each repository.
$ devsafe audit --crypto cipher: AES-256-GCM (nonce-unique AEAD) nonce: 96-bit random (NIST SP 800-38D) key derivation: HKDF-SHA256, two-level hierarchy hardware accel: AES-NI detected, active key escrow: none (zero-knowledge) repos audited: 14 nonce reuse: 0 violations ✓ all checks passed