用于 Web 服务身份验证的 HMAC/PBKDF2 与简单散列算法?

信息安全 密码学 验证 网络服务 hmac
2021-08-20 06:03:43

我们正在创建 Web 服务,并一直在研究保护它的方法。实际上,该服务可能会获得非常少的流量,并且数据可能对任何人都没有什么用处。但是,我们需要对用户进行身份验证,并尽我们所能确保传递给服务的数据的完整性。

因此,我们研究了使用 HMAC,其密钥是从使用 PBKDF2 在客户端输入的用户密码派生的 256 位密钥。虽然到目前为止我对我们的实现感到满意,但我不确定即使 1000 次迭代的 PBKDF2 将如何在 iPhone/Android 客户端上执行。此外,正如我之前提到的,不太可能有人想要损害我们的服务,并且在阅读诸如此类提到“威胁模型和风险概况”之类的问题,我想知道我是否做得过火了。

问题是,已经委托第三方开发客户端应用程序,他们的初始设计文档提供了他们安全理念的一些基本思考,而且更多的是围绕以下内容;

MD5(共享密钥 + 用户密码 + 请求 uri + 时间戳 + json 序列化后的数据(如果有))

无论我们选择 MD5、SHA1 还是 SHA256,选择 HMAC/PBKDF2 是否比他们建议的方法有任何优势(假设生成哈希的输入大致相同)?基本上,对于可能会看到非常少量流量的服务,我是否过于复杂化了?在这个阶段,很可能所有流量也将通过 SSL。

4个回答

推荐的方法。我建议您使用 SSL并使用其密码对客户端进行身份验证。然后你就不需要任何花哨的 MAC、哈希、PBKDF2 等。

细节。 您询问了如何对用户进行身份验证。这是一个简单的方法。在站点范围内使用 SSL。当用户登录时(通过 Web 客户端输入密码),然后设置一个会话 cookie,该 cookie 在会话的其余部分记住用户。(确保始终使用 SSL,并在所有 cookie 上设置安全标志。)如果需要,您可以在用户验证后设置持久安全 cookie,这样他们就无需在此浏览器上再次输入密码。

如果您想从专用的移动客户端访问 Web 服务,同样的方法也可以正常工作。Web 服务器可以发送一个安全的持久性 cookie,应用程序可以将其永久存储在其应用程序本地存储中,并且可以使用该 cookie 来验证客户端。

备择方案。如果由于某种原因无法实现上述操作,则有一些备用替代方案,但我认为它们不太可取,并且更有可能出现安全问题。这是一种合理的后备方法:

  • 在您的移动客户端应用程序首次启动时,它会提示用户输入密码,通过 SSL 连接到服务器,并通过 SSL 发送密码。服务器以随机的 128 位身份验证密钥(由服务器使用加密强度 PRNG 选择)进行响应。

  • 客户端应用程序将此身份验证密钥永久存储在应用程序本地存储中。服务器永久记住此身份验证密钥与用户帐户之间的关联。

  • 来自客户端应用程序的所有未来请求都使用此身份验证密钥进行身份验证,如下所示:您将一个参数附加到 URL 的末尾,该参数包含 URL 其余部分的 HMAC(在分配给此客户端的身份验证密钥下),任何 POST数据,以及服务器将考虑的任何其他状态。

只要所有请求都是幂等的(例如,对于非幂等操作,您确保在 URL 参数或 POST 数据中的某处包含唯一标识符,并且服务器会进行重放检测),这应该可以正常工作以保护从客户端到服务器的请求的真实性和完整性。

但是,它有一些安全限制。它不保护机密性。它也不保护其他请求标头、响应数据和各种其他内容。因此,它不如仅使用 SSL 安全。例如,使用这种方法构建的站点可能无法抵御中间人攻击,因为有大量其他内容不受 HMAC 保护,因此无法安全使用一个开放的 Wifi 网络。出于这个原因,我建议您只是全面使用 SSL 并简化您的生活,而不是尝试发明自己的加密请求身份验证格式。

防止密码猜测的安全性。您会注意到,我提出的任何方法都没有涉及根据用户密码生成加密密钥。用户通常选择密码。您应该期望在移动平台上尤其如此,输入密码很痛苦。出于这个原因,从密码派生的加密密钥通常会提供较弱的安全性,并且通常可以通过字典搜索来破解。例如,如果加密密钥是从密码中派生的,则捕获任何一个请求的窃听者将能够发起暴力密码搜索攻击以恢复密码,从而恢复加密密钥。

虽然 PBKDF2 试图尽可能地缓解这种情况,但根本的漏洞仍然存在。出于这个原因,我认为最好尽可能避免使用从密码派生的加密密钥面对弱用户密码,我的上述解决方案更加稳健,因为它们不涉及通过任何连接以明文形式发送密码或任何作为密码函数派生的内容。

第三方设计。您提到您聘请了第三方来进行设计,他们建议使用 MD5(秘密 + 数据 + 更多数据)之类的东西。这是个坏主意不要这样做。它有多个加密缺陷。首先,MD5(secret + data) 是一个糟糕的消息认证码;它容易受到消息扩展攻击。其次,通过连接来组合不同类型的数据是一个坏主意,也是十大最常见的加密错误之一因此,亚马逊和 Flickr 都存在引人注目的安全漏洞。相反,我建议您使用正确的消息身份验证代码(如 HMAC),并使用正确的方法来连接要验证的数据字段,例如,通过包括长度字段

我也在从事网络服务无会话身份验证。还要检查amazon s3 auth

他们还使用 HMAC_SHA256 来“签署”带有时间戳的请求。

但它并不比 http(非 ssl)强,因为有人可能会嗅到你的请求。

亚马逊通过仅允许在亚马逊服务器时间的 +/- 15 分钟内的时间戳来解决此问题。

当然,他们也建议通过 http* s * 进行连接。

即使你在这里使用这个系统,你仍然需要使用 SSL。

效率对于 Web 服务非常重要,而您提出的身份验证方法远非高效或安全。使用 PBKDF2 将是一个非常糟糕的选择,因为它会为每个请求增加大量 CPU 使用率,并且会增加大量延迟,因为必须在完成请求之前进行此检查。

HMAC 的使用引入了攻击的可能性。md5 和 sha1 都是非常损坏的原语,永远不应该在安全环境中使用。(虽然应该注意散列冲突不会影响 HMAC,但是散列函数还有其他问题)。甚至可以在 GPU 或 FPGA 上破解 sha256+PBKDF2 以检索您的秘密,这使得这是一个非常糟糕的选择。

只有在没有其他选择时才应该使用密码学,绝不应该使用它来将缺陷引入系统,而这正是您使用此设计所做的。这种有缺陷的会话管理方法的另一个例子是.net oracle padding 攻击加密会话信息并不能保证用户不能修改它。

如果您想要一个安全的系统,请向客户端发出一个密码随机数为此,我喜欢使用像/dev/random. 然后使用它从像memcachd这样的快速数据存储中检索信息。验证不需要昂贵的哈希函数。与使用 HMAC 相比,这减少了每个请求的带宽开销,并且它不能被篡改,因为没有要破解的加密原语

正如其他人所说,如果您使用 SSL,则无需在客户端实现 PBKDF2,但您可能希望研究 CHAP 之类的东西,作为 SSL 的轻量级补充,并解决 SSL 的一些潜在漏洞.

顺便说一句,我认为这是一个很好的方法,首先想出如何过度使用它,然后再回到更合理的解决方案。