Skip to content

AES (Advanced Encryption Standard)

This algorithm is recommended

AES is considered secure6. Use AES with 128, 192 or 256 (pick the largest size feasible for your system) with GCM mode of operation. GCM provides authentication, which makes this an AEAD cipher.

A very good and fast alternative is ChaCha, which comes in less variations and there are fewer things that can be done wrong when implementing it. Also, ChaCha might be faster on certain hardware that does not provide AES hardware-acceleration (which most common chipsets, even embedded ones, provide).

Disclaimer: How to use recommendations from Cryptography Primer

The recommendations on Cryptography Primer are based on research on multiple sources that are freely available online, such as:

  • Research papers available on e.g. arxiv.org1
  • Recommendations of Cryptographic Library authors
  • BSI technical guidelines4
  • NIST publications5
  • Blogs of reknown cryptographers or cybersecurity experts
  • crypto.stackexchange.com2
  • security.stackexchange.com3
  • and occasionally other sources

As should always be the case, you should not take recommendations from a single source for granted, but instead find at least a second - or better, third - source that confirms this recommendation.

Also, if you are using recommendations for anything that will be used in a production setting or will be used by anyone that relies on it's cryptograhic properties, it is highly recommended to let your concept and implementation being reviewed by a reknown cybersecurity firm.

That being said, the author hopes that Cryptography Primer helps you find the correct algorithm to use for your scenario, and find the correct parameters and modes for a safe implementation.

On this page you will learn:

  • What is AES, and features does it provide?
  • How secure is AES?
  • What can I use instead of AES?
  • What modes of operation can I use with AES?

Quick Info

Advanced Encryption Standard
Names AES, Advanced Encryption Standard, Rijndael
Attributes Symmetric (Private Key), Block Cipher
Features Encryption, AEAD
Block Size 128 Bits (16 Bytes)
Private Key Sizes 128, 192, 256
First Published 1998

AES in Practice

Hint

The key sizes 192 and 256 do not change the block size. The block size is always 128 Bits, even when larger keys are being used.

AES comes in multiple forms: AES-128, AES-192, AES-256. The number specifies the size of the private key that is being used. The higher the number, the higher the security (but also the slower the encryption and decryption speed). Even the smallest 128 Bit (16 Bytes) key size is currently considered secure6 and safe to use mid-term. With AES-256 you can even achieve quantum resistance from the current state of research (Januar 2022)78.

AES Key Generation

Private keys for AES do not have to follow a specific form - they just need to be (crypto-secure) random bits of the required size. Other algorithms, such as RSA or EC, require the values to conform to some mathematical requirements, but AES keys do not.

Private keys for AES do not have to follow a specific form - they just need to be (crypto-secure) random bits of the required size. Other algorithms, such as RSA or EC, require the values to conform to some mathematical requirements, but AES keys do not.

However, it is important to make sure that the key is generated properly, because otherwise the key generation can be an attack vector - and maybe even a very easy one to attack, if key generation is not "random enough".

Here are a few recommendations that you should keep in mind when implementing AES key generation:

  • Use a CSPRNG (Cryptographically-secure Pseudo Random Number Generator) or HSM (Hardware Security Module), if possible
  • Otherwise make sure that you seed your random number generator properly (don't only use the current timestamp)
  • Always seed a key generator with new randomness - don't succinctly generate multiples keys from the same random number seed
  • Generate keys where they will be ultimately needed and stored - e.g. don't generate keys server-side to use them on the client, but generate them client-side instead.
  • Store private keys securely
  • Avoid transferring private keys
  • It is highly recommended to re-negotiate or rotate keys as often as possible. Don't see a Private Key as something "permanently" bound to a person or a node, but instead make it something ephemeral that can change on a frequent basis.

How to use passwords to encrypt/decrypt with AES

Usually you use AES in a manner that the key is derived from the password that a user has to enter to encrypt/decrypt the data. Because the key is of fixed length (either 128, 192 or 256 Bits - which are 16, 24 or 32 Bytes, respectively), you can not use the password as the key directly, because that would impose insecure and inpractical constraints on the password that the user has to choose.

Instead, a key derivation function is used to create an AES-compatible key from a password. PBKDF2 (Password Based Key Derivation Function 2) is a state of the art key derivation function.

See the code sample below.

Modes of operation

AES is a block-cipher, which means that it can only encrypt data with the exact block size of 128 Bits (16 Bytes). This means that it must be combined with a so-called "Mode of operation" in order to be able to encrypt arbitrary number of bytes.

There are modes that add authentication to the encryption, and there are modes that do not include authentication. You must absolutely authenticate your encrypted data, because this protects against CCA10. The easiest and safest choice is to use an authenticated mode of operation. Alternatively, you can implement Encryt-then-MAC12 yourself, but this can easily be done incorrectly.

"GCM" (Galois/Counter Mode) is highly recommended

GCM provides authentication, which prevents many different kinds of attacks, and is well studied and has proven to be very secure.

How to pick a mode if GCM is not available

You can decide your mode of operation using these few rules of thumb:

  1. If your platform provides GCM, then use GCM.
  2. If your platform does not provide GCM, use CCM, EAX or OCB modes (preference in this order, consider that OCB might require a license13).
  3. If your platform does not provide GCM, CCM, EAX or OCB, use CTR or CFB (preference in this order) and apply Encrypt-then-MAC12.
  4. If your platform also does not provide CTR or CFB, reconsider your platform.
  5. If you can not use a platform that provides better modes, use anything except ECB, do your own research on the security of the chosen mode, and apply Encrypt-then-MAC12.

Never ever use ECB.14

IV vs. nonce?

Neither an IV (initialization vector) nor a nonce are secret and are usually sent alongside the ciphertext.

What is an "Initialization Vector"?

The IV needs to be random (generated with a CSPRNG, as you can find in your crypto library). You must generate a new IV for each encrypted message.

What is a "Nonce"?

"Nonce" means "Number only used once". While this is also true for an IV, a nonce does not have the requirement to be random. You can safely use a steadily increasing number (a counter) as your nonce, but you must not re-use the same number for different encryptions. You must generate a new nonce for each encrypted message.

Modes with Authentication (AEAD)

Mode of Operation Full Name Description
GCM Galois/Counter Mode

This mode is recommended

The GCM mode uses a random initialization vector (IV) for better security. This means that the same encrypted plaintext does never result in the same ciphertext. See implementation notes for GCM.

CCM Counter with CBC-MAC

Considered secure

This mode is considered secure and you can safely use it. It is somewhat slower than GCM, though.

EAX unknown

Not widely used

This mode is not widely used and hence not widely studied, so it is unsure how secure it is. While it is rather easy to implement, it is also slower than other modes.

OCB Offset Codebook Mode

This mode is patented

The OCB mode is very, very fast and considered secure. However, it is patented in the U.S. It is free to use in open source software. If you want to use it in a commercial product, you would need to require a license13 or permission to use.

Implementation notes for GCM

GCM is by far the recommended mode of operation for AES, because:

  • It uses a nonce, which strengthens confidentiallity, because the same plaintext will not be encrypted to the same ciphertext.
  • It provides AEAD, which prevents CCA.
  • It is well supported. For example, it is used in the Web Crypto API21 and is mandatory in TLS 1.322.
  • It is fast (enough), even for high throughput demands.

However, it comes with one major caveat for implementers23. It supports a nonce of 96 Bits (12 Bytes), which is, depending on the field of application, not enough to use a random value and feel safe enough that it will be unique. After 281,474,976,710,656 messages, you have a 50% chance of re-using a nonce. In practical terms, cryptographers recommend not more than 4,294,967,296 (4 billion) messages with the same key and a random nonce. The fatal thing about this is that a nonce-reuse makes it relatively easy to recover the key and break the security completely (for future and potentially previous messages for this key).

So, if your field of application only encrypts a few thousands or hundred thousands of messages per key, and has a good CSPRNG, you should not face a problem here. For example, when used with TLS, which creates a new Private Key for each session, this is more than unlikely to occur. However, for e.g. password-based schemes, the same key will be used permanently, or at least for a very long time, which makes this more likely.

To prevent this problem that applies to usage of AES-GCM with long-term keys, it is recommended to either

  • Implement a key rotation mechanism, if feasible. This minimizes other attack vectors, too, and might prevent the impact of a stolen or broken key.
  • Implement a persistent storage and use a counter per Private Key as the nonce.
  • Use AES-GCM-SIV24 instead, which uses larger nonces that are considered secure when generated at random.

Modes without Authentication

Warning

You should only use modes without authentication when you have reasons to not use a mode with authentication (listed above).

Unauthenticated modes are vulnerable to CCA (Chosen Ciphertext Attack), which authenticated modes are not.

You must apply Encrypt-then-MAC12 manually in your encryption scheme to prevent CCA-attacks if you are forced to use an unauthenticated mode.

Mode of Operation Full Name Description
CTR Counter Mode

Use GCM or CCM instead, if possible

Because this mode does not provide authentication, it is not recommended. However, of all the unauthenticated modes, it is the one with the strongest safety attributes and that is the least easy one to implement incorrectly. If taken care11, the IV can be a nonce and does not need to be produced by a CSPRNG, which could be an advantage. Can be parallelized.

You must apply Encrypt-then-MAC12 manually when using an unauthenticated mode

CFB Cipher Feedback

Use GCM, CCM or CTR instead, if possible

This mode is pretty similar to CBC, but chains the blocks in a different way. It is also always used with an Initialization Vector, and the IV is required to be produced by a CSPRNG.

You must apply Encrypt-then-MAC12 manually when using an unauthenticated mode.

CTS Ciphertext Stealing

Not recommended

Ciphertext stealing is a variation of ECB or CBC, but is in practice only used like CBC. The difference is that the last two blocks are chained differently. The security is not notably different from CBC.

CBC Cipher Block Chaining

Not recommended

This mode requires padding, which makes it vulnerable to padding oracle attacks17.

ECB Electronic Code Book

Do not ever use this

This method is not recommended, because it does not introduce diffusion into the ciphertext, which means that the same block is encrypted to the same ciphertext, effectively leaking patterns, which can easily be used to gain information that should be hidden.

Security Recommendations

Recommended Discouraged
  • Use the largest key size that your system can handle. You can still feel secure when using 128 Bits, though, but more is better.
  • Use a mode that supports authentication (AE or AEAD): GCM is recommended (see above).
  • Use a key derivation function such as PBKDF2 to convert a password into an AES-compatible key.
  • When you need asymmetric encryption (e.g. sender and receiver can not share a password and can not use a key exchange algorithm), use AES together with RSA and encrypt the AES-key using the RSA public key.TODO: Create a page with detailed instructions
  • It is very important that you don't use the same `nonce` or `initialization vectiro` multiple times with the same key.
  • Don't use a mode without authentication. (detailed explanation on Tony Arcieri's blog)
  • Don't trust your crypto library's defaults - check that you are not accidentally use a discouraged practice, because your library has bad defaults.
  • Don't transmit the key between two parties. Either pre-share the key over a secure medium, use a key exchange algorithm (such as DH or ECDH) or an asymmetric encryption algorithm (such as RSA) for this.

