Comparison of Symmetric Encryption Methods

There seems to be a lot of interest among software developers in the various cryptographic building blocks (block ciphers, hash functions, etc.), and more specifically how they stack up against each other.

Today, we’re going to look at how some symmetric encryption methods stack up against each other.

If you’re just looking for a short list of cryptographic “right answers”, your cheat sheet can be found on Latacora’s blog.


AES-GCM vs. ChaCha20-Poly1305

  • If you have hardware acceleration (e.g. AES-NI), then AES-GCM provides better performance. If you do not, AES-GCM is either slower than ChaCha20-Poly1305, or it leaks your encryption keys in cache timing.
  • Neither algorithm is message committing, which makes both unsuitable for algorithms like OPAQUE (explanation).
  • AES-GCM can target multiple security levels (128-bit, 192-bit, 256-bit), whereas ChaCha20-Poly1305 is only defined at the 256-bit security level.
  • Nonce size:
    • AES-GCM: Varies, but standard is 96 bits (12 bytes). If you supply a longer nonce, this gets hashed down to 16 bytes.
    • ChaCha20-Poly1305: The standardized version uses 96-bit nonces (12 bytes), but the original used 64-bit nonces (8 bytes).
  • Wearout of a single (key, nonce) pair:
    • AES-GCM: Messages must be less than 2^32 – 2 blocks (a.k.a. 2^36 – 32 bytes, a.k.a. 2^39 – 256 bits). This also makes the security analysis of AES-GCM with long nonces complicated, since the hashed nonce doesn’t start with the lower 4 bytes set to 00 00 00 02.
    • ChaCha20-Poly1305: ChaCha has an internal counter (32 bits in the standardized IETF variant, 64 bits in the original design).
  • Neither algorithm is nonce misuse resistant.

Conclusion: Both are good options. AES-GCM can be faster with hardware support, but pure-software implementations of ChaCha20-Poly1305 are almost always fast and constant-time.

Back to the top

AES-GCM vs. XChaCha20-Poly1305

  • XChaCha20 accepts 192-bit nonces (24 bytes). The first 16 of the nonce are used with the ChaCha key to derive a subkey, and then the rest of this algorithm is the same as ChaCha20-Poly1305.
  • To compare AES-GCM and ChaCha20-Poly1305 for encryption, see above.
  • The longer nonce makes XChaCha20-Poly1305 better suited for long-lived keys (i.e. application-layer cryptography) than AES-GCM.

Conclusion: If you’re using the same key for a large number of messages, XChaCha20-Poly1305 has a wider safety margin than AES-GCM. Therefore, XChaCha20-Poly1305 should be preferred in those cases.

Back to the top


AES-GCM is AES in Galois/Counter Mode, AES-CCM is AES in Counter with CBC-MAC mode.

Although I previously stated that AES-GCM is possibly my least favorite AEAD, AES-CCM is decidedly worse: AES-GCM is Encrypt-then-MAC, while AES-CCM is MAC-then-encrypt.

Sure, CCM mode has a security proof that arguably justifies violating the cryptographic doom principle, but I contend the only time it’s worthwhile to do that is when you’re building a nonce-misuse resistant mode (i.e. AES-SIV-GCM).

A lot of cryptography libraries simply don’t even implement AES-CCM; or if they do, it’s disabled by default (i.e. OpenSSL). A notable exception is the Stanford Javascript Cryptography Library, which defaults to AES-CCM + PBKDF2 for encryption.

Conclusion: Just use AES-GCM.

Back to the top


AES-GCM-SIV encryption runs at 70% the speed of AES-GCM, but decryption is just as fast. What does this 30% encryption slowdown buy? Nonce misuse resistance.

Soatok is HYPED!!!
Nonce misuse resistance is really cool. (Art by Swizz)

The algorithms are significantly different:

  • AES-GCM is basically AES-CTR, then GMAC (parameterized by the key and nonce) is applied over the AAD and ciphertext. (Encrypt then MAC)
  • AES-GCM-SIV derives two distinct keys from the nonce and key, then uses POLYVAL (which is related to GHASH) over the AAD and message with the first key to generate the tag. Then the tag used to derive a series of AES inputs that, when encrypted with the second key, are XORed with the blocks of the message (basically counter mode). (MAC then Encrypt)

