我使用php mcrypt_encrypt
和mcrypt_decrypt()
使用以下参数加密和解密数据:
MCRYPT_RIJNDAEL_256
substr(hash("sha1", $some_var),0,32)
MCRYPT_MODE_CBC
substr(hash("sha1", $other_var),0,32)
然后将生成的字符串传递给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 =='
我用:
答案 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