0

我想通过遵循良好实践来实现身份验证系统,我希望它尽可能简单和安全(我不会实现一些神奇的哈希函数或感觉像英雄的东西..)只是想使用已知的哈希但不确定正确的使用方法。我读了一些关于 Lastpass(密码管理公司)如何处理他们的身份验证的文章,我喜欢他们的想法。所以我想基于它实现我自己的身份验证。

基本上我从客户端的密码创建一个身份验证密钥(因此密码永远不会作为计划文本发送到服务器)。该身份验证密钥即时发送到服务器,而不是在服务器端进行一些散列操作,并将结果与​​数据库内的结果进行比较。

在我的客户端:

auth_key = PBKDF2(SHA256, password+username, last_login_fe_salt, fe_rounds)

解释 - 哈希密码+用户名+last_login_fe_salt文本fe_rounds

last_login_fe_salt -> 在用户在文本字段中输入用户名后发送给用户的随机盐 - 老实说,不确定这个 last_login_fe_salt 如何有效地防止字典攻击,但至少两个拥有相同密码的人会发送不同的哈希值在他们的网络上。任何黑客都可以通过从服务器询问来获取这些数据,我可以添加服务器端限制(req/s 如果它有一些不同等。让我知道你的想法)也添加验证码可能是一个好主意。当用户成功登录时,服务器会生成一个新的随机字符串并保存到数据库中。

*我没有看到 Lastpass 在他们的客户端散列中使用哪种 salt 的任何解释,他们正在使用需要 salt 参数的 PBKDF2 算法。

fe_rounds -> 输入用户名时服务器给出的轮数 - 它对每个人都是固定的,可由服务器配置,在我读到的关于 Lastpass 的文章中,他们也没有解释他们从哪里接收客户端的轮数......

所以现在我们将 auth_key 原样发送到服务器......

在我的服务器端

现在我们正在创建一个新的散列来比较数据库中的散列。为什么另一个哈希?如果我理解正确,我们将哈希绑定到服务器端数据,例如密码(只有用户知道)和服务器数据的组合。

db_auth=PBKDF2(SHA256, auth_key, user_be_salt, 100,000+user_configurable_rounds)

user_be_salt -> 保存在 db 中的随机数,只有服务器和获取数据库的人知道,每次成功登录时都会更改。

user_configurable_rounds -> 迭代次数,每个用户都可以选择迭代次数(就像在 Lastpass 中一样),所以攻击者还需要猜测迭代次数吗?

我很高兴听到您对此身份验证系统的看法,如果它错了,请向我解释原因并告诉我 Lastpass 做了什么,因为我不了解他们的整个身份验证流程。

4

1 回答 1

0

从安全的角度来看,您所做的大部分事情都是无用的。Lastpass 有不同寻常的安全要求——不要将它们视为最佳实践的来源。

如果客户端负责散列,并且该散列的所有参数都是固定的,则散列有效地成为密码。攻击者不需要知道原始密码;他们可以简单地将哈希传递给服务器。

一般来说,如果不通过网络发送密码(对于传统的密码身份验证协议)或让服务器以明文形式存储密码(对于SRP等不太常用的协议),就无法通过网络验证密码。两者中,前者更可取,因为可以使用 SSL/TLS 等协议保护传输中的密码,而 SRP 等协议需要密码的明文才能运行。

在客户端或服务器端调整 PBKDF 轮数是没有意义的。设置一个固定的轮数,使散列变慢,但不会太慢以至于会给客户端或服务器带来不适当的负载。(对于服务器端哈希来说,100,000 轮可能过多。使用这些设置验证密码大约需要半秒,因此每秒只有两个登录请求会使用服务器上一个内核的 100%!)

于 2017-07-28T18:45:37.687 回答