Search code examples
phpencryptionaesmcrypt

mcrypt_encrypt adds unwanted bytes


I'm trying to encrypt some data using the MCRYPT_RIJNDAEL_128 algoritm. But somehow when I encrypt and afterwards decrypt, the decrypted data has randomly added bytes.

The input: string(13) "test@test.com"

The output: string(16) "test@test.com"

enter image description here

As you can see the output has 16 characters while the input has 13.

The following is the code used for encryption.

class Cipher
{

/**
 * The key/salt(bin2hex format) used to encrypt data with in AES(RIJNDAEL) format.
 * @var string
 */
private static $encryptionKey = 'baafbd1f8d752d920caae00ae550be8185c1183207a142c97c36fca3edc507da';

/**
 * Gets and transforms the encryption key to binary format.
 * @return string (in binary format)
 */
public static function getEncryptionKey()
{
    return hex2bin(self::$encryptionKey);
}

/**
 * Generates a new random main encryption key used to encrypt data.
 * Store the generated key in the private property of this class.
 * @param bool $strong Whether the encryption will be strong.
 * @return string The generated key in hexadecimal format.
 */
public static function generateEncryptionKey($strong = true)
{
    $keySize = mcrypt_get_key_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
    return bin2hex(openssl_random_pseudo_bytes($keySize, $strong));
}

/**
 * Creates an encryption key IV used to store near the database record for the encrypted data.
 * Use bin2hex function for a representational string.
 * @return string (in binary format)
 */
public static function createIv()
{
    $ivSize = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
    return mcrypt_create_iv($ivSize, MCRYPT_DEV_URANDOM);
}

/**
 * Encrypts a given string by the generated encryption key and generated IV.
 * @param string $string The string which will be encrypted.
 * @param string $iv The dynamic key used to encrypt.
 * @return string (in binary format)
 */
public static function encrypt($string, $iv)
{
    return mcrypt_encrypt(MCRYPT_RIJNDAEL_128, self::getEncryptionKey(), $string, MCRYPT_MODE_CBC, $iv);
}

/**
 * Decrypts a given string by the generated encryption key and generated IV.
 * @param string $string The binary string which will be decrypted.
 * @param string $iv The dynamic key which belongs to the encrypted string.
 * @return string The decrypted string.
 */
public static function decrypt($string, $iv)
{
    return mcrypt_decrypt(MCRYPT_RIJNDAEL_128, self::getEncryptionKey(), $string, MCRYPT_MODE_CBC, $iv);
}

}

The encryption key showed here isn't used in production or testing environments and is only used for display purposes.

The following is used to display the decryption

$iv = Cipher::createIv();
$emailAddress = Cipher::encrypt('test@test.com', $iv);

var_dump(Cipher::decrypt($emailAddress, $iv));exit;

I'm using the following environments:

Ubuntu: 14.10

PHP: PHP 5.5.9-1ubuntu4.3 (cli) (built: Jul 7 2014 16:36:58)


Solution

  • Those are just padding 0x00 characters added at the end, because the string's length for that cryptographic algorithms has to be a multiple of 16 (with 128 bit).

    Indeed, if you add at the end of your code:

    var_dump(bin2hex(Cipher::decrypt($emailAddress, $iv)));
    

    You can see that the last 6 characters are all 0's (which means there are 3 0x00 bytes at the end).

    To remove them, just run:

    $decrypted = rtrim($decrypted, "\0");