如何在MySQL中存储“可查询”的加密数据?

时间:2011-10-26 15:52:09

标签: php mysql security encryption

我需要一种存储加密数据的方法,我仍然可以运行查询。这甚至可能吗?

至少我需要一个加密算法,它总是为同一个输入返回相同的字符串,所以我可以通过加密该字符串并在数据库中查找加密结果来找到所有名为“John”的用户。在PHP中,mcrypt总是返回不同的字符串(我知道这是故意的,以提高安全性)。

有什么想法吗?

2 个答案:

答案 0 :(得分:8)

取决于你如何存储'John'这个名字。如果它是特定领域中唯一的东西,你可以做类似

的事情
SELECT ...
FROM sometable
WHERE cryptedfirstname = AES_ENCRYPT('John', $key)

如果'John'是较大字符串的一部分('John Doe'或'King John,宇宙的统治者'),那么你必须解密整个字段并与之匹配

SELECT ...
FROM sometime
WHERE INSTR(AES_DECRYPT(cryptedFULLame, $key), 'John') > 0

请注意,我在查询中嵌入了解密密钥。生产系统的想法不好,但这只是一个例子。

您将无法执行以下操作:

...
WHERE INSTR(cryptedFULLname, AES_ENCRYPT('John', $key))

由于AES和大多数其他用户/体面的加密系统如何工作。

答案 1 :(得分:2)

听起来你理解这一点,但应该强调的是,一个始终为给定纯文本生成相同密文的加密算法会被破坏。它会导致各种攻击。

例如,有权访问您的数据库和应用程序的攻击者可以为字段选择值“John”,并使应用程序将其存储在数据库中。然后,他可以查看其记录的密文,并识别包含该密文的任何其他记录。他不需要为此获得钥匙。

如果要加密大的“不可预测的”唯一数字(例如,会话标识符或UUID),则会出现例外情况。在这种情况下,由于普通文本不再发生,并且攻击者无法预测有效的明文,因此不需要密文不可区分。

ECB模式中使用的任何对称密码都将从明文产生一致的密文,如果您总是使用相同的IV,则使用采用初始化向量的模式。这样做通常不是一个好主意。