# CRIME and BREACH: Compression Side Channels in TLS

**Source**: https://quantumsequrity.com/blog/crime-breach-compression
**Category**: Threats & Attacks

---

[← Back to Blog](../../blog.html) Threats & Attacks

# CRIME and BREACH: Compression Side Channels in TLS

12 min read

In September 2012, Juliano Rizzo and Thai Duong, the same researchers who built the BEAST attack a year earlier, returned with another live demonstration that broke a piece of the secure web. They called it CRIME, short for Compression Ratio Info-leak Made Easy. By exploiting how data compression interacts with encryption, the attack could steal HTTPS authentication cookies in seconds. Less than a year later, three researchers at Black Hat USA 2013 generalized the technique to HTTPS responses without TLS-level compression, in a follow-up they called BREACH. Together, CRIME and BREACH mapped out an entire family of compression side-channel attacks that fundamentally changed how engineers think about combining compression and encryption.

This post explains both attacks in plain language, walks through the size-leak mechanism that makes them possible, and shows why even modern TLS deployments still need to be careful about how compression interacts with secret data.

## The Counterintuitive Idea

If you have a file containing the word "apple" repeated a hundred times, a compressor like zlib or gzip will produce a very small output. If the file contains a hundred random words, the compressor will produce a much larger output. Compressors work by finding repeated patterns and replacing them with shorter codes. This is by design. It is what makes compression useful.

Now imagine the file contains a secret value followed by some attacker-chosen text. If the attacker can arrange for their text to partially overlap with the secret, the compressor will notice the overlap and produce a smaller compressed file. If the attacker's text does not overlap with the secret, the compressor produces a slightly larger output. By measuring the size of the compressed output, the attacker learns something about the secret.

This is the entire idea behind CRIME and BREACH. The compressed size leaks information. If the attacker can influence the compressed plaintext and observe the encrypted output's length, they can recover the secret one byte at a time.

## How CRIME Worked Specifically

CRIME targeted TLS with compression enabled. RFC 3749 (May 2004) defined the TLS Compression Methods, and zlib (DEFLATE) was the most common option. When a browser made an HTTPS request to a CRIME-vulnerable site, the entire TLS record (including the secret cookie) was compressed before encryption. The encrypted output was sent over the wire.

The attacker assumed the standard JavaScript injection capability that BEAST also relied on: malicious code running in one tab makes HTTPS requests to a target site in another tab. The browser's same-origin policy stops the attacker from reading the response, but it does not stop the attacker from issuing requests with chosen URL paths and bodies. Because cookies are sent automatically based on domain, every request includes the secret cookie in its headers.

The attacker constructs a probe like this: they send a request whose URL contains "Cookie: session=A". The TLS record contains both the attacker's path and the real cookie header. If the cookie starts with "session=A", the compressor will notice the duplication and produce a slightly shorter ciphertext. If the cookie starts with "session=B", there is no duplication, and the ciphertext is one or two bytes longer.

By cycling through 256 possible byte values for the first byte of the cookie, the attacker observes which probe produces the shortest ciphertext. That probe revealed the first byte. Repeat for the second byte, and so on. The whole cookie falls in seconds, because each byte requires only 256 probes and TLS records can be requested at thousands per second over JavaScript.

CVE-2012-4929 was assigned to CRIME. The fix was straightforward: disable TLS compression. By 2012, every major browser and TLS server stack turned it off, and TLS 1.3 (RFC 8446, 2018) removed compression support from the protocol entirely.

## The BREACH Variant

CRIME was killed within months because TLS compression was a single feature you could disable. But the underlying cryptographic principle was not specific to TLS. Any time you compress data that mixes attacker-chosen content with a secret, you have a potential side channel.

In August 2013 at Black Hat USA, Yoel Gluck, Neal Harris, and Angelo Prado presented BREACH (Browser Reconnaissance and Exfiltration via Adaptive Compression of Hypertext). Instead of attacking TLS-level compression, BREACH attacked HTTP-level compression. Most web servers compress their HTML, JSON, or text responses with gzip before sending them to the browser. The compression happens at the HTTP layer, inside the encrypted TLS record.

