在用户 ID 和密码中添加随机字符是不是一个坏主意?

信息安全 密码
2021-08-15 03:40:50

我听到人们一遍又一遍地说你不应该实现自己的安全算法,我想问你我是否违反了这条规则。

我正在创建一个带有扭曲的传统客户端-服务器应用程序:我想加密客户端上的所有数据,这样即使是完全控制我的服务器的攻击者也无法访问用户的数据。也就是说,我希望对我的客户端-服务器应用程序进行端到端加密。

客户端使用从用户密码派生的加密密钥加密用户的数据,因此服务器无法找出密码很重要,因为这将允许服务器解密用户的数据。因此,客户端使用安全远程密码协议来避免将密码发送到服务器。到现在为止还挺好。

现在这是我的设计有点不正统的地方。问题是用户通常不擅长创建密码——通常从前 10,000 个密码列表中选择一个密码——这将使有权访问服务器的攻击者很容易解密用户的数据。因此,我计划生成一组随机字符并将它们附加到用户 ID 字段,因此用户需要使用以下凭据登录:

User ID: John-CPE4E38J
Password: snoopy

但在处理这些凭据之前,登录代码会将随机字符移动到密码中,因此底层 SRP 身份验证库会看到:

User ID: John
Password: snoopy-CPE4E38J

此外,客户端提供记住用户 ID(即 John-CPE4E38J),因此大多数时候用户只需要记住他们的密码。

您如何看待这种方法?我是否违反了不实施自己的安全算法规则?或者这是加强我的应用程序安全性的好方法?

3个回答

是的:你在这里重写安全性。已经有几个已知可以工作的密码派生函数,最著名的是PBKDF2使用它而不是您的自定义方案。

本质上,您要做的是对密码进行加盐(使用短加盐)并将加盐值存储在用户名中。这并没有太大的改进。

您可能需要重新考虑其他一些事情:对于您的系统,加密密钥直接来自用户的密码。这意味着攻击者不仅可以通过尝试使用已知密码列表来尝试解密用户数据(即使使用基于密码的密钥派生函数会使其更难),而且您还可以有效地防止用户更改其密码(否则,您需要重新加密所有用户的数据)。

在不了解您的要求和环境的更多信息的情况下,很难提出最好的方法,但根据您的描述,我相信这可以大大改善。因此,我建议您聘请专家来帮助您在这种情况下找到合适的解决方案。

你的想法有点像黑客。但是,如果您受到现有软件的限制,它要求凭据仅包含两个字段,那么它可能是一个合适的 hack。

如果您正在编写客户端代码并且不受任意约束,则最好使用三个单独的字段,以便清楚地区分三个字符串中每个字符串的用途。

进行身份验证取决于存储在客户端计算机上的秘密和用户记住的秘密是一种合理的方法。这是一种双因素身份验证,因为用户既需要存储秘密的机器,也需要知道密码。

人们不得不担心保存存储在机器上的秘密的备份。这很重要,因为如果您丢失了它,将无法再解密数据,因此实际上他们的所有数据都会丢失。

您还应该使用密钥派生函数,该函数需要客户端上的一些 CPU 时间才能从秘密数据中派生出实际密钥。如果这需要 100 毫秒的 CPU 时间,用户几乎不会注意到,但每次尝试输入密码都需要 100 毫秒的 CPU 时间,这将大大减慢攻击者的速度。CPU 时间花在客户端而不是服务器上很重要,因为如果它在服务器上,它就会成为 DoS 向量。

使用从用户密码派生的密钥直接加密所有数据意味着更改密码将需要重新加密所有数据。另一方面,为加密数据保留一个固定密钥并使用从用户密码派生的密钥来加密该密钥更有效,但存在一个微妙的安全漏洞。

从服务器获取数据副本的攻击者可能会暴力破解某些用户的密码。如果攻击者稍后从服务器获取数据的另一个副本,即使用户在此期间选择了更强的密码,用户的数据仍然可以被解密。这意味着仅在用户切换到更强密码后才加密的数据仍然容易受到针对旧密码的攻击。

这个问题可以通过将数据存储在树结构中来解决,其中每个节点都使用存储在父节点中的密钥进行加密,而根使用从秘密数据派生的密钥进行加密。

另请注意,每当密码更改时,您存储在客户端上的秘密数据都需要更改。否则,您将无法获得预期的安全优势。

假设用户最初有一个弱密码,并且由于该弱密码,攻击者能够暴力破解存储在客户端上的秘密。如果用户切换到更强的密码,但存储的秘密保持不变,攻击者只需暴力破解新密码,而不是密码和存储的秘密的组合。

您的方法与密码学中的概念非常相似。在谈论什么是盐之前,我假设您至少存储了用户密码的哈希值,而不是纯文本的密码。否则,您的解决方案完全没用。

盐只是在散列密码时使用的随机数据,例如,用于存储目的。附加到用户名的随机字符串实际上是盐。因此,如果您只是简单地存储用户密码的未加盐哈希,那么在某种程度上,您在某种程度上加强了应用程序的安全性,因为原则上至少密码哈希列表不会受到字典攻击。但仅在这种情况下。无论如何,有保护密码哈希列表的标准方法,这些方法不涉及在身份验证期间公开盐。

但是,如果您的意图是让密码猜测变得困难,那么它不会提供任何额外的安全性,因为随机字符串是在身份验证期间提供给攻击者的。