Document Version: 1.0
Release Date: 2026-08-12
Target Architecture: GitPassword GITP v2
Abstract
GitPassword is a Git-backed password management system for credentials, secure notes, and encrypted files. GITP v2 enforces client-side zero-knowledge encryption: sensitive payloads are encrypted before being written to the Git repository and decrypted locally only after verifying identity, revision sequence, and AEAD integrity.
The cryptographic core centers around a randomly generated Vault Key protected by an Unlock Key derived from the master password. Users can optionally enforce a high-entropy 128-bit Vault Secret as a second secret. Application payloads are never encrypted directly with the master password or Vault Key; instead, an independent Content Encryption Key (CEK) is generated per object per revision.
GITP v2 combines Argon2id, HKDF-SHA256, HMAC-SHA256, and AES-256-GCM into a layered key hierarchy with canonical headers, authenticated associated data (AAD), 64 KiB chunked streaming, local monotonic trust state machines, and authenticated tombstone deletion records to protect confidentiality, integrity, object identity, and version continuity.
1. Security Objectives
- Remote Git repositories and transport channels never hold plaintext credentials, notes, or files;
- Local disk never stores or caches unencrypted plaintext (drafts, thumbnails, chunk caches, and index files are sealed with local envelope keys);
- The master password is never used directly as a content cipher key;
- Changing the master password or tuning KDF parameters never requires re-encrypting existing content payloads;
- Cryptographic isolation is enforced between different vaults, objects, revisions, and file chunks;
- Any modification to ciphertext, headers, UUIDs, or chunks terminates operations in a fail-closed manner;
- State validation defends against Git history replays, concurrent version forks, and resurrecting deleted objects;
- Strict bounds are enforced on untrusted lengths, enumerations, KDF parameters, and chunk sizes;
- Key materials are isolated and protected across memory and platform secure storage.
2. Security Architecture
2.1 Client-Side Encryption
Credentials, notes, file metadata, and file payloads are encrypted on the client device. The Git remote purely stores and syncs encrypted blobs, taking no part in key derivation or plaintext computation.
Git authentication and Vault decryption are completely independent: Git credentials grant repository access; the master password and Vault Secret unlock the Vault.
2.2 Layered Key Hierarchy
Master Password --UTF-8 NFC--> Argon2id -----------+
+--> HKDF-SHA256 --> Unlock Key
Vault Secret (Optional, 128-bit) ------------------+
|
| AES-256-GCM
v
Vault Key
|
+----------------------------------------------------+--------------------+
| | |
v v v
CEK Wrap Subkey Credentials Auth Subkey Local Data Subkey
| |
v v
Per-Object, Per-Revision CEK Drafts & Thumbnails
|
+-----+---------------------+
| |
v v
Entry Authenticated Encryption 64 KiB Chunked Stream
| Key | Derivation / Generation | Purpose |
|---|
| Unlock Key | Derived from Argon2id output + Vault Secret via HKDF-SHA256 | Wraps and unwraps the Vault Key |
| Vault Key | 256-bit CSPRNG random value | Root key for all domain subkeys |
| CEK Wrap Key | Derived from Vault Key bound to Vault ID and Writer ID | Wraps per-revision object CEKs |
| CEK | Random 256-bit key per object revision | Encrypts payload for a single object revision |
| Credentials Auth Key | Derived from Vault Key in a distinct domain | Validates Vault credentials integrity |
| Local Data Subkey | Derived from Vault Key per namespace and local key identity | Protects local drafts, caches, and thumbnails |
3. Master Password & Vault Secret
3.1 Normalization
The master password is processed as UTF-8 and normalized to Unicode NFC before KDF execution. Empty passwords, embedded NUL bytes, and invalid UTF-8 sequences are rejected.
3.2 Argon2id Key Derivation
GITP v2 uses Argon2id v1.3 (libargon2):
| Parameter | Default Value |
|---|
Memory Cost m_kib | 32,768 KiB (32 MiB) |
Time Cost t | 6 iterations |
Parallelism p | 4 lanes |
| Salt | 16-byte cryptographically secure random value |
| Output | 32 bytes |
3.3 Dual Unlock Modes
| Mode | Required Credentials |
|---|
| PasswordOnly | Master Password |
| PasswordAndSecret | Master Password + 128-bit Vault Secret |
argon2Out = Argon2id(passwordNFC, kdfParams)
PasswordOnly:
IKM = argon2Out
PasswordAndSecret:
IKM = argon2Out || secretRaw
unlockKey = HKDF-SHA256(IKM, salt = vaultId, info = "gitpassword:v2:unlock", L = 32)
3.4 Vault Secret Encoding
Vault Secret is a 128-bit CSPRNG value formatted in Base32 with versioning and input checksums:
payload = 0x02 || secretRaw[16] || SHA-256(0x02 || secretRaw)[0..1]
text = RFC 4648 Base32(payload), no padding (31 chars)
4. Vault Credentials v2
Vault credentials form a fixed 153-byte binary structure with magic GITC and suite 0x0001.
WrappedKey = nonce(12) || ciphertext(32) || tag(16)
Authenticated Associated Data (AAD) binds the credentials prefix, magic, suite, vaultId, Secret mode, Vault Key generation, wrap version, and all KDF parameters.
Master Password Changes
Changing the master password derives a new Unlock Key with fresh salt/nonce and re-wraps the same Vault Key while incrementing wrapVersion. Existing object payloads do not need to be re-encrypted.
Objects use magic GITP and a 158-byte canonical header containing UUIDs, chunk sizes, plaintext lengths, writer identities, and wrapped CEKs.
5.1 File Chunked Streaming
Files are split into 64 KiB independently authenticated chunks:
chunkAAD = "gitpassword:v2:chunk" || headerDigest || objectUuid
|| chunkIndex || plaintextLen || totalPlaintextLen || finalFlag
This binds every chunk to the canonical header, file UUID, index, and final flag, completely preventing truncation, chunk swapping, or reordering attacks.
5.2 Plaintext-Free Media Streaming
During in-app preview of audio, video, images, and text, chunks are decrypted directly in memory pipelines without creating plaintext temp files on disk.
6. Monotonic Trust State & Replay Protection
To prevent malicious Git force-push replays or version rollbacks:
- Credentials Trust State: Enforces monotonic
wrapVersion and baseline KDF parameters. - Content Trust State: Maintains maximum authenticated revisions and
headerDigests. - Authenticated Tombstones: Deleting an item writes a 17-byte authenticated Tombstone object, placing the UUID in an irreversible terminal state.
7. OS-Level Secure Storage
When "Remember Credentials" is enabled, device records (Vault ID, suite, and Vault Key) are stored exclusively in operating system hardware-backed keychains:
- Windows: Windows DPAPI
- macOS / iOS: Keychain Services
- Linux: freedesktop Secret Service (
libsecret)
8. Summary of Cryptographic Parameters
| Item | Specification |
|---|
| KDF | Argon2id v1.3 (m=32768 KiB, t=6, p=4) |
| Key Derivation | HKDF-SHA256 (RFC 5869) |
| Message Authentication | HMAC-SHA256 |
| Authenticated Encryption | AES-256-GCM (NIST SP 800-38D) |
| Nonce / Tag | 12 bytes / 16 bytes |
| Vault Secret / Vault Key | 16 bytes (128-bit) / 32 bytes (256-bit) |
| Content Encryption Key (CEK) | 32 bytes (per-revision fresh random) |
| Default Chunk Size | 65,536 bytes (64 KiB) |
| Max File Size | 16 GiB |
Next Steps