转换php mcrypt_encrypt并解密为mysql函数

时间:2015-08-05 21:24:11

标签: php mysql encryption hash cryptography

我使用php mcrypt_encryptmcrypt_decrypt()使用以下参数加密和解密数据:

  • $ cipher:MCRYPT_RIJNDAEL_256
  • $ key:32位散列sha1,生成如下substr(hash("sha1", $some_var),0,32)
  • $ data:可以是数字或字符串
  • $ mode:MCRYPT_MODE_CBC
  • $ iv:生成如下substr(hash("sha1", $other_var),0,32)
  • 的32位散列sha1

然后将生成的字符串传递给base64_encode,结果就是加密数据。 最终的功能类似于:

function encrypt($data, $key1, $key2) {
    return
            trim( base64_encode( mcrypt_encrypt(
                    MCRYPT_RIJNDAEL_256,
                    substr($key1,0,32),
                    $data,
                    MCRYPT_MODE_CBC,
                    substr($key2,0,32)
            )));
    }

我想使用mysql做同样的事情,所以我可以在选择数据时解密数据。 我想编写加密我的数据的 mysql函数,就像上面的php encrypt函数一样。

我搜索了mysql文档,发现AES_ENCRYPT可以执行与mcrypt_encrypt相同的操作,而TO_BASE64(str)可以执行base64_encode

的功能
CREATE DEFINER=`root`@`localhost` FUNCTION `mcrypt_encrypt`(
    _data text,
    _key1 varchar(40),
    _key2 varchar(40)  
) RETURNS varchar(40) CHARSET utf8
BEGIN
    DECLARE encryData varchar(40);        
    SET @@session.block_encryption_mode = 'aes-256-cbc';
    SET encryData = AES_ENCRYPT(
        _data,
        SUBSTRING(key1,1,32),
        SUBSTRING(key2,1,32)
    );

RETURN TO_BASE64(encryData);

END

但它不能用作php函数。

echo encrypt('abcdefg', $key1, $key2);的输出

  • $key1是'5c2787d529149d3016ce50451290df1779ec93c7'
  • $key2是'33db3475db4badb7f6ba86489257c873610e9298' 是'FO51NxIIdOO / UQYtCTGhf2O0eq52C0AnRNTr9CxdOZc ='

同时输出

Select mcrypt_encrypt(
    'abcdefg',
    '5c2787d529149d3016ce50451290df1779ec93c7',
    '33db3475db4badb7f6ba86489257c873610e9298'
) as a

是'FQ =='

我用:

  • XAMPP for Linux 5.6.8-0!
  • PHP Version 5.6.8
  • MySQL 5.6.24 - 来源分发
  • 我在mysql中禁用区分大小写

1 个答案:

答案 0 :(得分:1)

您创建的问题是您在PHP中使用RIJNDAEL,这与AES不同。 AES是RIJNDAEL的子集,这意味着使用RIJNDAEL可能会使用AES不可用的参数 - 因此只使用AES时,RIJNDAEL的加密可能无法解密。

StackOverflow上有一个问题详细说明:Differences Between Rijndael and AES

关键区别:AES总是使用128位块,并允许使用128,192和256位长度的密钥(发布的攻击表明使用128位密钥是最好的安全性,因为下面的密钥可能会被削弱128位 - IIRC它在112位区域,仍然足够,但你永远不知道。)

PHP提供的RIJNDAEL指定BLOCK LENGTH - RIJNDAEL-256使用256位的块长度,允许128,192或256位密钥长度。与AES兼容的唯一方案是RIJNDAEL-128,具有128位块长度。

关于你的其他加密选项的两个评论:我并不特别喜欢密钥是散列函数的结果,因为这会将不同字符的数量减少到16个。攻击者,知道只有32个十六进制字符已被使用将真正欢迎这个信息,因为它极大地减少了搜索工作量。 32字节0-255:1.1E + 77种组合。 32个字节的16个字符:1.2E + 24。使用62小写,大写和数字:2.2E + 57组合。

初始化矢量也应该是纯随机的。一般用法是将创建的IV添加到密码结果的前面并在解密之前从那里拆分。这是为了防止将相同的明文加密到相同的密文 - 随机性是您可以做的最佳选择 - 其他任何东西都可能削弱您的加密强度。

还有一件事:你必须把你拥有的数据填充到整块。有几种可用的填充方案,以"填充零字节"开头,但当前推荐的填充方案似乎是https://en.wikipedia.org/wiki/Padding_(cryptography)#PKCS7