DevSafe / Docs
Docs Security Encryption model

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.

Why GCM and not just AES?

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

Master Key (generated once, stored on your machine) | +-- HKDF-SHA256(master, repo_id) --> Per-Repo Key | +-- HKDF-SHA256(repo_key, sequence || timestamp) --> Per-Bundle Key | +-- HKDF-SHA256(repo_key, sequence || timestamp) --> Per-Bundle Key | +-- ...

Here is what each level does:

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:

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.

nonce derivation (pseudocode)
// 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.

terminal
$ 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.

If you lose your key, we cannot help you.

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.

terminal
$ 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