AES encryption in mysql and php

后端 未结 4 1244
夕颜
夕颜 2020-12-22 12:02

There is a function in Mysql AES_encrypt.

SELECT AES_encrypt( \"Hello World\", \"password\" ) AS encrypted_value 

This gives the result:

4条回答
  •  甜味超标
    2020-12-22 12:02

    mcrypt_encrypt is deprecated, so here's a solution that's capable of falling back on openssl_encrypt instead. Truthfully, I don't know how all of it works. It's kind of a composite of some solutions I found regarding replicating MySQL's AES_ENCRYPT in mcrypt_encrypt, and then replicating mcrypt_encrypt in openssl_encrypt. The generation of the key from what would otherwise be used as the salt arguments in AES_ENCRYPT, as well as understanding which cypher to use when, is a little beyond me. But I can say these functions have been time-tested to be functionally identical to their MySql counterparts.

    if (!function_exists('mysql_aes_key')) {
        /**
         * @param string $key
         * @return string
         */
        function mysql_aes_key($key)
        {
            $new_key = str_repeat(chr(0), 16);
            for ($i = 0, $len = strlen($key); $i < $len; $i++) {
                $new_key[$i % 16] = $new_key[$i % 16] ^ $key[$i];
            }
            return $new_key;
        }
    }
    
    if (!function_exists('aes_encrypt')) {
        /**
         * @param string $val
         * @param string $cypher
         * @param bool $mySqlKey
         * @return string
         * @throws \BadFunctionCallException
         */
        function aes_encrypt($val, $cypher = null, $mySqlKey = true)
        {
            $salt = getenv('SALT') ?: '1234567890abcdefg';
            $key = $mySqlKey ? mysql_aes_key($salt) : $salt;
    
            if (function_exists('mcrypt_encrypt')) {
                $cypher = (!$cypher || $cypher == strtolower('aes-128-ecb')) ? MCRYPT_RIJNDAEL_128 : $cypher;
                $pad_value = 16 - (strlen($val) % 16);
                $val = str_pad($val, (16 * (floor(strlen($val) / 16) + 1)), chr($pad_value));
                return @mcrypt_encrypt($cypher, $key, $val, MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB), MCRYPT_DEV_URANDOM));
            } elseif (function_exists('openssl_encrypt')) {
                //TODO: Create a more comprehensive map of mcrypt <-> openssl cyphers
                $cypher = (!$cypher || $cypher == MCRYPT_RIJNDAEL_128) ? 'aes-128-ecb' : $cypher;
                return openssl_encrypt($val, $cypher, $key, true);
            }
    
            throw new \BadFunctionCallException('No encryption function could be found.');
        }
    }
    
    if (!function_exists('aes_decrypt')) {
        /**
         * @param string $val
         * @param string $cypher
         * @param bool $mySqlKey
         * @return string
         * @throws \BadFunctionCallException
         */
        function aes_decrypt($val, $cypher = null, $mySqlKey = true)
        {
            $salt = getenv('SALT') ?: '1234567890abcdefg';
            $key = $mySqlKey ? mysql_aes_key($salt) : $salt;
    
            if (function_exists('mcrypt_decrypt')) {
                $cypher = (!$cypher || $cypher == strtolower('aes-128-ecb')) ? MCRYPT_RIJNDAEL_128 : $cypher;
                $val = @mcrypt_decrypt($cypher, $key, $val, MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB), MCRYPT_DEV_URANDOM));
                return rtrim($val, chr(0)."..".chr(16));
            } elseif (function_exists('openssl_decrypt')) {
                //TODO: Create a more comprehensive map of mcrypt <-> openssl cyphers
                $cypher = (!$cypher || $cypher == MCRYPT_RIJNDAEL_128) ? 'aes-128-ecb' : $cypher;
                return openssl_decrypt($val, $cypher, $key, true);
            }
    
            throw new \BadFunctionCallException('No decryption function could be found.');
        }
    }
    

    So...

    putenv('SALT=1234567890abcdefg');
    aes_encrypt('some_value') === SELECT AES_ENCRYPT('some_value', '1234567890abcdefg')
    aes_decrypt('some_encrypted_value') === SELECT AES_DECRYPT('some_encrypted_value', '1234567890abcdefg')
    

    I tested these by encrypting a value with the php function, and decrypting it with the MySQL one, and visa-versa.

提交回复
热议问题