2009-08-10 55 views
0

我正在为一个客户开发一个Asp.NET网站,并且希望确保我使用安全的身份验证方案。安全用户身份验证 - 我是否正确地执行此操作?

在我的用户表中,我有一个验证哈希列,计算结果为sha1(salt + username + password)。该网站正在通过HTTPS提供服务。要登录,用户通过HTTPS提交他们的名字和密码。 Web服务器计算散列值,并将其与数据库存储值进行比较以进行认证。

这听起来合理安全吗?我跑过这个计划,经过我的一个朋友,他说它很容易受到恶意的系统管理员的攻击。他说我应该做以下事情:

  • 服务器在每次登录页面服务时指定一个独特的salt。
  • 在提交之前,通过JavaScript在客户端上密码哈希密码。
  • 发送此散列进行身份验证,但不是密码。
  • 做一些奇怪的垃圾,我不明白认证哈希。

我该怎么办?

+1

你的伴侣为什么说它很容易受到流氓系统管理员的攻击?通常这是非腌制或明文密码的问题。我想知道他的推理是什么...... – davewasthere 2009-08-10 16:35:55

回答

7

不要重新发明轮子,只需使用.Net Membership

+0

我以前参与过使用此项目的项目。我记得有些事情让我避免了这个解决方案。但我不记得那是什么。有些事情太僵化了。 但是,阅读您的链接表明我的信息不正确。 :) – recursive 2009-08-10 16:37:19

2

如果您在每次提供登录页面时更改salt,如何将其与使用不同盐进行散列的数据库中的内容进行比较?

你在SSL下,你可以发送凭据的自由文本,因为该行已被加密,然后将规则应用于盐/哈希你的密码比较服务器端。这样没人知道你是如何加密你的密码的。将信息存储在客户端JavaScript只是将这些信息发送出去。

除此之外,你的方法看起来是正确的。我假设你需要一个自定义的解决方案,而不是出于任何原因内置的解决方案。

+0

我猜他的盐将存储在一个单独的列。否则,重新验证会非常棘手。 – davewasthere 2009-08-10 16:37:05

3

阅读:
Enough With The Rainbow Tables: What You Need To Know About Secure Password Schemes

我们学到了什么?
...如果是2007年,彩虹桌攻击将您置于火中,我们知道您应该回到1975年,等待30年后再尝试设计密码散列方案。
...我们应该在安全领域咨询我们的朋友和邻居,以获得密码方案的帮助。
...在密码散列方案中,速度是敌人。我们了解到MD5是为了速度而设计的。所以,我们了解到MD5是敌人。
...如果我们想要安全地存储密码,我们有三个合理的选项:PHK的MD5方案,Provos-Maziere的Bcrypt方案和SRP。我们了解到正确的选择是Bcrypt。

关键点的位置:

  • 不管你做什么,不要试图从头开始构建自己的身份验证码
  • Bcrypt是散列密码的最佳选择。
+1

嗯,这是一篇很好的文章,直到我看到这个 - “你可以使用挑战 - 响应方案,双方使用数学问题向对方证明他们知道密码,但双方都不通过线路发送密码。方案很好,但除非双方都能访问明文密码 - 换句话说,服务器必须将其存储在明文中,否则它们不起作用。“他在这里绝对是错的。质询/响应系统不需要服务器以明文方式存储密码。 – 2009-08-10 18:32:45

4

首先,如果用户通过HTTPS连接,那么通过网络发送密码到服务器应该没有问题。

否则,确保你的盐很长,并使用体面的熵来随机。由于SHA-1是considered broken,所以请确保您使用SHA-2而不是SHA-1。

2

你的朋友是正确的断言盐应该是唯一的,但他在处理盐方面是错误的。

  • 哈希密码前 提交通过JavaScript客户端上的独特的盐。

,需要你要么使用相同的盐为大家还是知道用户是谁,所以你可以把他们自己的独特的盐。盐不应该离开服务器。

+0

它不应该是一个用户盐。它应该每一次都是独一无二的。 – recursive 2009-08-10 16:50:18

+0

@recursive:如果盐每次都不同,用户如何进行认证?如果用户名/密码/ salt对用户来说不完全相同,那么散列将永远不匹配存储在数据库中的内容。 – MyItchyChin 2009-08-10 18:04:23

4

这听起来合理安全吗?我 运行这个计划通过我的一个朋友, ,他说它很容易受到 邪恶的系统管理员。

直接发送密码总是有点危险。即使你使用SSL。如果这就是他所指的那么他就是对的。我不会说它很脆弱,只是不是最安全的方法。

  • 服务器在每次登录页面提供时指定一个独特的salt。
  • 提交之前,通过javascript 将密码散列在客户端上的唯一盐。
  • 发送此散列进行身份验证,但不是密码。
  • 做一些奇怪的垃圾,我不明白认证哈希。

这听起来像是他提出了一个与SSL结合的挑战 - 响应方案。这是一个很好的方法,但让我逐步解释清楚。

注册后,密码通过SSL发送到服务器。这应该是密码直接发送的唯一时间。服务器生成一个盐并存储以下哈希:

hash = sha1(password + salt) 

服务器还应该存储salt。

当客户端访问登录页面时,服务器应该在具有ID和挑战值的表中生成记录。然后服务器应该将ID,存储的盐和挑战值发送到客户端。

当客户端就可以登录,你应该有一个javascript函数产生一个挑战,以及像这样的哈希:

hash = sha1(sha1(password + server_salt) + server_challenge + client_challenge) 

客户端应当提交的哈希值,该server_saltid和client_challenge值。然后,服务器计算哈希像这样:

hash = sha1(stored_hash + server_challenge + client_challenge) 

如果哈希匹配用户进行身份验证,在任何情况下,面临的挑战记录应予删除。