First off, my understanding of encrypting and hashing:
首先,我对加密和散列的理解:
- Encrypting - can be decrypted
- 加密 - 可以解密
- Hashing - can NOT be unhashed
- 哈希 - 不能没有散布
When building a web application, I should:
在构建Web应用程序时,我应该:
- Encrypt the email address (will be used to login) with encryption key. It's nice to be able to decrypt email addresses for later use (e.g. emailing users)
- 使用加密密钥加密电子邮件地址(将用于登录)。很高兴能够解密电子邮件地址供以后使用(例如通过电子邮件发送给用户)
- Hash the password with a salt. No one should be able to see user's password, so hashing (since it is one-way) is good.
- 用盐哈希密码。没有人应该能够看到用户的密码,因此散列(因为它是单向的)是好的。
If the above 2 points are right, where should I store the encryption key and salt?
如果以上2点是正确的,我应该在哪里存储加密密钥和盐?
If I store it in the DB, the seems a bit pointless should the DB ever be compromised. The benefit, though, is that I can assign a unique encryption key and salt for each user.
如果我将它存储在数据库中,那么DB应该受到损害似乎毫无意义。但是,好处是我可以为每个用户分配唯一的加密密钥和salt。
Should I store the encryption key and salt in my application's configuration? If the DB is ever compromised, at least the encryption key and salt are not also compromised (hopefully). The problem with this is that it probably means that everyone shares the same encryption key and salt.
我应该在应用程序的配置中存储加密密钥和salt吗?如果数据库遭到破坏,至少加密密钥和盐也不会受到损害(希望如此)。这个问题是它可能意味着每个人都共享相同的加密密钥和盐。
Suggestions on what to do?
关于该怎么办的建议?
3 个解决方案
#1
1
If you encrypt the email at all, you need to do it with a common salt/key. Otherwise, how are you going to select a user by his email address from the db to check whether the hashed password is correct? You can't decrypt every email address every time.
如果您根本加密电子邮件,则需要使用公共盐/密钥进行加密。否则,您将如何通过数据库中的电子邮件地址选择用户以检查散列密码是否正确?您不能每次都解密每个电子邮件地址。
Overall, I think there's very little to be gained from encrypting email addresses. Use MySQL database encryption if you want, but don't worry about this at the application level.
总的来说,我认为加密电子邮件地址几乎没有什么好处。如果需要,请使用MySQL数据库加密,但不要在应用程序级别担心这一点。
The salt for hashing the password should/needs to be unique and can be stored in the database, in fact it can be part of the hash itself. See http://www.openwall.com/phpass/ for a good implementation.
用于散列密码的salt应该/需要是唯一的并且可以存储在数据库中,实际上它可以是散列本身的一部分。请参阅http://www.openwall.com/phpass/以获得良好的实施。
#2
2
Your understanding seems correct to me.
你的理解对我来说似乎是对的。
Password: Only the hash of a password should be stored, together with a user specific salt. The salt can be stored plaintext, the reason for the salt is, that an attacker cannot use one single rainbowtable for all users (building a rainbowtable is expensive). It's recommended to use the hash_hmac()
function.
密码:只应存储密码的哈希值以及用户特定的盐。盐可以是明文存储的,盐的原因是,攻击者不能为所有用户使用单一的彩虹表(构建彩虹表是昂贵的)。建议使用hash_hmac()函数。
EMail: I think it's a good idea to encrypt these adresses, but however you do it, if the attacker has control over the server, he will be able to recover these addresses. I would put a secret key in a separate directory, which is outside the web root (cannot be accessed directly from the web). Don't write it in a file that can be delivered without interpreting, the extension *.php is better than *.inc . If you have no access to such a directory, at least make one and protect it with .htaccess Deny from all
.
电子邮件:我认为加密这些地址是个好主意,但无论如何,如果攻击者控制了服务器,他将能够恢复这些地址。我会将一个密钥放在一个单独的目录中,该目录位于Web根目录之外(无法直接从Web访问)。不要在没有解释的情况下将其写入文件中,扩展名* .php优于* .inc。如果您无法访问此类目录,请至少创建一个并使用.htaccess Deny保护它。
If you need to find an email address in the DB you can additionally store a hash, this allows to search case insensitive (first turn to lowercase, then generate the hash).
如果你需要在数据库中找到一个电子邮件地址,你可以另外存储一个哈希,这允许搜索不区分大小写(首先转到小写,然后生成哈希)。
#3
0
The salt should be per-user, and can be indeed in the database; thus the point of a salt is that someone with a copy of your db can't work on cracking all the passwords at once, but each separately.
盐应该是每个用户,并且可以确实在数据库中;因此,盐的一点是,拥有数据库副本的人不能同时破解所有密码,但每个密码都是分开的。
As for the encryption key, that's a much harder issue - definitely don't store it in the database; if your platform offers any kind of protected storage, you may want to use that. See e.g. this for useful answers: What's the best method to use / store encryption keys in MySQL
至于加密密钥,这是一个更难的问题 - 绝对不会将其存储在数据库中;如果您的平台提供任何类型的受保护存储,您可能希望使用它。参见例如这是有用的答案:在MySQL中使用/存储加密密钥的最佳方法是什么
#1
1
If you encrypt the email at all, you need to do it with a common salt/key. Otherwise, how are you going to select a user by his email address from the db to check whether the hashed password is correct? You can't decrypt every email address every time.
如果您根本加密电子邮件,则需要使用公共盐/密钥进行加密。否则,您将如何通过数据库中的电子邮件地址选择用户以检查散列密码是否正确?您不能每次都解密每个电子邮件地址。
Overall, I think there's very little to be gained from encrypting email addresses. Use MySQL database encryption if you want, but don't worry about this at the application level.
总的来说,我认为加密电子邮件地址几乎没有什么好处。如果需要,请使用MySQL数据库加密,但不要在应用程序级别担心这一点。
The salt for hashing the password should/needs to be unique and can be stored in the database, in fact it can be part of the hash itself. See http://www.openwall.com/phpass/ for a good implementation.
用于散列密码的salt应该/需要是唯一的并且可以存储在数据库中,实际上它可以是散列本身的一部分。请参阅http://www.openwall.com/phpass/以获得良好的实施。
#2
2
Your understanding seems correct to me.
你的理解对我来说似乎是对的。
Password: Only the hash of a password should be stored, together with a user specific salt. The salt can be stored plaintext, the reason for the salt is, that an attacker cannot use one single rainbowtable for all users (building a rainbowtable is expensive). It's recommended to use the hash_hmac()
function.
密码:只应存储密码的哈希值以及用户特定的盐。盐可以是明文存储的,盐的原因是,攻击者不能为所有用户使用单一的彩虹表(构建彩虹表是昂贵的)。建议使用hash_hmac()函数。
EMail: I think it's a good idea to encrypt these adresses, but however you do it, if the attacker has control over the server, he will be able to recover these addresses. I would put a secret key in a separate directory, which is outside the web root (cannot be accessed directly from the web). Don't write it in a file that can be delivered without interpreting, the extension *.php is better than *.inc . If you have no access to such a directory, at least make one and protect it with .htaccess Deny from all
.
电子邮件:我认为加密这些地址是个好主意,但无论如何,如果攻击者控制了服务器,他将能够恢复这些地址。我会将一个密钥放在一个单独的目录中,该目录位于Web根目录之外(无法直接从Web访问)。不要在没有解释的情况下将其写入文件中,扩展名* .php优于* .inc。如果您无法访问此类目录,请至少创建一个并使用.htaccess Deny保护它。
If you need to find an email address in the DB you can additionally store a hash, this allows to search case insensitive (first turn to lowercase, then generate the hash).
如果你需要在数据库中找到一个电子邮件地址,你可以另外存储一个哈希,这允许搜索不区分大小写(首先转到小写,然后生成哈希)。
#3
0
The salt should be per-user, and can be indeed in the database; thus the point of a salt is that someone with a copy of your db can't work on cracking all the passwords at once, but each separately.
盐应该是每个用户,并且可以确实在数据库中;因此,盐的一点是,拥有数据库副本的人不能同时破解所有密码,但每个密码都是分开的。
As for the encryption key, that's a much harder issue - definitely don't store it in the database; if your platform offers any kind of protected storage, you may want to use that. See e.g. this for useful answers: What's the best method to use / store encryption keys in MySQL
至于加密密钥,这是一个更难的问题 - 绝对不会将其存储在数据库中;如果您的平台提供任何类型的受保护存储,您可能希望使用它。参见例如这是有用的答案:在MySQL中使用/存储加密密钥的最佳方法是什么