Skip to content

DOCS / DETERMINISTIC AEAD

Deterministic AEAD

The problem

Standard AEAD ciphers (GCM, SIV) use a random nonce per encryption. This means encrypting the same plaintext twice produces different ciphertext. For CAS-based storage, this is a problem: the same content appears as two different blobs, defeating deduplication.

The solution

enprot's deterministic variants (aes-256-gcm-det, aes-256-gcm-siv-det) derive the nonce from the plaintext itself:

enc_key = HKDF-SHA256(master_key, "enprot-enc", 32)
iv_key  = HKDF-SHA256(master_key, "enprot-iv", 32)
iv      = HMAC-SHA256(iv_key, plaintext)[..12]

Same (password, plaintext) pair → same iv → same ciphertext. This enables:

  • CAS dedup on encrypted segments — identical secrets across files share the same CAS blob
  • Git-friendly diffs — unchanged secrets produce unchanged ciphertext
  • Idempotent transformsencrypt(encrypt(x)) = encrypt(x)

Security tradeoffs

Deterministic encryption leaks whether two ciphertexts encrypt the same plaintext. This is acceptable when:

  • The same key is used for all instances of a given WORD (the common case)
  • CAS dedup is a requirement (large-scale deployment)
  • The adversary cannot mount chosen-plaintext attacks (offline file processing)

For maximum confidentiality, use aes-256-siv (random nonce per encryption). For CAS-friendly deployments, use aes-256-gcm-siv-det.

Usage

# Encrypt with deterministic AEAD
enprot encrypt -w SECRET --cipher aes-256-gcm-siv-det config.txt

# Same content always produces the same ciphertext:
enprot encrypt -w SECRET --cipher aes-256-gcm-siv-det config.txt
# → identical output (idempotent)

# Store encrypted content in CAS — dedup works:
enprot encrypt-store -w SECRET --cipher aes-256-gcm-siv-det config.txt
# → STORED pointer with deterministic hash

Wire format

The deterministic IV derivation is transparent to decryptors — the same key derivation runs during decryption. The cipher extfield records the algorithm:

// <( ENCRYPTED word pbkdf:$argon2id$... cipher:aes-256-gcm-siv-det )>

No additional metadata is needed — the -det suffix in the algorithm name tells enprot to derive the IV.