BREACH relied on three preconditions. First, the response body had to contain a secret (such as a CSRF token embedded in an HTML form). Second, the response body had to also reflect attacker-controlled input (such as a query parameter echoed back into the page). Third, HTTP compression had to be enabled, which it usually was for performance reasons.

The attacker fires requests to the target site with varying input. The server reflects the input back into the response. If the input matches a prefix of the secret CSRF token, the response compresses smaller. If it does not, the response compresses bigger. The attacker measures the encrypted response length, identifies the smallest one, and learns the next byte of the token.

CVE-2013-3587 covers BREACH. Unlike CRIME, BREACH could not be fixed by disabling a single TLS feature. The vulnerability lived at the application layer, in the interaction between HTTP compression and reflected user input. Each web application had to decide how to mitigate it.

## Mitigating BREACH in Practice

The cleanest fix is to never compress responses that contain secrets. If your CSRF tokens, session identifiers, or other secrets live in HTML responses, you can disable HTTP compression for those specific endpoints. This costs bandwidth, but it eliminates the side channel.

The second-cleanest fix is to randomize the secret on every response. If the CSRF token is regenerated for every request and not the same across requests, the attacker cannot use successive probes to converge on a single value. This requires server-side machinery to mint fresh tokens but works well in practice.

The third fix is to add randomness to the compressed output. By padding the response with a random number of random bytes, you blur the compression signal. The attacker still gets some information, but each byte recovery requires far more probes. This is sometimes called "length masking," and it is a partial defense rather than a complete one.

The fourth fix, which most large web applications adopted, is to combine all of the above. Disable compression for sensitive endpoints, randomize tokens, and add request-rate-limiting to block the high-volume probing that BREACH requires.

## TIME and Other Variants

CRIME and BREACH were not the only compression side channels. Tal Be'ery and Amichai Shulman published TIME (Timing Info-leak Made Easy) in 2013, which used response timing rather than response length to extract the same information. TIME was particularly nasty because it could attack scenarios where the attacker could not measure the response length directly but could time how long it took for the response to arrive.

In 2016, Karthikeyan Bhargavan and Gaetan Leurent showed how 64-bit block ciphers like 3DES and Blowfish could be exploited via the Sweet32 attack (CVE-2016-2183), which used birthday paradox collisions on long-lived TLS connections. Sweet32 is structurally different from CRIME or BREACH but lives in the same family of attacks where the protocol leaks something it should not because of an interaction between cipher properties and ambient communication patterns.

## What These Attacks Teach

The biggest lesson is that compression and encryption do not compose safely when an attacker can influence the plaintext. This is now standard knowledge in cryptographic engineering. Modern protocol designs avoid mixing the two unless you can prove the threat model excludes adaptive plaintext attacks.

The second lesson is that side channels are everywhere. Length, timing, power, and electromagnetic emissions all leak. Cryptographic engineers have to think about which channels are observable in their threat model and either eliminate them, mask them with noise, or make the attack so expensive that it becomes impractical. See [AES-256-GCM Explained](aes-256-gcm-explained.md) for how modern AEAD modes try to avoid timing-based side channels in the encryption itself, even though they cannot prevent application-layer leaks like BREACH.

The third lesson is that protocol features added for performance can break security. TLS compression was added because it sped up page loads on slow connections. The performance benefit was real, but the security cost (CRIME) made it indefensible. Whenever you propose a new protocol optimization, you have to check whether it interacts safely with the secrets the protocol carries.

## Why Post-Quantum Migrations Need to Watch for This

As the world moves toward post-quantum cryptography, the same compression-versus-encryption tension will appear in new places. ML-KEM ciphertexts are large (around 1.5 KB for ML-KEM-1024). Engineers will be tempted to compress key exchange messages or post-quantum signatures to save bandwidth. If those messages travel over channels where attackers can influence the plaintext, the same CRIME-style attack could resurface.

This is one reason QNSQY does not compress encrypted output. Each .qs file is laid out with deterministic block boundaries and no compression. The resulting files are slightly larger than they could be, but the trade-off avoids any compression side channel. See [What Is Post-Quantum Cryptography](what-is-post-quantum-cryptography.md) for a broader walk-through of how PQC algorithms are being deployed in real systems and where the size-vs-security trade-offs land.

