密码、盐和授权

发布于 2024-10-01 20:47:10 字数 538 浏览 5 评论 0原文

如果我有一个随机的、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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

落在眉间の轻吻 2024-10-08 20:47:10

不,您不需要全站盐。盐用于使彩虹表变得无用。如果您确实愿意,可以使用站点范围的盐,但我认为没有必要。

我认为,如果您的数据库遭到破坏,并且有人意识到您的密码已用盐进行了哈希处理,他们会转移到下一个安全性较低的网站(当然,除非您正在运行一个值得黑客攻击的网站 - 很可能您不是: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 )

北城半夏 2024-10-08 20:47:10

使用“全站点”盐可能会有用。这意味着不仅您的数据库必须受到损害,而且您的源代码也必须受到损害才能真正理解您的密码方案。

我称之为“盐”和“胡椒”方法。每个用户存储的盐,胡椒是整个站点的价值。


每个人独特的盐的目的是使彩虹表失效。盐通常存储在数据库中,并附加或前置到密码中。意识到这一点的人仍然可以对每个用户运行基于字典的攻击,但盐的好处是他们不能对这种常见的字典术语使用彩虹表。

胡椒
我称之为“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.

注定孤独终老 2024-10-08 20:47:10
sha1($user_salt . $password)

这很常见,但并不好。

典型的最终用户密码长度约为 8 个字符,并且大多保留 7 位 ASCII 字符集。因此,典型的密码大约是 64 位或更少的随机数据。现代并行暴力攻击可以通过简单地尝试所有可能的密码来解决这个问题。使用 SHA256 或 SHA512 不会显着改变结果,因为最终用户密码是限制因素。

从我在 Stack Overflow 上的阅读来看,关于密码存储似乎有两种流派:

  1. 您应该使用 计算成本较高的方法,如 BCrypt 或 scrypt。这样暴力攻击就变得不可行。这是可行的,但代价是用户登录时需要服务器提供更多的 CPU 能力。请参阅此优秀文章概述了其基本原理
  2. 第二种想法是,虽然 BCrypt 和 scrypt 确实有效,但它们对于多用户应用程序来说是不受欢迎的,因为它们占用了太多的 CPU 时间 - 让最终用户等待,或者可能通过发送大量数据而遭受拒绝服务攻击身份验证请求。请参阅此处的冗长讨论(请务必阅读评论)。

目前,我有一个加密的 cookie,它可以在数据库中查找会话。在这个会话中,有一个user_id和一个user_token。然后,我使用 user_id 查询数据库——如果 DB 中 user_id+hash 的 sha1 === user_token,则允许用户通过。

您没有提到的安全会话处理的一个要点是 SSL 无处不在,以防止 Sidejack。用户 ID 通常不利于安全,因为它们通常是可猜测的(自动递增主键),或者错误地出现在 URL 等中。您可以使用同行评审的代码库,而不是滚动自己的会话处理系统吗?

sha1($user_salt . $password)

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:

  1. You should use a computationally expensive approach like BCrypt or scrypt. That way brute force attacks become infeasible. This works, at the expense of requiring much more CPU power from your server when a user logs in. See this excellent article for an overview of the rationale.
  2. The second school of thought is that while BCrypt and scrypt certainly work, they are undesirable for multiuser apps because they take too much CPU time -- making the end user wait, or potentially opening up for a denial-of-service attack by sending lots of authentication requests. See the lengthy discussion here (be sure to read the comments as well).

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.

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?

度的依靠╰つ 2024-10-08 20:47:10

目前,我有一个加密的
cookie,它在 a 中查找会话
数据库。在本次会议上,有一个
user_id 和 user_token。我然后
使用 user_id 查询数据库 -- if
DB中user_id+hash的sha1 ===
user_token,则允许该用户
通过。

我对 user_id 进行第二次查询
在每个页面加载时,如果我
删除、禁止或更改密码
用户,该操作立即生效
效果。

仅在此处出现其他人没有发现的错误时才发表评论:

  1. 您提到 cookie 已加密
  2. 您的意思是 user_id+hash 的 sha1
  3. 您提到第二个查询(我不清楚这两个查询是什么),即对密码更改敏感。

听起来很像您在 cookie 中存储密码或密码哈希,而不是在 cookie 中存储会话标识符。我建议反对。最大的原因是,像这样使用密码的派生词很有可能将派生词变成密码的等价物。

换句话说,攻击者需要的只是密码的哈希值,而不是密码本身,才能有效地进行身份验证。这样做的问题是,除非密码更改(不受您控制),否则密码的散列不会更改,而会话 ID 会在您需要时更改。

我的建议(如果您希望会话对密码更改敏感)是在密码更改时更改会话 ID。

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.

Commenting only in case there is something wrong here that no-one else caught:

  1. You mention that the cookie is encrypted
  2. You meantion sha1 of user_id+hash
  3. You mention a second query (it isn't clear to me what either query is) that is sensitive to password changes.

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.

杀手六號 2024-10-08 20:47:10

听起来您正在尝试重新创建 DIGEST-MD5SCRAM。这两种方法都允许您存储站点特有的非密码字符串,并与另一方进行质询/响应,以验证他们是否拥有密码字符串,而无需在线发送密码字符串。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文