AES-GCM is a simpler algorithm to analyze. AES-GCM-SIV provides a greater safety margin. However, like AES-GCM, AES-GCM-SIV is also vulnerable to the Invisible Salamanders attack.

So really, use which ever you want.

Better security comes from AES-GCM-SIV, better encryption performance comes from AES-GCM. What are your priorities?

If we apply Colm’s advice, AES-GCM-SIV should be preferred over AES-GCM.

Conclusion: AES-GCM-SIV is better, but both are fine.

Back to the top


At the risk of being overly reductionist, AES-SIV is basically a nonce misuse resistant variant of AES-CCM:

  • Where AES-CCM uses CBC-MAC, AES-SIV uses CMAC, which is based on CBC-MAC but with a doubling step (left shift then XOR with the round constant).
  • AES-SIV is MAC then encrypt (so is AES-CCM).
  • AES-SIV uses AES-CTR (so does AES-CCM).

If you need nonce misuse resistance, AES-SIV is a tempting choice, but you’re going to get better performance out of AES-GCM.

AES-GCM also has the added advantage of not relying on CBC-MAC.

Conclusion: Prefer AES-GCM in most threat models, AES-SIV in narrower threat models where nonce misuse is the foremost security risk.

Back to the top


If you read the previous two sections, the conclusion here should be obvious.

  • AES-GCM-SIV is slightly better than AES-GCM.
  • AES-GCM is better than AES-SIV.

Conclusion: Use AES-GCM-SIV.

Back to the top


Just use AES-GCM. No contest.

AES-GCM is an authenticated encryption mode. It doesn’t just provide confidentiality by encrypting your message, it also provides integrity (which guarantees that nobody tampered with the encrypted message over the wire).

If you select AES-CBC instead of AES-GCM, you’re opening your systems to a type of attack called a padding oracle (which lets attackers decrypt messages without the key, by replaying altered ciphertexts and studying the behavior of your application).

If you must use AES-CBC, then you must also MAC your ciphertext (and the initialization vector–IV for short). You should also devise some sort of key-separation mechanism so you’re not using the same key for two different algorithms. Even something like this is fine:

  1. encKey := HmacSha256(“encryption-cbc-hmac”, key)
  2. macKey := HmacSha256(“authentication-cbc-hmac”, key)
  3. iv := RandomBytes(16)
  4. ciphertext := AesCbc(plaintext, iv, encKey)
  5. tag := HmacSha256(iv + ciphertext, macKey)

For decryption you need a secure compare function. If one is not available to you, or you cannot guarantee it will run in constant time, a second HMAC call with a random per-comparison key will suffice.

There is no possible world in which case unauthenticated AES-CBC is a safer choice than AES-GCM.

AES-CBC + HMAC-SHA256 (encrypt then MAC) is message-committing and therefore can be safely used with algorithms like OPAQUE.

The Signal Protocol uses AES-CBC + HMAC-SHA2 for message encryption.

Back to the top


Just use AES-GCM. No contest.

Unlike AES-GCM, AES-CTR doesn’t provide any message integrity guarantees. However, strictly speaking, AES-GCM uses AES-CTR under the hood.

If you must use AES-CTR, the same rules apply as for AES-CBC:

  1. encKey := HmacSha256(“encryption-ctr-hmac”, key)
  2. macKey := HmacSha256(“authentication-ctr-hmac”, key)
  3. nonce := RandomBytes(16)
  4. ciphertext := AesCtr(plaintext, nonce, encKey)
  5. tag := HmacSha256(nonce + ciphertext, macKey)

For decryption you need a secure compare function.

AES-CTR + HMAC-SHA256 (encrypt then MAC) is message-committing and therefore can be safely used with algorithms like OPAQUE.

Back to the top


If you find yourself trying to decide between CBC mode and CTR mode, you should probably save yourself the headache and just use GCM instead.

That being said:

AES-CTR fails harder than AES-CBC when you reuse an IV/nonce.