## How QNSQY Avoids Compression Side Channels

QNSQY uses AES-256-GCM for symmetric encryption with a fresh random nonce per file. There is no compression at any layer of the file format. Sensitive metadata (like the recipient list in multi-recipient encryption) is included verbatim, not compressed. The file size grows with input size in a predictable way that does not vary based on the relationship between attacker-controlled and secret content.

The hybrid PQC + classical key encapsulation uses [ML-KEM Explained](ml-kem-explained.md) combined with X25519, both of which produce fixed-size ciphertexts. There is no length-leak channel in the KEM step. The signature uses ML-DSA combined with Ed25519, again with fixed-size signatures. Whether a file is signed or not produces a deterministic length difference, but within a given configuration, every signature is the same length.

If you read [Hybrid Encryption](hybrid-encryption.md), you will see how the layering further reduces side-channel risk: even if a future attack found a length leak in one layer, the other layer would still be hiding the secret.

## FAQ

**Why was TLS compression added in the first place?**
TLS compression was added in RFC 3749 (2004) to reduce bandwidth on slow connections. At the time, dial-up and early broadband meant every byte mattered. The performance gain was significant for text-heavy pages. CRIME made the trade-off unacceptable, and TLS 1.3 removed compression entirely.

**Are CRIME and BREACH still relevant in 2026?**
CRIME is dead because TLS compression is gone from modern stacks. BREACH is still relevant for any web application that compresses responses containing reflected input plus secrets. Most large applications have implemented mitigations, but smaller sites still have the issue. Periodically scanning for BREACH conditions is part of standard application security practice.

**Does HTTP/2 or HTTP/3 reintroduce compression risks?**
HTTP/2 has HPACK header compression, which had its own variant of the compression-leak issue (CVE-2016-1546 in nghttp2 and others). HTTP/2 implementations have specific defenses against the worst variants. HTTP/3 uses QPACK, which inherits HPACK's design with similar care taken around side channels.

**Could BREACH apply to JSON APIs?**
Yes. If your JSON API echoes user input and includes a secret token in the response, BREACH applies. The same mitigation pattern works: disable compression, randomize tokens, or rate-limit probing.

**Is QNSQY affected by anything like CRIME or BREACH?**
No. QNSQY uses no compression in the file format, so there is no compression side channel. The AEAD encryption produces deterministic ciphertext lengths for a given input size.

## Sources

1. Rizzo, J., and Duong, T. "The CRIME Attack." Ekoparty 2012 presentation.
2. CVE-2012-4929. MITRE CVE database. Published 2012-09-15. https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2012-4929
3. Gluck, Y., Harris, N., and Prado, A. "BREACH: Reviving the CRIME Attack." Black Hat USA 2013. https://www.breachattack.com/resources/BREACH%20-%20BH%202013%20-%20PRESENTATION.pdf
4. CVE-2013-3587. MITRE CVE database. Published 2013-08-01. https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2013-3587
5. Hollenbeck, S. "Transport Layer Security Protocol Compression Methods." RFC 3749, IETF, May 2004. https://www.rfc-editor.org/rfc/rfc3749
6. Bhargavan, K., and Leurent, G. "On the Practical (In-)Security of 64-bit Block Ciphers: Collision Attacks on HTTP over TLS and OpenVPN." ACM CCS 2016 (Sweet32). https://sweet32.info

## Related Articles

- [AES-256-GCM Explained](aes-256-gcm-explained.md)
- [Hybrid Encryption](hybrid-encryption.md)
- [ML-KEM Explained](ml-kem-explained.md)
- [What Is Post-Quantum Cryptography](what-is-post-quantum-cryptography.md)
- [Harvest Now Decrypt Later](harvest-now-decrypt-later.md)

---

### Protect Your Data Before Q-Day Arrives

QNSQY's NIST-standardized post-quantum encryption protects files against both current and quantum-era threats.

[Try QNSQY](../../pricing.html)
