传输休息api的用户密码

dar*_*eir 6 php security rest web

我正在设计REST API,在验证用户的安全性方面存在一些问题.对于身份验证,我不希望密码以纯文本形式通过网络发送.

为了绕过这个问题,我可以发送密码的SHA-256哈希值(用户名为salt),因此密码永远不会以纯文本形式发送.在我的数据库中,我将存储以下哈希:SHA256(密码+盐),如果两个哈希匹配,我将进行比较.

这个选项的问题是我将使用快速哈希算法计算哈希,并且盐不是随机的.

在安全性方面,最佳做法是使用慢速签名算法,使用随机盐(如bcrypt).

慢速算法不是问题,我可以在客户端使用bcrypt,但对于salt我不知道该怎么做:

  • Bcrypt需要一个定义大小的盐,所以我不能把用户名
  • 如果我使用随机盐,客户端在计算密码的哈希值之前如何知道这个盐的值?

所以我可以看到3个选项,但没有一个是令人满意的:

  • 我以明文形式发送密码(我使用的是SSL)并且我将bcrypt存储在db =>中仍然容易受到中间人的影响
  • 我使用SHA256并发送哈希,其中salt是用户名(仍使用SSL)=> db中的哈希不太安全
  • 我使用bcrypt并且我有一个两步过程:我要求给定用户的salt然后发送此用户的哈希值(仍然使用ssl)=>通过尝试使用其他用户名登录我可以获得他的盐,而不是真棒

有人有更好的解决方案或一些建议吗?

mfr*_*kli 5

我认为您可能会在这里混淆/混淆一些问题:

  • 如果您将哈希值(密码+用户名)存储在服务器上,并且身份验证涉及发送哈希值(密码+用户名),那么您实际上并没有比仅将密码存储在服务器上更好。仅长期存储哈希值的目标是,如果发生数据泄露(即攻击者获得对数据库的访问权限),他们仍然无法生成正确的值进行身份验证。但如果你进行简单的比较,这仍然是一个问题。
  • 哈希+加盐的正确用法是:(1)服务器存储(Salt,哈希(密码+盐)的元组;(2)用户发送(声明的密码);(3)服务器计算哈希(声明的密码+盐);( 4) 如果 hash(claimed Password + Salt) == hash(Password + Salt), 那么它们是真实的。这样,即使攻击者获得了数据库的访问权限,他们也无法生成一个声称的密码,这样hash(要求的密码+盐)有效。
  • 通过 SSL 发送明文密码并不是“明文”的。根据 @NullUserException 的评论,除非攻击者破坏了 SSL。只有服务器才能获取密码的值(假设服务器的公钥有效,这是一个完全不同的故事)。

希望这可以帮助!


qua*_*oup 2

客户端的散列方法有几个优点。其中之一是服务器永远无法获得真实密码,因此如果服务器以任何方式受到损害,它仍然无法获得真实密码。另一个是,如果您打算使用慢速散列,它可以减轻服务器端的负载。

但是,哈希密码旨在保护您,以防数据库遭到破坏和哈希值被盗。这意味着如果有人掌握了哈希密码,他们仍然可以通过发送哈希来冒充用户。这意味着,即使你在客户端进行哈希处理,你仍然需要在服务器上重新进行哈希处理。

另一个潜在的缺点是,这可能会疏远部分未启用 JavaScript 的用户群。


为了解决你的观点:

Bcrypt 需要一个定义大小的盐,所以我不能输入用户名

不要将用户名用作盐。盐应该是唯一的,并且用户名(及其派生)当然不是唯一的。我所说的“唯一”并不是指仅对服务器而言是唯一的,而是在任何地方都是唯一的。请改用加密随机数。

如果我使用随机盐,客户端在计算密码哈希之前如何知道该盐的值?

只需让服务器事先发送盐(随机数)即可。您也可以在客户端上执行此操作,但据我所知,Javascript 没有 CSPRNG,并且您仍然需要将随机数发送回服务器。

我以纯文本形式发送密码(我使用的是 SSL),并将 bcrypt 存储在数据库中 => 仍然容易受到中间人的攻击

SSL 旨在防止中间人攻击。除非它以某种方式损坏,否则这不会成为问题。

我使用 SHA256 并发送哈希值,其中盐是用户名(仍然使用 SSL)=> 数据库中的哈希值不太安全

不要使用用户名作为盐。正如我之前所说,无论您是否在客户端进行哈希处理,都必须在服务器端进行哈希处理。

我使用 bcrypt,我有一个两步过程:我请求给定用户的盐,然后发送该用户的哈希值(仍然使用 ssl)=> 通过尝试使用其他用户名登录我可以获得他的盐,不太好

确实不太棒。