密码、盐和授权
如果我有一个随机的、16 个字符长的字母数字盐(不同大小写),是为每个用户生成和存储的,我是否还需要一个站点范围的盐?
换句话说,这样好吗?
sha1($user_salt . $password)
我应该这样做吗?
sha1($user_salt . $password . $site_salt)
另外,
目前我有一个加密的 cookie,它可以在数据库中查找会话。在这个会话中,有一个user_id和一个user_token。然后,我使用 user_id 查询数据库——如果 DB 中 user_id+hash 的 sha1 === user_token,则允许用户通过。
我在每个页面加载时对 user_id 进行第二次查询,这样如果我删除、禁止或更改用户的密码,该操作会立即生效。
这是我通过浏览网站和问题得出的结论。你怎么认为?我错过了什么吗?
我需要添加角色检查,但这可能会添加另一个查询(第三个查询仅用于身份验证)。有什么建议吗?
If I have a random, 16 character long, alphanumeric salt (varying case) that is generated and stored per user, do I need a site wide salt as well?
In other words, is this good?
sha1($user_salt . $password)
should I do this instead?
sha1($user_salt . $password . $site_salt)
Also,
At the moment, I have an encrypted cookie, that looks up a session in a DB. In this session, there is an user_id and an user_token. I then query the DB using the user_id -- if the sha1 of the user_id+hash in DB === user_token, then the user is allowed through.
I do the second query for the user_id on every page load so that if I delete, ban or change the password of an user, the action has immediate effect.
This is what I've come up looking through websites and questions here. What do you think? Did I miss something?
I need to add role checking but that would probably add yet another query (3rd one just for auth). Any tips?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
不,您不需要全站盐。盐用于使彩虹表变得无用。如果您确实愿意,可以使用站点范围的盐,但我认为没有必要。
我认为,如果您的数据库遭到破坏,并且有人意识到您的密码已用盐进行了哈希处理,他们会转移到下一个安全性较低的网站(当然,除非您正在运行一个值得黑客攻击的网站 - 很可能您不是:P)
No, you do not need a sitewide salt. The salt is used to make rainbow tables useless. A site wide salt could be used if you really wanted to, but I don't think it is necessary.
I think if your database was compromised and someone realised your passwords were hashed with a salt, they'd move onto the next site that had less security in place (unless of course you are running a site worth hacking - chances are you aren't :P )
使用“全站点”盐可能会有用。这意味着不仅您的数据库必须受到损害,而且您的源代码也必须受到损害才能真正理解您的密码方案。
我称之为“盐”和“胡椒”方法。每个用户存储的盐,胡椒是整个站点的价值。
盐
每个人独特的盐的目的是使彩虹表失效。盐通常存储在数据库中,并附加或前置到密码中。意识到这一点的人仍然可以对每个用户运行基于字典的攻击,但盐的好处是他们不能对这种常见的字典术语使用彩虹表。
胡椒
我称之为“pepper”的目的是向每个密码添加一个潜在未知的字符串,这意味着考虑到盐的暴力字典攻击将因为缺少胡椒而完全失败。这还意味着对每个字符进行强力检查将需要“发现”更长的密码,这可能需要更长的时间。一旦胡椒被发现,这些好处就消失了。
Utilizing a "site-wide" salt might be useful. This means that not only would your database have to be compromised, but your source code would have to be as well in order to really understand your password scheme.
I call this a "salt" and "pepper" approach. The salt stored per user, the pepper is the site-wide value.
Salt
The purpose of a unique per-person salt is to invalidate rainbow tables. The salt is typically stored in the database and either appended or prepended to the password. Someone aware of this can still run dictionary based attacks per user, but the good thing about a salt is that they cannot use a rainbow table for such common dictionary terms.
Pepper
The purpose of "pepper" as I call it is to add a potentially unknown string to every password which means a brute force dictionary attack taking salt into consideration would just plain miss because of lack of pepper. It also means that a brute force per character check would need to "discover" a longer password which could take longer. These benefits disappear as soon as the pepper is discovered.
这很常见,但并不好。
典型的最终用户密码长度约为 8 个字符,并且大多保留 7 位 ASCII 字符集。因此,典型的密码大约是 64 位或更少的随机数据。现代并行暴力攻击可以通过简单地尝试所有可能的密码来解决这个问题。使用 SHA256 或 SHA512 不会显着改变结果,因为最终用户密码是限制因素。
从我在 Stack Overflow 上的阅读来看,关于密码存储似乎有两种流派:
您没有提到的安全会话处理的一个要点是 SSL 无处不在,以防止 Sidejack。用户 ID 通常不利于安全,因为它们通常是可猜测的(自动递增主键),或者错误地出现在 URL 等中。您可以使用同行评审的代码库,而不是滚动自己的会话处理系统吗?
This is very common, but it isn't good.
A typical end user password is ~8 characters long, and mostly keeps to the 7-bit ASCII character set. So a typical password is about 64 bit of random data or less. Modern parallel brute-force attacks can defeat this, by simply trying out all possible passwords. Using a SHA256 or SHA512 instead does not materially change the outcome because the end users password is the limiting factor.
From my reading here at Stack Overflow, there seems to be 2 schools of thought regarding password storage:
One main point of secure session handling that you're not mentioning is SSL everywhere to guard against Sidejack. And User IDs are generally not good for security, because they are often guessable (auto-incrementing primary key) or they end up in URLs etc by mistake. Instead of rolling your own session handling system, isn't there a peer reviewed codebase you could use?
仅在此处出现其他人没有发现的错误时才发表评论:
听起来很像您在 cookie 中存储密码或密码哈希,而不是在 cookie 中存储会话标识符。我建议反对。最大的原因是,像这样使用密码的派生词很有可能将派生词变成密码的等价物。
换句话说,攻击者需要的只是密码的哈希值,而不是密码本身,才能有效地进行身份验证。这样做的问题是,除非密码更改(不受您控制),否则密码的散列不会更改,而会话 ID 会在您需要时更改。
我的建议(如果您希望会话对密码更改敏感)是在密码更改时更改会话 ID。
Commenting only in case there is something wrong here that no-one else caught:
It sounds a lot like you are storing the password or a password hash in the cookie, rather than storing a session identifier in the cookie. I would recommend against that. The biggest reason is that using a derivative of the password like this stands a good chance of turning the derivative into a password equivalent.
In other words, all an attacker needs is the hash of the password, and not the password itself in order to effectively authenticate. The problem with this is that the hash of the password doesn't change except when the password changes (not under your control), whereas a session ID changes whenever you darn well please.
My recommendation (if you want a session to be sensitive to password changes) is to change the session ID whenever the password changes.
听起来您正在尝试重新创建 DIGEST-MD5 或 SCRAM。这两种方法都允许您存储站点特有的非密码字符串,并与另一方进行质询/响应,以验证他们是否拥有密码字符串,而无需在线发送密码字符串。
It sounds like you're trying to recreate DIGEST-MD5 or SCRAM. Both of these allow you to store a non-password string that is unique to your site and challenge/response with another party to verify that they have the password string, without sending the password string on the wire.