How to replicate MySQL aes-256-cbc in PHP

Using this article as a guide, I was able to successfully replicate MySQL aes-128-ecb in PHP:

final class Encryption
{

  // The key
  const KEY = '36F3D40A7A41A827968BE75A87D60950';

  /**
   * Encrypt a string
   *
   * @access public
   * @static
   * @param string $string
   * @return string
   */
  public static function encrypt($string)
  {
    return mcrypt_encrypt(MCRYPT_RIJNDAEL_128, self::getMySQLKey(self::KEY), self::getPaddedString($string), MCRYPT_MODE_ECB);
  }

  /**
   * Decrypt a string
   *
   * @access public
   * @static
   * @param string $string
   * @return string
   */
  public static function decrypt($string)
  {
    return rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_128, self::getMySQLKey(self::KEY), $string, MCRYPT_MODE_ECB), "\x00..\x10");
  }

  /**
   * Get MySQL key
   *
   * @access public
   * @static
   * @param string $key
   * @return string
   */
  public static function getMySQLKey($key)
  {

    // The new key
    $new_key = str_repeat(chr(0), 16);

    // Iterate over the key and XOR
    for ($i = 0, $l = strlen($key); $i < $l; ++$i)
    {
      $new_key[$i % 16] = $new_key[$i % 16] ^ $key[$i];
    }

    // Return the new key
    return $new_key;

  }

  /**
   * Get padded string
   *
   * @access public
   * @static
   * @param string $string
   * @return string
   */
  public static function getPaddedString($string)
  {
    return str_pad($string, (16 * (floor(strlen($string) / 16) + 1)), chr(16 - (strlen($string) % 16)));
  }

}

As an example:

// PHP, gives CJI+zJyviQI7GgSCLGMNsqsXq2MDKC3a9FIG3wDrE8Y=
base64_encode(Encryption::encrypt('michael@example.com'))

// MySQL, gives CJI+zJyviQI7GgSCLGMNsqsXq2MDKC3a9FIG3wDrE8Y=
SELECT TO_BASE64(AES_ENCRYPT('michael@example.com', '36F3D40A7A41A827968BE75A87D60950'));

However, I want to upgrade to using aes-256-cbc, but I'm having difficulties. I started by replacing MCRYPT_RIJNDAEL_128with MCRYPT_RIJNDAEL_256and MCRYPT_MODE_ECBby MCRYPT_MODE_CBCand used the constant KEYas the initialization vector:

  /**
   * Encrypt a string
   *
   * @access public
   * @static
   * @param string $string
   * @return string
   */
  public static function encrypt($string)
  {
    return mcrypt_encrypt(MCRYPT_RIJNDAEL_256, self::getMySQLKey(self::KEY), self::getPaddedString($string), MCRYPT_MODE_CBC, self::KEY);
  }

  /**
   * Decrypt a string
   *
   * @access public
   * @static
   * @param string $string
   * @return string
   */
  public static function decrypt($string)
  {
    return rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, self::getMySQLKey(self::KEY), $string, MCRYPT_MODE_CBC, self::KEY), "\x00..\x10");
  }

The problem is that now I get different values ​​from PHP and MySQL:

// PHP, gives XSRfnrl05CE7JIHCvfhq6D67O0mAW2ayrFv2YkjFVYI=
base64_encode(Encryption::encrypt('michael@example.com'))

// MySQL, gives lTLT4MRXcHnOAsYjlwUX4WVPHgYvyi6nKC4/3us/VF4=
SELECT TO_BASE64(AES_ENCRYPT('michael@example.com', '36F3D40A7A41A827968BE75A87D60950', '36F3D40A7A41A827968BE75A87D60950'));

I am not sure where to come from here, so any help would be appreciated.

And just to make sure MySQL really uses the right encryption method:

// aes-256-cbc
SELECT @@session.block_encryption_mode
+4
source share
2 answers

eggyal, Artjom B. , .

, AES-256 - MCRYPT_RIJNDAEL_128, MCRYPT_RIJNDAEL_256, - , AES-256 AES-128, 32- , 16- .

:

final class AESEncrypter
{

  // The key
  const KEY = 'F40E2A9E22150793C6D0CA9E316FEA42';

  // The IV
  const IV = '5C354934224F698E';

  /**
   * Encrypt a string
   *
   * @access public
   * @static
   * @param string $string
   * @return string
   */
  public static function encrypt($string)
  {
    return mcrypt_encrypt(MCRYPT_RIJNDAEL_128, self::getMySQLKey(self::KEY), self::getPaddedString($string), MCRYPT_MODE_CBC, self::IV);
  }

  /**
   * Decrypt a string
   *
   * @access public
   * @static
   * @param string $string
   * @return string
   */
  public static function decrypt($string)
  {
    return rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_128, self::getMySQLKey(self::KEY), $string, MCRYPT_MODE_CBC, self::IV), "\x00..\x10");
  }

  /**
   * Get MySQL key
   *
   * @access public
   * @static
   * @param string $key
   * @return string
   */
  public static function getMySQLKey($key)
  {

    // The new key
    $new_key = str_repeat(chr(0), 32);

    // Iterate over the key and XOR
    for ($i = 0, $l = strlen($key); $i < $l; ++$i)
    {
        $new_key[$i % 32] = $new_key[$i % 32] ^ $key[$i];
    }

    // Return the new key
    return $new_key;

  }

  /**
   * Get padded string
   *
   * @access public
   * @static
   * @param string $string
   * @return string
   */
  public static function getPaddedString($string)
  {
    return str_pad($string, (16 * (floor(strlen($string) / 16) + 1)), chr(16 - (strlen($string) % 16)));
  }

}

:

// PHP, gives mwVraDh/7jG3BvPJyYqgxY6Ca8CTRN5JHvwPGeV8Vd0=
base64_encode(AESEncrypter::encrypt('michael@example.com'))

// MySQL, gives mwVraDh/7jG3BvPJyYqgxY6Ca8CTRN5JHvwPGeV8Vd0=
SELECT TO_BASE64(AES_ENCRYPT('michael@example.com', 'F40E2A9E22150793C6D0CA9E316FEA42', '5C354934224F698E'))
0

AES - Rijndael, AES 128 128, 192 256 .

MCRYPT_RIJNDAEL_256 256 , , MCRYPT_RIJNDAEL_128 128 , . .

Rijndael , .

, iv , , AES 128 .

, .

+1

Source: https://habr.com/ru/post/1623921/


All Articles