Implementing AES Encryption in PHP

Advanced Encryption Standard (AES) is a specification for the encryption of electronic data established by the U.S. National Institute of Standards and Technology (NIST) in 2001. Also referenced as Rijndael, it is one of the most powerful encryption algorithms available today. Although there are some possible attacks (which will be discussed later), the algorithm was strong enough to become the first publicly accessible encryption algorithm that was approved by the National Security Agency (NSA) for encrypting top secret information. This tutorial will explain how AES encryption works and how to implement it in PHP.

How Does AES Work?

Technically speaking, AES can be described as an iterative, symmetric block cipher. It is iterative because the encryption process is done in multiple rounds, symmetric because it uses the same key for encryption and decryption and block cipher because it performs operations on blocks of data. Possible key lengths are 128, 192 and 256 bits (192 or 256-bit keys are required for top secret data). The number of iterations (rounds) is 10, 12 or 14, depending on the length of the key. Blocks of data are always 128 bits long.

Key expansions are the first step of the AES algorithm???deriving round keys from the cipher key using Rijndael key schedule. AES requires a separate 128-bit key for each round plus one more. After that, the algorithm starts performing operations on blocks of data. Each 128-bit block of data is copied into a two-dimensional array, creating a 4×4 matrix called the state matrix. The state matrix looks like this:

First AES iteration is called the initial round. The only operation performed in this round is AddRoundKey, where each byte of the state array is combined with a block of the round key using bitwise exclusive OR. The following rounds perform four different mathematical operations:

  • SubBytes – a non-linear substitution step where each byte is replaced with another according to an 8-bit substitution box, called the Rijndael S-box
  • ShiftRows – a transposition step where the last three rows of the state are shifted cyclically a certain number of steps
  • MixColumns – a mixing operation which operates on the columns of the state array, combining the four bytes in each column
  • AddRoundKey

The last round of processing is called the final round and it does not perform MixColumns operation. So, the final round performs only SubBytes, ShiftRows and AddRoundKey operations.

AES Implementation in PHP

There are many AES implementation in PHP. However, a lot of the code that can be seen on internet is very insecure and not to be used in production. provides a good starting example, but their code uses Zero byte padding and is not protected against padding oracle attacks. Having that in mind, in this tutorial I will use a PHP AES encryption?class that has implemented all the necessary security measures and has been informally reviewed by the PHP community. That class implements AES-128 encryption (AES-256 can be used by changing the key size inside the class), PKCS7 padding and authenticates messages with HMAC-SHA256. It requires PHP 5.4 or newer and OpenSSL PHP extension.

After importing the class, the AES encryption code would look like this:

// Import the PHP AES Encryption classrequire_once('Crypto.php');  try {      // Create a random key      // This key is a random binary      // Use scrypt, bcrypt or PBKDF2 to convert string into a key      $key = Crypto::CreateNewRandomKey();      // WARNING: Do NOT encode $key with bin2hex() or base64_encode(),      // they may leak the key to the attacker through side channels.  } catch (CryptoTestFailedException $ex) {      // Error handling      die('Cannot safely create a key');  } catch (CannotPerformOperationException $ex) {      // Error handling      die('Cannot safely create a key');  }  $message = "ATTACK AT DAWN";  try {      // Encrypt the message using the key generated above      $ciphertext = Crypto::Encrypt($message, $key);  } catch (CryptoTestFailedException $ex) {      // Error handling      die('Cannot safely perform encryption');  } catch (CannotPerformOperationException $ex) {      // Error handling      die('Cannot safely perform decryption'); 


The following code will decrypt AES encrypted messages:

try {      $decrypted = Crypto::Decrypt($ciphertext, $key);  } catch (InvalidCiphertextException $ex) { // VERY IMPORTANT      // Either:      //   1. The ciphertext was modified by the attacker,      //   2. The key is wrong, or      //   3. $ciphertext is not a valid ciphertext or was corrupted.      // Assume the worst.      die('DANGER! DANGER! The ciphertext has been tampered with!');  } catch (CryptoTestFailedException $ex) {      die('Cannot safely perform encryption');  } catch (CannotPerformOperationException $ex) {      die('Cannot safely perform decryption');  }

There is one more thing that is not mentioned here???key management. Since the same key is used for encryption and decryption, you will have to store the keys in a secure manner and implement key management strategies and best practices. Also, note that the code used in this tutorial is just for educational purposes and, in case you are developing an application with sensitive data, you should consult a security professional.

Share the Post:
Share on facebook
Share on twitter
Share on linkedin

Related Posts