我正在寻找一种方法,在数据进入MySQL数据库的过程中对其进行加密,并在数据出来的过程中对其进行解密。此外,我希望能够在这些字段上执行正常的SQL查询,例如搜索和比较,这使我无法使用纯PHP解决方案。
这让我想到了AES_ENCRYPT()和AES_DECRYPT(),它们可以在PHP中使用MCRYPT复制。
我在使用AES_DECRYPT时遇到了困难,我已经尝试了所有通过网上搜索能找到的建议。
这是我的表。
CREATE TABLE IF NOT EXISTS `test_table` (
`id` int(6) NOT NULL,
`secure_info` text NOT NULL,
`encrypted_blob` blob NOT NULL,
`encrypted` text NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
我进行了这些查询
INSERT INTO test_table (id, secure_info) VALUES (1,'Testing');
UPDATE test_table SET encrypted = AES_ENCRYPT(secure_info,'key') WHERE id=1 LIMIT 1;
UPDATE test_table SET encrypted_blob = AES_ENCRYPT(secure_info,'key') WHERE id=1 LIMIT 1;
SELECT *, AES_DECRYPT(encrypted,'key') as decrypted, AES_DECRYPT(encrypted_blob,'key') as decrypted_blob FROM test_table WHERE id=1;
我无法得到原始值 'decrypted'返回NULL,'decrypted_blob'返回54657374696e67。
有什么想法,或者也许有更好的解决方案?
Blob解密就可以了,"54657374696e67 "是 "Testing",只有十六进制编码。你可能是用一个将blob显示为十六进制的工具来执行的。文本解密不起作用(也不应该)。
MySQL中的TEXT字段要进行字符集转换。如果你用iso-8859连接,而表的存储在CP1252中,比如说,那么MySQL会在两个字符集之间自动转换文本。这将会破坏加密数据,因为原来8859数据中的一些字节会被转换为1252的等价物,而这些等价物具有不同的值。
另一方面,BLOB字段则会逐字通过,没有转换,所以解密时不会出错。
AES_ENCRYPT返回的是二进制字符串,所以不要使用文本列类型。
小贴士:主键的编号开始于 1
,不 0
提示2:尽量不要用MySQL关键字来命名你的字段。这可能会导致混淆,通常需要用回车符转义 (text
是一个例外)。)
如果你使用AES_ENCRYPT加密一个字符串,那么AES_DECRYPT返回的不是一个字符串,而是一个System.Byte的数组。 我用下面的代码把它还原成一个字符串。
Dim back As System.Byte()
back = DirectCast(reader(x), System.Byte())
Dim s As String = ""
For Each b As Byte In back
s &= Chr(b)
Next
同意@user187291的说法
我也有同样的问题,我发现在我的phpmyadmin中勾选了一个选项
将二进制内容显示为HEX
当我在mysql命令行中运行同样的查询时,它给我显示了正确的结果。
投放会将你的解密文本直接转换为原始格式。
SELECT *, CAST(AES_DECRYPT(encrypted_blob,'key') AS text) FROM test_table WHERE id = 1;