Code Samples

AES key generation

This code sample shows how to securely generate a new AES key:

Warning

Do not use your regular "random" function for key generation, but use your crypto library's dedicated functions for this.

Info

This code sample requires the widely used pyca/cryptography package.

Install it with pip install cryptography or your favorite package manager.

from cryptography.hazmat.primitives.ciphers.aead import AESGCM

# Generate a random 256 Bit private key:
key = AESGCM.generate_key(bit_length=256)
print(key.hex())
// TODO
// TODO

Key derivation from passwords

This code sample show how to securely derive an encryption key from a password:

Info

This code sample requires the widely used pyca/cryptography package.

Install it with pip install cryptography or your favorite package manager.

from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC

# Salts should be randomly generated and need to be accessible
# whenever a key is derived from a password. So basically,
# the salt is usually stored/transmitted alongside the encrypted data.

salt = bytes.fromhex('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa') # EXAMPLE VALUE - DO NOT USE THIS!

# derive
kdf = PBKDF2HMAC(
    algorithm=hashes.SHA256(),
    length=32, # 32 Bytes = 256 Bits
    salt=salt,
    iterations=100000, # This should be the minimum. You can increase the iterations if your system can handle it
                       # to strengthen security.
)
key = kdf.derive(b"my great password")
print(key.hex())

# `key` can now be used with AES-256.

# When you use different key sizes (AES-128 or AES-192), you need to specify
# the corresponding length. 128 Bits = 16 Bytes, 192 Bits = 24 Bytes.

