添加MCrypt的AES-CBC加密后,数据未保存到数据库中或未正确解密

时间:2015-05-24 13:27:23

标签: php mysql encryption aes mcrypt

我遇到了我写的加密脚本的问题。我有数百个输入,因此我使用桶排序算法作为“脚本内”数据库,以避免处理数百个MySQL列的麻烦,更不用说节省代码空间。数据存储在SQL数据库的一列中。条目以'分隔,条目中的变量由>分隔。这就是为什么我用字符串替换加密的最终结果......以避免产生额外的分隔符。

ENCRYPT:

$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
$iv = mcrypt_create_iv($iv_size, MCRYPT_DEV_URANDOM);
$key = pack("H*", "**64CharacterStringHere**");

$value = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $value, MCRYPT_MODE_CBC, $iv);

$value = $iv . $value;

$value = str_replace (">", "9Y6SnNmOBl", $value);
$value = str_replace ("'", "SxsNEpBe18", $value);   

DECRYPT:

$value = str_replace ("9Y6SnNmOBl", ">", $value);
$value = str_replace ("SxsNEpBe18", "'", $value);

$iv = substr($value, 0, 16);
$value = substr($value, 16);

$key = pack("H*", "**64CharacterStringHere**");

$value = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $value, MCRYPT_MODE_CBC, $iv);

如果我从代码中省略这个代码段,它就能完美运行。数据显示并正常保存。但是,如果我添加此代码,有时数据将无法保存,如果至少有一个变量由于某种原因而无法解密,即使我100%确定该函数正在对每个变量运行,因为该功能不仅仅是加密和解密。

我完全不知道为什么会这样。

MySQL查询:

$new_accountant = "'" . $var_1 . ">" . $var_2;
$new_string = $string . $new_accountant;

$new_entry_query = 'UPDATE phone_tree SET string="' . $new_string  . '" WHERE id="' . $userid . '";';
mysql_query($new_entry_query);

在上面的脚本中,$string由MySQL查询定义,该查询获取包含迄今为止所有数据的列的当前值。

我现在正在搞乱它。它大约一半时间都没有保存,当它被保存时,变量在大约一半时间内无法正确解密。

我怀疑这是关于我如何存储IV的内容...这与变量有关,但我不知道我在做什么是一个问题。

1 个答案:

答案 0 :(得分:2)

在我看来,您的MySQL string列定义为varchar(nnn)数据类型。这是对的吗?

如果是这样,我建议你在加密材料存储到MySQL之前对其进行base-64编码,然后base-64对其进行解码?这是加密信息的传输和存储中的常见做法。它使您的材料安全。 MySQL可能正在抨击你的二进制数据。

base-64字符集(由php中实现的base-64的MIME版本使用)仅包含7位ASCII字符。它包括数字,大写和小写字母以及字符+ / =。这很好,因为您选择的分隔符(> ')不会出现在编码文本中,因此您可以摆脱符号填充{ {1}}代码。

在您进行编码时执行此操作,并跳过符号填充。

str_replace ("9Y6SnNmOBl", ">", $value)

在您解码时执行此操作,并跳过符号解压缩。

$value = base64_encode($iv . $value);

这使您的加密数据大约是原来的1.3倍。这与现代大容量存储价格相差无几,并且为简单性付出了合理的代价。如果它出现了难以逾越的成本障碍,您可以调查MySQL中的压缩行格式。