为什么 PHP / MySQL 在某一特定 AES 字符串解密时会选择性地失败?
我通过 PHP5 中的 PDO 函数将敏感的 16 个字符的用户字符串存储在 MySQL 表中。我有一对本机加密/解密函数,如下所示:
function encrypt($in)
{
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$enc = mcrypt_encrypt(MCRYPT_RIJNDAEL_256,ENCRYPT_KEY, $in, MCRYPT_MODE_ECB, $iv);
return $enc;
}
function decrypt($in)
{
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$dec = mcrypt_decrypt(MCRYPT_RIJNDAEL_256,ENCRYPT_KEY, $in, MCRYPT_MODE_ECB, $iv);
return $dec;
}
其中 ENCRYPT_KEY 是先前定义的全局常量。
我首先对字符串进行加密(),然后将记录插入指定的表中。有时,我需要通过 SELECT 语句循环访问这些信息,然后对结果进行解密以进行处理。
现在,这种情况对于所有情况都完美发生,除了一个。
在选择/解密周期中,大约 50 条记录中的一条(也是唯一一条)解密为 gobbledy-goop。我看不出 加密() 和解密() 函数有什么问题,并且多次插入有问题的记录,结果相同。如下所示的调用:
echo decrypt(encrypt($string));
工作正常。因此,我唯一想到的是 MySQL 无法正确存储这个特定字符串的加密版本,但我不知道为什么。存储功能如下:
function update_sensitive_details($sensitive)
{
$this->store_sensitive = encrypt($sensitive);
try
{
$sql = "UPDATE table SET store_sensitive = ? WHERE (id = ?);";
$sth = $this->registry->db->prepare($sql);
$sth->execute(array($this->store_sensitive,$this->id));
}
catch (PDOException $p)
{
log_error($p);
return false;
}
return true;
}
这不会导致任何错误,我可以确认这实际上确实用数据更新了表(尽管因为它是加密的,所以在 phpMyAdmin 中查看时难以理解。
有谁知道什么是我唯一能想到的是 MySQL 没有正确存储特定的加密字符串,因为即使更改 16 个字符之一也可以解决这个问题。会被阻止PDO,但也许不是。
I'm storing a sensitive, 16 character user string in a MySQL table via the PDO functions within PHP5. I have a pair of native encryption/decryption functions as follows:
function encrypt($in)
{
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$enc = mcrypt_encrypt(MCRYPT_RIJNDAEL_256,ENCRYPT_KEY, $in, MCRYPT_MODE_ECB, $iv);
return $enc;
}
function decrypt($in)
{
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$dec = mcrypt_decrypt(MCRYPT_RIJNDAEL_256,ENCRYPT_KEY, $in, MCRYPT_MODE_ECB, $iv);
return $dec;
}
Where ENCRYPT_KEY is a previously defined global constant.
I firstly encrypt() the string, then INSERT the record into the nominated table. Every so often, I need to cycle through this information via a SELECT statement, then decrypt() the results for processing.
Now, this happens perfectly for every case except one.
On the select/decryption cycle, one (and only) record from about 50 decrypts as gobbledy-goop. I cannot see anything wrong with the encrypt() and decrypt() functions, and have repeatedly INSERTed the record in question with the same results. A call like below:
echo decrypt(encrypt($string));
Works fine. Therefore, the only thing that I have come up with is that MySQL is failing to correctly store the encrypted version of this particular string, but I'm at a loss as to why. The storage function is as follows:
function update_sensitive_details($sensitive)
{
$this->store_sensitive = encrypt($sensitive);
try
{
$sql = "UPDATE table SET store_sensitive = ? WHERE (id = ?);";
$sth = $this->registry->db->prepare($sql);
$sth->execute(array($this->store_sensitive,$this->id));
}
catch (PDOException $p)
{
log_error($p);
return false;
}
return true;
}
This does not result in any errors, and I can confirm that this does in fact update the table with data (although as it is encrypted it is unintelligable when viewed in phpMyAdmin.
Does anyone have any ideas about what might be going on here? I'm stumped. The only thing I can think of is that the particular encrypted string isn't being properly stored by MySQL, as even changing one of the sixteen characters fixes the problem. I would have thought this would have been prevented by PDO, but perhaps not.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
在解密之前,尝试先使用 base64_encode() 封装加密数据,然后再使用 base64_decode() 封装加密数据。在某些情况下,我在 MySQL 中遇到过数据损坏的情况,这总是能修复它。
Try wrapping your encrypted data with base64_encode() and then base64_decode() before decrypting it. I've had data corrupt in MySQL in some instances and this has always fixed it.