# Further processing can be done to use with AES-256-GCM (explanation and code samples coming soon...)
// TODO
// TODO

AES encryption and decryption

Here's a code sample on a simple use case to encrypt and decrypt data:

Info

This code sample requires the widely used pyca/cryptography package.

Install it with pip install cryptography or your favorite package manager.

import os
from cryptography.hazmat.primitives.ciphers.aead import AESGCM

# The text to be encrypted:
plaintext = b"I am secret"

# Can be None, when no associated data is required:
authenticated_text= b"authenticated but unencrypted data"

# Generate a random private key for this example:
key = AESGCM.generate_key(bit_length=256)

# Create an object that can encrypt/decrypt with the following cipher:
# Algorithm: AES
# Key Size: 256
# Mode of Operation: GCM - an authenticated mode (see "AEAD")
aesgcm = AESGCM(key)

# Generate a "nonce" for this encryption session of size 96 Bits (12 Bytes).
# A nonce ensures that the same plaintext is not encrypted to the same ciphertext, which strenghtens security:

nonce = os.urandom(12)
# Notice: NEVER re-use the same nonce with the same key. Using a counter - if feasible - is an appropriate
# way to prevent this. Using a random number might have a realistic chance of reuse,
# depending on the number of messages that are being encrypted, the implementation of the random number generator
# and the available entropy in the system.

# Encrypt the data and add the authenticated (but not encrypted) data:
ciphertext = aesgcm.encrypt(nonce, plaintext, authenticated_text)

# The content of "ciphertext" can now be shared via an untrusted medium.
# The receiver also needs to know the "nonce" and the authenticated text (when used),
# which can also be shared via an untrusted medium.

# Decrypt the ciphertext back into the plaintext:
plaintxt = aesgcm.decrypt(nonce, ciphertext, authenticated_text)

print(plaintext)

# Result: "I am secret"
// TODO
// TODO

Security Level

"Security Level" explained

In cryptography, anything that lets you decrypt a message or extract the secret key with less effort than "brute force" is considered a "break" or a possible "attack". "Brute force" means testing out the key in the whole key space - for 128 Bits (like in AES-128) this means trying all 340,282,366,920,938,463,463,374,607,431,768,211,456 possible values that an 128 Bit (16 Bytes) value can have. For 256 Bits (like in ChaCha20 or AES-256), these are 115,792,089,237,316,195,423,570,985,008,687,907,853,269,984,665,640,564,039,457,584,007,913,129,639,936 possible values.

As you can imagine, not every "attack" is a real problem. Having an attacker have to try out for example 2127 values (instead of 2128) is not a risk in practice.

With the help of certain "attacks" it is possible to reduce the key space required to try out in order to break the encryption. The lowest key space that you can attain for a given cipher using one or a combination of attacks is considered the "security level".

In cryptography, a key space of 280 (this is a security level of 80 Bits) has long been considered secure. This might no longer be the case, depending on how strong your security needs to be. The BSI (German Institute of Cybersecurity) recommends a security level of at least 100 Bits and even 120 Bits for high security15 in 2022.

The security level of a cipher is not fix in time. It might become lower if attacks on the cipher have been found. That is why security recommendations are valid usually not more than one or two years into the future.

In 2022, AES is considered to have the following security levels:

What does it mean when a cipher is "broken"?

In cryptanalysis, which is the science of analysing and breaking cryptographic primitives, a cipher is "broken" if a way is found to decrypt the ciphertext or find the Private Key in less rounds than a brute force attack, which means trying all possible values in the Private Key's key space.

In practice, not every cipher that is "broken" by the definition of cryptanalysis is indeed insecure. For example, for AES a technique was found to reduce the theoretic maximum key space of 256 Bits down to 254 Bits. Because this reduced key space is still large enough for modern encryption requirements, AES is still very secure, although you might find statements that it has been "broken".

Variation Security Level Considered Secure?
AES-128 126.1 Bits :fontawesome-solid-check-circle:
AES-192 189.7 Bits :fontawesome-solid-check-circle:
AES-256 254.4 Bits :fontawesome-solid-check-circle:

The security level is lower than the raw key size, because there is an attack method that allows to lower the key space that is required to be searched in order to break an encryption. This attack is called the "Biclique attack"16.

