假设表中的每一行都有与一个特定用户有关的数据。用户具有访问系统的密码。
如何使用InnoDB加密一列数据,以便除了数据用户以外的任何人都无法读取数据?我正在考虑使用一个MySQL加密函数(比如AES)和一个基于根据用户密码计算的哈希的密钥。
有没有人对我如何做到这一点有任何指示?我是在正确的轨道上吗?
其中一个答案如下
修改用户密码的问题涉及通过新密码重新加密用户密钥,这比重新加密可以任意大的整组用户数据要简单得多。用户密钥在系统中的用户数据的整个生命周期内保持不变。
这有什么用?说密码是pass1。并且有一堆记录使用由此生成的密钥加密。如果用户现在将密码重置为pass2,我无法解密使用pass1加密的数据。在用户完全忘记密码的情况下,他的所有加密数据都将丢失。
我不知道用用户密码哈希加密数据是否有多大意义, 特别 如果你将哈希本身保留在数据库中。在这种情况下,任何可以访问加密数据的人也可以访问密码哈希并解密数据。
另一种方法是使用特定于应用程序的密钥加密数据,并使用某些特定于用户的数据。但是,您面临另一个问题:如何安全地存储应用程序密钥。对于这个问题,我不知道一个简单的答案,但是如果您担心数据库数据可能会受到损害,那么将其保留在源代码中可能就足够了,但源代码本身并不是这样。如果您的数据库存储在异地(想想Amazon S3)。
如果您只在数据库中保留密码的哈希值,那么使用用户密码保存应用密钥会有所帮助,但会引入另一个安全漏洞:您必须在应用会话中以明文形式保留用户密码。
至于技术解决方案,它非常简单 示例代码可用。您可以按如下方式对其进行修改,以使用密码哈希加密的应用程序密码加密数据:
INSERT INTO secure_table VALUES (
1,
AES_ENCRYPT(
'plain text data',
CONCAT(@application_password, @user_password))
);
在任何情况下,您都必须将应用程序密码存储在某处,因此我认为没有一种简单的方法可以提供完美的安全性。
我能想到的另一种方法是向用户询问可以用作加密密钥的简短PIN。 PIN不会存储在数据库中, 但 每次访问他们的数据时,您都需要询问用户。
当然,您必须考虑加密的可行性。如果没有解密,您将无法索引或搜索它。可能需要一组有限的数据(例如信用卡号),但我不会对它有所了解。
为了澄清问题中提到的答案之一:“user / app key”是随机生成的私钥,用于加密数据。私钥永远不会改变(除非它被泄露)。您使用密码加密和存储私钥。由于私钥比数据小得多,因此更改密码要便宜得多:您只需使用旧密码解密私钥并使用新密码对其进行重新加密。
对于非用户特定(全局)的数据,您可以使用对称和非对称密码的组合。你可以有一个 extra password
要求所有用户输入的字段,以便即使一个用户更改了一个密码,全局数据仍可用于具有不同密码的其他用户。
该 extra password
可以与另一个按位xor'ed salt-like string
在源代码中。它可以一起构成对称密钥来解密a private key
存储在数据库中(永远不会改变)。后 private key
使用。解密 extra password
,私钥可以解密和 read
db中的所有数据。私钥可以存储为会话变量。
该 public key
顾名思义,它可以作为纯文本字符串驻留在数据库中。当你需要的时候 write
到db,使用公钥加密数据。
您可以定期为用户提供新的 extra password
并重新加密静态 private key
接着是xor'ing salt-like string
。
如果数据是用户特定数据而不是其他用户,则可以使用用户密码而不使用额外密码字段来加密私钥。管理员可以为特定用户提供另一个私钥副本,可以使用他的密码对其进行解密。
我不认为这是最好的方法,除非您强制要求用户永远不能更改密码,或者每次用户更改密码时都有办法重新加密所有内容。
您可以存储另一个密钥来加密/解密在创建新用户时可能生成的用户特定数据。我们称这个新的密钥用户密钥。此用户密钥也应在数据库中加密,最直接的方法是通过用户密码或任何其他密码密码(如密码和创建/修改时间等)对其进行加密。
我会在用户会话中保留解密的用户密钥,以便在会话期间的任何所需时间访问用户的数据。
修改用户密码的问题涉及通过新密码重新加密用户密钥,这比重新加密可以任意大的整组用户数据要简单得多。用户密钥在系统中的用户数据的整个生命周期内保持不变。
当然,只有在通过在登录时将实际用户密码发送到服务器来执行认证时才能使用该方法,因为数据库仅希望包含密码的散列。
说密码是pass1。并且有一堆记录使用由此生成的密钥加密。如果用户现在将密码重置为pass2,我无法解密使用pass1加密的数据
密钥需要以可逆的方式加密,以便可以解密
使用pass1并使用pass2重新加密。
总结一下:
存储在数据库中的是:单向加密密码(用于密码检查),
其他数据的加密密钥,使用明确密码(或以任何速率,以与存储在数据库中的方式不同的方式加密的密码)进行可逆加密,以及使用明文加密密钥可逆加密的其他数据。
每当您需要其他数据时,您必须具有清除(或者不同于数据库中存储的加密密码),读取加密密钥,使用密码对其进行解密,并使用该密码解密其他数据。
更改密码时,使用旧密码解密加密密钥,使用新密码加密并存储。
如果您需要在没有用户交互的情况下访问数据(例如,对于数据库迁移),您将无法使用密钥进行解密。