Store mcrypt values from PHP in MySQL

The mcrypt functions return a binary string, so you can store it in a VARBINARY or BLOB field or as VARCHAR or TEXT if you first base64 encode it.

When using the CBC (Cipher Block Chaining) mode, the input is divided into blocks of X bytes. The last block is then padded with NULL bytes by PHP before encryption. This means when you retrieve the result, you have to remove the padded NULL bytes with rtrim($value, "\0"). This only works 100% reliable for strings and not for binary content, because they can contain NULL bytes.

It's important to use a IV once per key! This means that you want to encrypt some user data, for example email, birthdate and gender, you have to use different IV's for each field. A common approach is to prepend the encrypted value with the IV.

The secret key and the IV's you use must be in some format, you can see it with:

mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC);

mcrypt_get_key_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC);

An example of storing some user data.

One way to generate a secret key - in this case 32 bytes:

$secret = bin2hex(openssl_random_pseudo_bytes(16));

We have 1 secret key $secretKey that has the same length as mcrypt_get_key_size(). We store this somewhere outside of the web directory.

We use the following class to encrypt / decrypt:

class Crypt {

  private $ivSize;
  private $maxKeySize;

  function __construct() {
    $this->ivSize =
    $this->maxKeySize =

  public function getIvSize() {
    return $this->ivSize;

  public function createIV() {
    return mcrypt_create_iv($this->ivSize,

  public function encrypt($s) {
    $iv = $this->createIV();
    return $iv .
        APP_ENC_KEY, $s,MCRYPT_MODE_CBC, $iv);

  public function decrypt($s) {
    $s = rtrim($s, "\0");
    $iv = substr($s, 0, $this->getIvSize());
    $s = substr($s, $this->getIvSize());
    return rtrim(
        APP_ENC_KEY, $s, MCRYPT_MODE_CBC, $iv));

Tag: , | Category: