验证和签名HTTP请求。

13

我正在寻求关于如何对HTTP请求进行身份验证和签名(完整性检查)的最佳实践建议。语言和技术方面比较开放,但基本参数和要求如下:

  • 需要进行身份验证和完整性检查。
  • 请求包含敏感数据并将通过HTTPS传递,但不能假定请求无法被攻击者嗅探到,无论是在HTTPS加密之前(在客户端端由某些非法安装软件)还是在服务器端,例如通过放置在HTTPS端点和实际服务器之间的嗅探器。 HTTPS加密/解密处理已经被外部负载均衡器接管,因此攻击者可以在负载均衡器和服务器之间插入嗅探器。
  • 需要确保交易不能被伪造。
  • 需要确保交易不能被重复播放。
  • 请求可以是GET或POST方法,因此任何额外的数据都需要保持在GET请求的最大大小限制内。

我们考虑过以下内容:

  • 每个请求的用户名/密码。这应该可以保证身份验证,但如果攻击者能够嗅探到用户名/密码对,则所有内容都将失败。
  • 每个请求的私钥签名。服务器将拥有公钥,只有客户端将拥有私钥。这可以保证完整性,因为只有客户端才能生成签名,但服务器可以检查签名。它通常也可以保证身份验证,因为私钥不是请求数据的一部分,无法被嗅探到。但单独使用它不能防止交易被重复播放,因为具有相同数据的2个交易将具有相同的签名。
  • 在请求数据中使用密码学客户端随机数(https://en.wikipedia.org/wiki/Cryptographic_nonce),并将其包含在要签名的数据中。我们遇到了这些问题,尤其是当它们在客户端生成时,因为如果它们不足够随机,那么攻击者可以找出它们是如何生成的,然后攻击者可以提前生成自己的一系列随机数,而客户端正在尝试重用攻击者已经使用过的随机数,这可能会导致拒绝服务攻击。考虑在服务器端生成非ces,但这是一个额外的事务,可能会影响性能。
  • 将日期/时间包含在请求数据中,但这可能会导致客户端的时钟和服务器的时钟失去同步而引起问题。
  • 如果某个管理员决定将其标记为重复项,则以下是我考虑过但不完全解决此问题范围的其他问题:


    “我对使用的语言和技术比较开放。” - 那你为什么要在Stack Overflow上问呢?这不再是一个编程问题,如果是的话,那它就太宽泛了。[security.se]更适合这种类型的问题。 - Artjom B.
    1个回答

    5
    假设客户端和服务器之间是一对一的关系,使用带有计数器的HMAC可以解决这个问题。客户端和服务器共享一个128位的秘密密钥。客户端发送的消息包含一个带有秘密密钥和计数器的HMAC。建议使用SHA-256,因为SHA-1已经过时了(虽然SHA-1 HMAC仍被认为是安全的,但这是另一个故事)。例如:
    example.com?message=foo&counter=1&hmac=35ed8c76e7b931b06f00143b70307e90f0831682e7bdce2074ebb5c509d16cfb`
    

    (此工具 用于此帖子,并使用密钥 bar。)
    HMAC 是在 message=foo&counter=1 上计算的。
    现在,一旦服务器验证了 HMAC 并检查了计数器,服务器的计数器会增加到 2。现在,服务器不会接受任何计数小于 2 的已经验证过的消息。
    可以使用JSON Web Tokens以标准格式执行上述操作。您可以使用多个客户端执行上述操作,但是您需要为每个客户端在服务器端跟踪计数器,并且客户端必须在消息中标识自己。如果您为每个客户端决定使用不同的密钥,则管理共享密钥是最棘手的部分。

    感谢您指出JWT,我一直以为有一些标准格式来完成这个过程,但是到目前为止我还没有发现它。我们的客户和服务器之间存在多对一的关系,但我们没有那么多客户,无法为每个客户维护不同的密钥(我们大约有15个客户)。在此期间,我们决定使用RSA密钥实现某些功能,而不是HMAC,但我看到JWT也支持这种方式。 - delatbabel
    关于JWT我不喜欢的一件事情就是 -- 不透明的、base64编码的负载会让调试变得不那么友好。 - jchook

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接