JWT:在 HMAC 和 RSA 之间进行选择

信息安全 电子签名 RSA hmac jwt
2021-09-03 03:18:09

据我了解,HMAC 是一种对称签名算法(单个密钥),而 RSA 是一种非对称签名算法(私钥/公钥对)。我试图在这两种签名 JSON Web 令牌的方法之间进行选择。

但是,我对 HMAC 的用例有点困惑。如果客户端(用户)和服务器共享一个密钥,那么是什么阻止客户端更改令牌的有效负载字段(可能是另一个用户的 id 的主题),然后在客户端重新签署令牌。显然这会很糟糕。HMAC 是否只保证数据是由使用密钥的人签名的,而不是像 RSA 那样只是一个实体?这实际上有什么用例,也许我误解了什么?或者可能根本不与客户共享密钥?

2个回答

HMAC 用于防止无权访问机密的人操纵。通常,这意味着如果只有服务器知道秘密,则防止客户端操纵,或者如果客户端和服务器知道秘密,则防止传输中的操纵。

基于 RSA 的签名用于防止操纵,也允许其他人在无法操纵数据的情况下验证数据的完整性和来源之所以可以这样做,是因为只有数据的提供者和签名者才知道私钥,而喜欢验证完整性的每个人都知道公钥。

因此,选择什么取决于您的具体用例。如果服务器只需要保护令牌不被客户端操纵,那么使用带有服务器端机密的 HMAC 就足够了。相反,如果还需要向其他人证明令牌是由特定(受信任的)服务器创建的,则应使用基于 RSA 的签名。

请参阅JWT 推荐算法的更长答案,单行答案是使用 RS256(带有 SHA 256 的 RSA 2048 位)。

JWT 令牌支持几种签名方案,主要是:RSA(RS256)、ECDSA(ES256)和 HMAC(HS256)。

HMAC 是一种专门针对 JWT 的对称签名模式。据我所知,它没有实际用例,你最好完全忽略它。

在 HMAC 中,应用程序和身份提供者共享一个秘密密码。密码用于创建和验证令牌。

想想就觉得奇怪,因为它允许客户端和身份服务器都创建身份验证令牌。“正常”操作模式仅用于身份服务器(Google、Facebook auth、内部 Active Directory 等)来验证用户并创建 JWT 令牌。客户制造代币毫无意义。

理论上,HMAC 可以用在一些奇异的 app2app 用例中,但在使用普通签名 (RSA/ECDSA) 时,这些用例已经被覆盖——而且更安全——因此 HS256 没有实际应用。

  1. 传递信任:Google 和 Apple 身份验证可以相互信任,共享一个秘密密码来制作内部令牌并相互交流。

除了开箱即用的常规签名已经支持联合身份验证,而且更容易。没有理由更喜欢秘密密码,在组织之间共享秘密密码需要额外的工作,如果任何一个泄露秘密,两个组织都会受到损害。

  1. app2app 身份验证:服务可以向身份服务器进行身份验证,以获取自己的 JWT 令牌并与其他服务(受身份验证保护)进行通信。

除了已使用用户名/密码或证书身份验证开箱即用地支持编程身份验证。没有理由更喜欢秘密密码。

我以身份验证为生,我已经在一些公司实现了所有这些用例。在规范的深渊中,在client_credentials授予服务到服务身份验证(除了客户端证书身份验证之外)中,还有一些关于客户端签署 JWT 令牌的事情。我 99% 确定这是唯一可以使用共享密钥模式的地方(以一种非疯狂的方式),以及为什么规范中完全支持该模式......并且使用证书身份验证可以更好地涵盖所有这些。