AES-CBC requires a padding scheme (e.g. PKCS #7 padding) which adds unnecessary algorithmic complexity.

If you have to decide between the two, and you have a robust extended-nonce key-splitting scheme in place, opt for AES-CTR. But really, unless you’re a cryptography engineer well-versed in the nuances and failure modes of these algorithms, you shouldn’t even be making this choice.

Back to the top


Never use ECB mode. ECB mode lacks semantic security.

Block cipher modes that support initialization vectors were invented to compensate for this shortcoming.

Conclusion: If you’re trying to decide between these two, you’ve already lost. Rethink your strategy.

Back to the top

AES vs. Blowfish

A lot of OpenVPN configurations in the wild default to Blowfish for encryption. To the authors of these configuration files, I have but one question:

Why?! (Art by Khia)

Sure, you might think, “But Blowfish supports up to 448-bit keys and is therefore more secure than even 256-bit AES.”

Cryptographic security isn’t a dick-measuring contest. Key size isn’t everything. More key isn’t more security.

AES is a block cipher with a 128-bit block size. Blowfish is a block cipher with a 64-bit block size. This means that Blowfish in CBC mode is vulnerable to birthday attacks in a practical setting.

AES has received several orders of magnitude more scrutiny from cryptography experts than Blowfish has.

Conclusion: Use AES instead of Blowfish.

Back to the top

ChaCha vs. Salsa20

Salsa20 is an eSTREAM finalist stream cipher. After years of cryptanalysis, reduced round variants of Salsa20 (specifically, Salsa20/7 with a 128-bit key) were found to be breakable. In response to this, a variant called ChaCha was published that increased the per-round diffusion.

That is to say: ChaCha is generally more secure than Salsa20 with similar or slightly better performance. If you have to choose between the two, go for ChaCha.

Conclusion: Your choice (both are good but ChaCha is slightly better).

Back to the top

ChaCha vs. RC4

Don’t use RC4 for anything! What are you doing?

My reaction when I read that the CIA was using a modified RC4 in their Assassin malware instead of a secure stream cipher, per the Vault7 leaks. (Art by Khia)

RC4 was a stream cipher–allegedly designed by Ron Rivest and leaked onto a mailing list–that has been thoroughly demolished by cryptanalysis. RC4 is not secure and should never be relied on for security.

Conclusion: Use ChaCha. Never use RC4.

Back to the top

Cipher Cascades

A cipher cascade is when you encrypt a message with one cipher, and then encrypt the ciphertext with another cipher, sometimes multiple times. One example: TripleSec by Keybase, which combines AES and Salsa20 (and, formerly, Twofish–an AES finalist).

Cipher cascades don’t meaningfully improve security in realistic threat models. However, if your threat model includes “AES is broken or backdoored by the NSA”, a cipher cascade using AES is safer than just selecting a nonstandard cipher instead of AES. However, they’re necessarily slower than just using AES would be.

If you’re worried about this, your time is better spent worrying about key management, side-channel attacks, and software supply chain attacks.

Conclusion: Avoid cipher cascades, but they’re better than recklessly paranoid alternatives.

Back to the top

Symmetric Encryption Rankings

So with all of the above information, can we rank these algorithms into tiers?

Art by Riley

Sort of! Although it’s based on the above analyses, ranking is inherently subjective. So what follows is entirely the author’s opinion of their relative goodness/badness.

SXChaCha20-Poly1305, AES-SIV-GCM
AAES-GCM, ChaCha20-Poly1305
FAny: AES-ECB, RC4, Blowfish
Unauthenticated: AES-CBC, AES-CTR, Salsa20, ChaCha
Soatok’s ranking of symmetric encryption methods

7 replies on “Comparison of Symmetric Encryption Methods”

[…] This post is about why I dislike AES-GCM’s design, not “why AES-GCM is insecure and should be avoided”. AES-GCM is still miles above what most developers reach for when they want to encrypt (e.g. ECB mode or CBC mode). If you want a detailed comparison, read this. […]


This is an excellent blog Soatok. I look forward to speaking to you on Telegram. This blog really opened our eyes on the pros and cons of each and every cipher. You convinced me that XChaCha20-Poly1305 is the best general-use cipher.


Thank you for this high-level overview! Definitely makes it less overwhelming to a neophyte like myself. I’m trying to decide whether to go with gocryptfs to replace veracrypt for long-term encrypted storage, and I was wondering how you feel about this comparison chart (especially in regards to CryFS), and if there are more appropriate tools not considered (that use any of your S tier methods for example) :


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s