TazPod: Crypto Detail

Level 3 (Detail) — AES-256-GCM encryption engine with PBKDF2 key derivation.

Concept

The vault is encrypted at the application layer using AES-256-GCM authenticated encryption. The passphrase is derived through PBKDF2 with a random salt. The output format is [salt(32)] + [nonce(12)] + [ciphertext+tag].

Encryption

File: internal/crypto/crypto.goEncrypt() (lines 15-52)

func Encrypt(data []byte, passphrase string) ([]byte, error)
  1. Generate 32 random bytes (salt) via crypto/rand
  2. Derive 32-byte key: pbkdf2.Key(passphrase, salt, 100000, 32, sha256.New)
  3. Create AES cipher: aes.NewCipher(key)
  4. Create GCM: cipher.NewGCM(block) — uses 12-byte nonce
  5. Generate 12 random bytes (nonce) via crypto/rand
  6. Seal: aesGCM.Seal(nil, nonce, data, nil)
  7. Output: salt || nonce || ciphertext

Decryption

File: internal/crypto/crypto.goDecrypt() (lines 56-83)

func Decrypt(data []byte, passphrase string) ([]byte, error)
  1. Validate minimum length: SaltSize + NonceSize (44 bytes)
  2. Extract salt: data[:32]
  3. Extract nonce: data[32:44]
  4. Extract ciphertext: data[44:]
  5. Re-derive key: pbkdf2.Key(passphrase, salt, 100000, 32, sha256.New)
  6. Create AES cipher + GCM
  7. Open: aesGCM.Open(nil, nonce, ciphertext, nil)
  8. On failure: returns “incorrect password or corrupted file”

Constants

ConstantValuePurpose
SaltSize32 bytesRandom salt for PBKDF2
NonceSize12 bytesStandard GCM nonce
KeySize32 bytesAES-256 key
Iterations100000PBKDF2 iteration count

Output Format

[Salt: 32 bytes] [Nonce: 12 bytes] [Ciphertext + GCM Tag: variable]

Total overhead: 44 bytes beyond the plaintext size.

Dependencies

  • golang.org/x/crypto/pbkdf2 — key derivation
  • crypto/aes — AES-256 block cipher
  • crypto/cipher — GCM mode
  • crypto/rand — cryptographically secure random

Security Properties

  • Confidentiality: AES-256-GCM provides authenticated encryption
  • Integrity: GCM authentication tag prevents tampering
  • Key stretching: PBKDF2 with 100k iterations slows brute-force attacks
  • No hardcoded keys: Key is always derived from user passphrase + random salt
  • No plaintext on disk: Vault file is always encrypted at rest

See Also