【发布时间】:2018-01-04 18:36:44
【问题描述】:
我想通过遵循良好实践来实现一个身份验证系统,我希望它尽可能简单和安全(我不会实现一些神奇的哈希函数或感觉像英雄的东西..)只是想使用已知的哈希但不确定使用它的正确方法。 我读了一些关于 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 在其客户端散列中使用哪种盐的任何解释,他们使用的是需要盐参数的 PBKDF2 算法。
fe_rounds -> 输入用户名时服务器给出的轮数 - 它对每个人都是固定的,并且可以由服务器配置,在我读到的关于 Lastpass 的文章中,他们也没有解释他们从哪里接收客户端的轮数......
所以现在我们将 auth_key 原样发送到服务器...
在我的服务器端
现在我们正在创建一个新的散列来比较数据库中的散列。 为什么另一个哈希?如果我理解正确,我们会为服务器端数据绑定哈希,例如密码(只有用户知道)和服务器数据的组合。
db_auth=PBKDF2(SHA256, auth_key, user_be_salt, 100,000+user_configurable_rounds)
user_be_salt -> 一个随机数,保存在数据库中,只有服务器和获取数据库的人知道,每次成功登录都会改变。
user_configurable_rounds -> 迭代次数,每个用户都可以选择迭代次数(就像在 Lastpass 中一样),所以攻击者还需要猜测迭代次数?
我很乐意听到您对这个身份验证系统的看法,如果它错了,请向我解释原因并告诉我 Lastpass 做了什么,因为我不了解他们的整个身份验证流程。
【问题讨论】:
-
这听起来像是一个代码审查问题,不幸的是,这不是 Stack Overflow 的目的。
-
如果攻击者获得了 auth_key,我们不就如同他们拥有我的密码一样吗?由于那部分,我没有看到任何额外的安全性。
-
Lastpass 使用客户自己的密码加密敏感数据(在他们的情况下为密码保险库)我还想使用他们自己的密码为用户加密数据。因此,如果有人获得密码,我可能会遇到大问题。攻击者也不会知道用户的实际密码,因此他无法使用该密码登录其他站点,我知道他可以使用该 auth_key 直接向服务器发布请求。也许将 csrf_token 添加到请求中可能会有所帮助?所以唯一接受的发送请求的方式是从网站提交表单,这需要实际密码..
标签: javascript security authentication pbkdf2 lastpass