Alternatives

Other Symmetric Encryption algorithms are:

Overview of encryption algorithms

Algorithm Key Sizes Type Authentication?
(AE or AEAD)
Recommendation
AES 128, 192 or 256 Bits

Symmetric

128 Bit Block Cipher

via GCM mode

Recommended

This algorithm is considered very secure and widely studied and deployed. GCM or CBC modes are recommended.

ChaCha 256 Bits

Symmetric

Stream Cipher

via Poly1305

Recommended

ChaCha20 is considered very secure and is widely studied and deployed. Use of Poly1305 is recommended.

RSA >= 1028 Bits

Asymmetric

Block Cipher
?

Recommended

This algorithm is considered very secure. Usually used with an symmetric encryption algorithm, while RSA "only" encrypts the symmetric key.

ECIES 256 Bits

Asymmetric (Hybrid)

Block Cipher or Stream Cipher possible
?

Recommended (but can be hard to implement)

This encryption scheme is considered very secure. It is not a precicse defined algorithm, but instead a framework to implement encryption when knowing the receiver's Elliptic Curve public key. It can be used with symmetric encryption algorithms (recommended: AES or ChaCha20).

Camellia 128, 192 or 256 Bits

Symmetric

Block Cipher

Considered secure

This algorithm is considered secure, but is not as widely studied or deployed as AES or ChaCha20

3DES 112 or 168 Bits

Symmetric

64 Bit Block Cipher

Less secure than AES and ChaCha20

This algorithm is not inherently insecure, but it is less secure than AES or ChaCha20, and computationally more expensive.

DES 56 Bits

Symmetric

64 Bit Block Cipher

Not recommended

This algorithm is no longer considered secure

Blowfish 32-448 Bits Symmetric 64 Bit Block Cipher

Not recommended

This algorithm is no longer considered secure

ARC4

(aka "RC4")
40-2048 Bits Symmetric Stream Cipher

Not recommended

This algorithm is no longer considered secure

IDEA 128 Bits Symmetric 64 Bit Block Cipher

Not recommended

This algorithm is no longer considered secure

History

Year Event
1998 First published by Vincent Rijmen, Joan Daemen
2001 Standardized by the NIST as the Advanced Encryption Standard (AES)
2003 Endorsed by the U.S. Government to protect classified information

References


  1. arXiv.org e-Print archive 

  2. Cryptography Stack Exchange 

  3. Information Security Stack Exchange 

  4. BSI - Cryptography on bsi.bund.de 

  5. NIST Computer Security Resource Center on nist.gov 

  6. Is 128-bit security still considered strong in 2020, within the context of both ECC Asym & Sym ciphers on crypto.stackexchange.com. 

  7. Is AES-256 a post-quantum secure cipher or not? on crypto.stackexchange.com. 

  8. Post-quantum cryptography on Wikipedia 

  9. Using Encryption and Authentication Correctly (for PHP developers) 

  10. All the crypto code you’ve ever written is probably broken as blogged by Tony Arcieri. 

  11. "Counter (CTR)" at "Block cipher mode of operation" on Wikipedia 

  12. Should we MAC-then-encrypt or encrypt-then-MAC? 

  13. Free Licenses on www.cs.ucdavis.edu by Phillip Rogaway 

  14. "Electronic codebook (ECB)" at "Block cipher mode of operation" on Wikipedia 

  15. BSI - Technical Guide - Cryptographic Mechanisms: Recommendations and Key Lengths on bsi.bund.de 

  16. Biclique attack on Wikipedia 

  17. Padding oracle attack on Wikipedia 

  18. Recommendation for Block Cipher Modes of Operation: Galois/Counter Mode (GCM) and GMAC on csrc.nist.gov 

  19. Hardware Security Module on Wikipedia 

  20. Cryptographically-secure pseudorandom number generator on Wikipedia 

  21. Web Crypto API's "SubtleCrypto.encrypt()" at MDN on developer.mozilla.org 

  22. RFC 8446: The Transport Layer Security (TLS) Protocol Version 1.3 on ietf.org 

  23. Why AES-GCM Sucks on soatok.blog 

  24. RFC 8452: AES-GCM-SIV: Nonce Misuse-Resistant Authenticated Encryption on ietf.org