# Encrypt-then-MAC Envelope Visualizer

> One page from jmrp.io, published as markdown. Index: https://jmrp.io/llms.txt

> Generated: 2026-08-29

URL: https://jmrp.io/tools/etm-envelope-visualizer/
Language: en
Alternate: https://jmrp.io/es/tools/etm-envelope-visualizer/index.md
Updated: 2026-08-25
Category: security
Tags: security, cryptography, encrypt-then-mac, aes, hmac, firmware

Seal a secret into an encrypt-then-MAC envelope, flip a byte, and watch the read verify the tag before decrypting. Runs client-side.

Features:
- Live AES-256-CBC + HMAC-SHA256 envelope sealing
- Separate encKey and macKey sub-key derivation
- Context-bound tag: ver‖recordType‖slotId‖generation
- Seven real attacks: flip, forge, truncate, relocate, retype, roll back
- Encrypt-then-MAC vs decrypt-first, with a live padding-oracle attack
- Web Crypto API, nothing leaves your browser

Questions answered:

**What does "encrypt-then-MAC" mean?**

It means you encrypt the plaintext first, then compute a MAC over the resulting ciphertext (plus the version byte and IV). On read, the MAC is verified before any decryption is attempted.

**Why verify the MAC before decrypting?**

Checking the tag first means a tampered file never reaches the AES-CBC decrypt path, which closes off padding-oracle attacks. If the tag does not match, the read fails closed and no plaintext is produced.

**Why use separate keys for encryption and the MAC?**

Reusing one key for both AES and HMAC is unsafe, so the passphrase derives a master key that fans out into distinct encKey and macKey sub-keys. The encryption key and the MAC key are never the same value.

**What happens when I flip a byte in the envelope?**

Flipping any byte changes the data the HMAC covers, so the recomputed tag no longer matches the stored tag. The read fails closed — no decryption runs and no plaintext is returned.

**Is my secret or passphrase sent anywhere?**

No. All cryptography runs entirely in your browser via the Web Crypto API, and nothing you type is transmitted to any server.


---

**Interactive tool** — this page hosts the working application itself, not a description of one.

## About This Tool

Every file in the vault is an **encrypt-then-MAC** envelope: `[ver][iv][hmacTag][cipher]`. This tool builds one for real in your browser — it derives separate `encKey` and `macKey` sub-keys, encrypts the secret with **AES-256-CBC**, and authenticates the version byte, IV, and ciphertext together with **HMAC-SHA256**.

It is the interactive companion to the article [A Vault File That Fails Closed: Encrypt-then-MAC on an MCU](https://jmrp.io/blog/011-encrypt-then-mac-vault/).

### How do I use it?

1. Type a secret and a passphrase, and set the **authenticated context** (record type, slot, generation). The envelope re-seals live as you type.
2. **Click any byte** to flip it, or pick one of the seven **attacks**: flip a cipher/IV byte, forge the tag, truncate the ciphertext, move the file to another slot, change its record type, or roll back its generation.
3. Watch the **read-path verdict**. Under encrypt-then-MAC every attack **fails closed** — and the tool tells you *why* each one fails (a different reason for each).
4. Flip the read path to **decrypt-first** and press **Run the padding-oracle attack**: a real Vaudenay attack recovers the last plaintext block *byte-by-byte* using only the padding-valid/invalid signal — no key. Switch back to encrypt-then-MAC and the same attacker goes silent.

### What does it show?

- **Key separation** — one passphrase becomes a master key, which fans out into distinct `encKey` and `macKey` sub-keys.
- **Context binding** — the tag covers `ver ‖ recordType ‖ slotId ‖ generation`, so relocating, retyping, or rolling back a file breaks the MAC even though the ciphertext is pristine.
- **Verify-before-decrypt & fail-closed** — the tag is checked first, so a tampered file never reaches the AES-CBC decrypt path, and any failure returns nothing.
- **The doom path** — decrypt-first runs the cipher on attacker bytes before the MAC, exposing a genuine **padding oracle**.
- **CBC malleability** — flipping an IV byte flips the matching plaintext byte of block 0 by the same amount: the attacker's lever.

### The construction, in formulas

Sealing (write path):

```
encKey = HMAC(master, "vault-enc")
macKey = HMAC(master, "vault-mac")
C      = AES-256-CBC-Encrypt(encKey, IV, PKCS7(P))
tag    = HMAC-SHA256(macKey, ver ‖ recordType ‖ slotId ‖ generation ‖ IV ‖ C)
file   = [ver] [IV] [tag] [C]
```

Reading under encrypt-then-MAC (verify, then decrypt):

```
tag' = HMAC-SHA256(macKey, context ‖ IV ‖ C)
if not constant_time_equal(tag', tag): reject   // fail closed, no plaintext
P    = unpad(AES-256-CBC-Decrypt(encKey, IV, C))
```

Why the order is the whole game — the work an attacker faces:

- Forge a tag without `macKey`: a brute force of `2^256` (HMAC-SHA256) — infeasible.
- Padding oracle (decrypt-first): ~1 bit per query, ≤ 256 queries per byte → a
  16-byte block in ≤ ~4096 queries.
- Encrypt-then-MAC removes the oracle outright: for a forged file the decrypt step is *unreachable*, so the attack drops from linear to impossible.

### Why CBC malleability is the lever

In CBC, `P_i = Decrypt(C_i) ⊕ C_(i-1)` (with `C_(-1) = IV`). So `ΔP_i = ΔC_(i-1)`: flipping a byte of the previous block — or of the IV, for block 0 — flips the same byte of the plaintext by the same amount, predictably. That controlled change is exactly what lets a padding oracle walk the plaintext out one byte at a time.

### References & further reading

- [Bellare & Namprempre — Authenticated Encryption: Relations among Notions and Analysis of the Generic Composition Paradigm](https://eprint.iacr.org/2000/025) (encrypt-then-MAC is the generically secure composition)
- [Krawczyk — The Order of Encryption and Authentication for Protecting Communications](https://eprint.iacr.org/2001/045)
- [Vaudenay (2002) — Security Flaws Induced by CBC Padding](https://www.iacr.org/archive/eurocrypt2002/23320530/cbc02_e02d.pdf) (the original padding-oracle attack)
- [Moxie Marlinspike — The Cryptographic Doom Principle](https://moxie.org/2011/12/13/the-cryptographic-doom-principle.html)
- [RFC 2104 — HMAC](https://datatracker.ietf.org/doc/html/rfc2104) · [RFC 5652 §6.3 — PKCS#7 padding](https://datatracker.ietf.org/doc/html/rfc5652#section-6.3)
- [NIST SP 800-57 Part 1](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-57pt1r5.pdf) (one key, one purpose) · [FIPS 180-4 — SHA-256](https://csrc.nist.gov/pubs/fips/180-4/upd1/final)

### Privacy

All cryptography runs entirely in your browser via the Web Crypto API. Nothing
you type is transmitted to any server.

