推荐的 JWT 非对称算法?

信息安全 RSA 不对称 jwt ecdsa
2021-08-24 17:22:56

我正在为新的 Web 服务实施 JWT 身份验证,但不确定选择哪种非对称算法。我四处搜寻,没有找到任何共识或明确的建议。根据PyJWT 文档,有几种不同的算法可供选择。

我想使用一种安全(显然)、开销低且经得起未来考验的算法。哪种算法符合要求?

4个回答

简短的回答是使用 RS256,可以理解为 SHA 256 和 RSA 2048 位密钥。

有关所有支持的算法,请参阅RFC 7518 JSON Web 算法 (JWA)

关于签名算法

JWT 支持两种主要的签名算法:RSAECDSA.

  • RSA(如alg:RS256)是基于素数分解的经典非对称签名算法。它得到了很好的理解并得到了广泛的支持。在我看来,没有理由使用 RSA 以外的任何东西。推荐的密钥大小为 2048 位。

  • ECDSA(如alg:ES256)是一种基于椭圆曲线的替代非对称算法。作为 RSA 的替代品,它在 2010 年代开始受到关注。它不像 RSA 那样受到广泛支持,但它有一些支持(特别是对 SSH 密钥)并且它正在增长。如果其中一个在未来被破坏,那么有两种选择是很有用的。我认为使用 ECDSA 除了是前沿之外没有任何意义,因为 RSA 可以很好地完成这项工作,而 ECDSA 库并不那么普遍并且不久前就出现了问题。

查看所有 Microsoft 产品和库中值得注意的漏洞CVE-2020-0601破坏椭圆曲线加密。简而言之,实现中存在一个小错误,因此验证内容根本不会验证任何内容。您将重新使用来自互联网的随机库来验证各种语言的各种应用程序中的 JWT 令牌,我会警惕库是否可以在 Microsoft 和 consort 不能很好地实现 ECDSA 时。RSA 根本没有这种错误,因为它更简单,并且库已经经过数十年的审查。

  • HS256(如alg:HS256):预共享密钥模式。签名和验证令牌只有一个密钥。客户端和服务器都必须知道密钥。我不知道有任何用例,所以请帮自己一个忙,完全忽略 HSxxx 模式。

关于哈希算法

JWT:SHA256支持三种主要的散列SHA384算法SHA512

它们的长度越来越长,以抵抗计算能力的进步。

SHA256 足够安全,不能在合理的时间内用整个数据中心破解,没有理由偏爱更慢的算法。

请注意,SHA1JWT 从未支持 160 位,因为在 2010 年计划 JWT 时,它被认为是不安全的并且不是未来的证明。

表现

当谈到RSAvsECDSA时,没有关于相对性能的一般结论。任何一个都可能比另一个更快。

它完全取决于使用的库和特定的 CPU。

拥有标准令牌的一点是,它可以更轻松地支持使用不同库的不同应用程序(Python、Java、C、C# 等)的身份验证,因此对性能做出任何一般性结论确实是错误的。如果您关心性能,您应该为自己运行一个基准测试。

作为参考,从广义上讲,验证令牌的量级是毫秒(读作:它比一微秒长得多,比一秒短得多)。

不要将密码哈希建议与 JWT 建议混淆。您会在互联网上找到的大多数加密建议(包括堆栈溢出)都面向密码散列(通常使用 PBKDFD2/bcrypt/scrypt/argon 之一),这是一个设计和配置为缓慢的用例,可能高达整个第二个是计算哈希。JWT 令牌必须在每次“调用”时进行验证,并且要足够快以供 API 使用。

密钥大小和鲁棒性

推荐尺码:

  • SHA 256 位
  • 具有 2048 位密钥的 RSA
  • 具有 P-256 曲线的 ECDSA

有关所有支持的算法,请参阅RFC 7518 JSON Web 算法 (JWA)

这些是 2020-2030 十年的推荐设置。这可以抵抗专用数据中心的攻击者试图破解密钥。

身份验证系统(使用 JWT)旨在支持对 Web 上的外部客户和公司内部员工的身份验证。需要抵抗这种攻击。

请注意,所有大公司、大学、研究中心和政府机构 (#NSA) 都有计算网格可供使用,因此购买数千台服务器来暴力破解密钥实际上是“微不足道的”。

(可能会在 2030 年重新审视建议,届时 AWS/Google 将租用 60 000 个未来 GPU 的整个数据中心)。

RFC7518列出了算法以及它们对于 JWT 库是必需的、推荐的还是可选的。这可以帮助您选择在其他库中实现的算法,以实现互操作性。

从安全角度来看,有以下选项:

  • RSASSA 与 ECDSA。ECDSA 使用椭圆曲线,有些人认为这些比 RSA 更安全。它们也更快,允许您使用较小的键。
  • SHA256、SHA384、SHA512。您可以说越多越好,但由于 SHA256 已经无法暴力破解,因此使用更多位毫无意义。
  • PKCS1-v1_5 与 PSS。PSS 有一些安全优势,但比 PKCS1 更复杂,可能更容易出错。

所有这些选项都是安全的,并且差异在很大程度上是理论上的。我可能会推荐使用 P-256 和 SHA-256(规范中的alg参数值)的 ECDSA,因为ES256

  • 根据 RFC,这很可能在很多 JWT 实现中实现,
  • 它使用椭圆曲线,具有一些轻微的安全性和性能优势。

另一个答案提到了量子计算机。我们现在没有可行的量子计算机,但如果它们存在,它们可以轻松破坏所有可能的 JWT 算法。所以从后量子的角度来看,你选择哪一个并不重要,因为所有这些都是同样不安全的。

也可以看看:

RSA 通常是首选算法,因为它现在相当陈旧,并且经过大量审查后幸存下来。选择它不会出错。IMO 的 256 变体已经足够好,因为 SHA256 远未被破坏。

如果您关心消息的大小,您可能会在 JWT 中这样做,您可能希望使用 ECC。它允许显着更短的签名,同时在理论上与 RSA 一样安全。在实践中,问题在于实施。过去曾出现过尖峰曲线,并且在实现方面存在许多问题,例如偏离曲线攻击。ECC 在实施 IMO 时更有可能出现错误。

PS 算法基于 RSA,但显然已修改为具有简化证明。我不会在证明中给出太多的库存,因为它相对较新且更复杂,实现可能会有问题。我不会选择这些。

所以最后,我会根据您需要的安全级别选择这两个中的一个。ES256 可能是大多数 webapps 的更好选择。

PS:无论哪种方式,您显然都应该确保及时更新您的 jwt 库,以防出现与安全相关的错误修复。

您应该以这种方式实现您的软件,以便您可以轻松地交换签名算法。希望 pyjwt 也能支持新的算法,当它们出现时。

鉴于有几个人害怕量子计算机,据说有一天能够破解 RSA,因为素数生成很容易并行化,您应该考虑使用椭圆曲线算法。

但正如以下段落所述......如果使用错误的方式,使用“好”算法通常是一个坏主意。