鉴于您确实必须在客户端执行密码散列,您如何实现服务器端加盐?
我能想到的第一个解决方案是在执行哈希之前从服务器的用户表中询问用户的盐。但这意味着您确认用户“存在”,因为您给了他用户的有效盐。
我还认为,不是将盐存储在用户的表中,而是可以使盐成为用户可用的东西,例如,他的用户名的变体。但是可能会出现一致性问题,因为服务器和客户端需要记住盐是如何从提供的用户数据中获取的。
做这个的最好方式是什么?
鉴于您确实必须在客户端执行密码散列,您如何实现服务器端加盐?
我能想到的第一个解决方案是在执行哈希之前从服务器的用户表中询问用户的盐。但这意味着您确认用户“存在”,因为您给了他用户的有效盐。
我还认为,不是将盐存储在用户的表中,而是可以使盐成为用户可用的东西,例如,他的用户名的变体。但是可能会出现一致性问题,因为服务器和客户端需要记住盐是如何从提供的用户数据中获取的。
做这个的最好方式是什么?
如果您没有用于登录的 HTTPS,散列客户端很有用,但它可能有一些缺点,例如泄露您的散列和/或加盐方法。话虽如此,如果他们可以访问您的密码哈希数据库,他们可能已经可以访问该信息。
为了只做服务器端的盐,您需要使用盐和密码哈希重新哈希密码。在这种情况下,您将只存储用户名、盐(如果不使用用户名和密码哈希盐)和第二个哈希。
如果从您的示例中您希望在客户端和服务器上执行加盐,我建议使用用户名和初始密码哈希的组合来加盐。客户端不会不知道盐,因为任何人都可以检查您的加盐方法,甚至将其应用于密码破解者,但它会避免他们使用彩虹表来破解相同的密码用户。
不要将用户名本身用作盐。如果它是一个常见的用户名(例如 admin),那么可能已经有一个带有这种盐的表。
使用 nyde1319 的答案的问题(抱歉无权评论答案)是您需要在数据库中拥有未加密版本的密码才能执行密码+盐哈希。违背哈希的目的。如果它是使用密码的散列版本完成的,则您必须存储第一个散列,他们可以破解该散列,从而破坏了盐的目的。
我不是该主题的专家,但是如何使用一次性盐之类的东西以及您提到的解决方案。
这意味着,您为客户端提供了一个加盐函数,该函数在短时间内根据随机种子生成盐。种子本身是动态的,并且会在一段时间后发生变化,并且在服务器和客户端之间必须相同。毕竟,盐不必保密。
在客户端使用用户名(或任何可用的用户数据)生成盐,假设它是唯一的。然后在连接的密码和盐上生成哈希并将其发送到服务器上。
在服务器端,您使用客户端中的相同加盐函数以用户名作为输入来计算盐值。然后您生成相同的哈希值并确定这两个值是否匹配。您只需确保时间窗口足够宽以允许成功的身份验证。