简体   繁体   English

转换php mcrypt_encrypt并解密为mysql函数

[英]convert php mcrypt_encrypt and decrypt to mysql function

I was encrypting and decrypting data using php mcrypt_encrypt and mcrypt_decrypt() with the following arguments: 我正在使用带有以下参数的php mcrypt_encryptmcrypt_decrypt()加密和解密数据:

  • $cipher : MCRYPT_RIJNDAEL_256 $ cipher: MCRYPT_RIJNDAEL_256
  • $key : 32 bit hash sha1, generated as follow substr(hash("sha1", $some_var),0,32) $ key:32位哈希sha1,生成方式如下substr(hash("sha1", $some_var),0,32)
  • $data : can be number or string $ data:可以是数字或字符串
  • $mode : MCRYPT_MODE_CBC $ mode: MCRYPT_MODE_CBC
  • $iv : 32 bit hash sha1 generated as follow substr(hash("sha1", $other_var),0,32) $ iv:如下生成的32位哈希sha1 substr(hash("sha1", $other_var),0,32)

Then the generated string is passed to base64_encode and the result is the encrypted data. 然后将生成的字符串传递给base64_encode ,结果是加密数据。 The final function look something like: 最终函数如下所示:

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)
            )));
    }

i want to do the same thing using mysql , so i can decrypt data while selecting them. 我想使用mysql做同样的事情,因此我可以在选择数据时解密数据。 I want to write mysql function that encrypt my data the same as the php encrypt function above. 我想编写与上述php encrypt函数相同的mysql函数来加密我的数据。

I searched mysql documentation and found that AES_ENCRYPT can do the same thing as mcrypt_encrypt and TO_BASE64(str) can do the function of base64_encode 我搜索MySQL文档,发现AES_ENCRYPT可以做同样的事情, mcrypt_encryptTO_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

but it not working as the php function. 但它不能用作php函数。

the output of echo encrypt('abcdefg', $key1, $key2); echo encrypt('abcdefg', $key1, $key2);的输出echo encrypt('abcdefg', $key1, $key2); where 哪里

  • $key1 is '5c2787d529149d3016ce50451290df1779ec93c7' $key1是'5c2787d529149d3016ce50451290df1779ec93c7'
  • and $key2 is '33db3475db4badb7f6ba86489257c873610e9298' is 'FO51NxIIdOO/UQYtCTGhf2O0eq52C0AnRNTr9CxdOZc=' 并且$key2是'33db3475db4badb7f6ba86489257c873610e9298'是'FO51NxIIdOO / UQYtCTGhf2O0eq52C0AnRNTr9CxdOZc ='

while the output of 而输出

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

is 'FQ==' 是'FQ =='

i use: 我用:

  • XAMPP for Linux 5.6.8-0! XAMPP for Linux 5.6.8-0!
  • PHP Version 5.6.8 PHP版本5.6.8
  • MySQL 5.6.24 - Source distribution MySQL 5.6.24-源代码分发
  • i disable case sensitivity in mysql 我在MySQL中禁用区分大小写

The problem you created is that you are using RIJNDAEL in PHP, which is not the same as AES. 您创建的问题是您正在PHP中使用RIJNDAEL,这与AES不同。 AES is a subset of RIJNDAEL, which means that using RIJNDAEL may use parameters that are unavailable to AES - so an encryption with RIJNDAEL may not be decryptable when only using AES. AES是RIJNDAEL的子集,这意味着使用RIJNDAEL可能会使用AES无法使用的参数-因此,仅使用AES时,使用RIJNDAEL进行的加密可能无法解密。

There is a question on StackOverflow detailing this: Differences Between Rijndael and AES 关于StackOverflow,有一个问题对此进行了详细说明: Rijndael和AES之间的区别

The key difference: AES always uses 128 bit blocks, and allows using 128, 192 and 256 bit length for the key (with an attack published suggesting that using a 128 bit key is the best security because longer keys may be weakened below 128 bit - IIRC it was in the area 112 bit, still enough, but you never know). 密钥区别:AES始终使用128位块,并允许使用128、192和256位长度的密钥(已发布的攻击表明,使用128位密钥是最好的安全性,因为更长的密钥可能会减弱到128位以下- IIRC处于112位区域,仍然足够,但您永远不知道)。

RIJNDAEL as offered by PHP specifies the BLOCK LENGTH - RIJNDAEL-256 uses 256 bits of block length, allowing for 128, 192 or 256 bits of key length. PHP提供的RIJNDAEL指定了块长度-RIJNDAEL-256使用256位的块长度,允许128、192或256位的密钥长度。 The only scheme compatible with AES is RIJNDAEL-128 with 128 bits of block length. 唯一与AES兼容的方案是RIJNDAEL-128,具有128位的块长度。

Two remarks about your other crypto options: I don't particularly like the idea that the key is the result of a hash function, because this reduces the amount of different characters to 16. An attacker, knowing that only 32 characters of hex have been used will truly welcome this info because it reduces the search effort tremendously. 关于其他加密选项的两点评论:我不是特别喜欢密钥是哈希函数的结果的想法,因为这样可以将不同字符的数量减少到16。攻击者知道只有32个十六进制字符使用它会真正欢迎此信息,因为它极大地减少了搜索工作。 32 bytes 0-255: 1.1E+77 combinations. 32字节0-255:1.1E + 77组合。 32 bytes of 16 chars: 1.2E+24. 32个字节的16个字符:1.2E + 24。 Using 62 lowercase, uppercase and digits: 2.2E+57 combinations. 使用62个小写,大写和数字:2.2E + 57组合。

Also the initialization vector should be purely random. 同样,初始化向量应该是纯粹随机的。 The general usage is that the created IV is added to the front of the cipher result and split from there before decrypting. 一般用法是将创建的IV添加到密码结果的前面,并在解密之前从那里分割。 This is to prevent encrypting the same clear text to the same cipher text - randomness is simply the best choice you can make - anything else may weaken your cryptographic strength. 这是为了防止将相同的明文加密为相同的密文-随机性只是您可以做出的最佳选择-其他任何措施都可能削弱您的加密强度。

One more thing: You have to take care of padding the data you have to full blocks. 还有一件事:您必须注意将必须填充的数据填充到完整块中。 There are several padding schemes available, starting with "pad with zero bytes", but the current recommended padding scheme seems to be https://en.wikipedia.org/wiki/Padding_(cryptography)#PKCS7 有几种可用的填充方案,以“零字节填充”开头,但是当前推荐的填充方案似乎是https://en.wikipedia.org/wiki/Padding_(cryptography)#PKCS7

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM