Safeguard
Security Guides•

Encrypt-then-MAC and padding oracles explained for developers

Encryption alone does not stop tampering. Why order matters when authenticating ciphertext, what a padding oracle leaks, and why AEAD is the simpler fix.

Safeguard Security Team
3 min read

Encryption keeps data secret but does not stop someone changing it. If you build your own scheme from a block cipher mode plus a MAC, authenticate the ciphertext and check the MAC before decrypting: encrypt-then-MAC. Better still, use an AEAD cipher, which does this correctly for you.

Why encryption alone is not enough

With modes like CBC or CTR, an attacker who cannot read your data may still flip bits in the ciphertext and cause predictable changes in the plaintext. Without authentication, the receiver decrypts the altered data and acts on it.

OWASP's storage guidance says authenticated modes should always be used where available, and that if you must use CTR or CBC, you should add separate authentication such as Encrypt-then-MAC.

What a padding oracle is

CBC needs padding to fill the last block. If a server reveals, through an error message, a status code or even timing, whether the padding was valid after decryption, an attacker can submit modified ciphertexts and learn the plaintext piece by piece. The server becomes an oracle answering "is this padding right?"

The root cause is processing ciphertext that was never authenticated. Check the MAC first and reject bad input before any decryption or padding check happens. Then there is nothing to probe.

The three orderings

  • Encrypt-then-MAC: encrypt, then MAC the ciphertext, verify MAC before decrypting. The sound choice.
  • MAC-then-encrypt: MAC the plaintext, then encrypt both. Decryption happens before verification, which is where oracles appear.
  • Encrypt-and-MAC: MAC the plaintext and send beside the ciphertext. The tag can leak information about the plaintext.

Use separate keys for the cipher and the MAC. See one key, one purpose.

Practical advice

  1. Reach for an AEAD such as AES-GCM or ChaCha20-Poly1305. See the AEAD decision guide.
  2. If you maintain legacy CBC code, verify the MAC with a constant-time compare before decrypting.
  3. Return one generic error for every failure, with similar timing.
  4. Do not decrypt untrusted data in a path that logs detailed errors to the client.
  5. Add tests that flip single bits and expect rejection.

Try it yourself

Click through it at your own pace, or open it full screen. Look at how each result names the exact place to fix.

Quick check

Does GCM have padding oracles?

GCM does not use block padding. It does authenticate the data, so altered ciphertext is rejected before plaintext is released.

Is HTTPS enough so I do not need this?

TLS protects data in transit. Data you store, or pass through queues and cookies, still needs authenticated encryption of its own.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.