了解JWT的RSA签名

了解JWT的RSA签名,rsa,jwt,digital-signature,Rsa,Jwt,Digital Signature,我正在JWT(JSONWebToken)方案的帮助下实现一个登录系统。基本上,在用户登录/登录之后,服务器会签署JWT并将其传递给客户端 然后,客户端随每个请求返回令牌,服务器在返回响应之前验证令牌 这几乎是你所期望的,但我对这个过程的逻辑有一些问题。从我读过的所有数学文章来看,RSA签名似乎使用非对称密钥进行签名。正如其名称所示,公钥向客户端公开,私钥保存在服务器上,因此使用发送到客户端的公钥对JWT进行签名并在服务器端使用私钥进行验证是有意义的 然而,在我看到的每个示例和库中,似乎都是相反的

我正在JWT(JSONWebToken)方案的帮助下实现一个登录系统。基本上,在用户登录/登录之后,服务器会签署JWT并将其传递给客户端

然后,客户端随每个请求返回令牌,服务器在返回响应之前验证令牌

这几乎是你所期望的,但我对这个过程的逻辑有一些问题。从我读过的所有数学文章来看,RSA签名似乎使用非对称密钥进行签名。正如其名称所示,公钥向客户端公开,私钥保存在服务器上,因此使用发送到客户端的公钥对JWT进行签名并在服务器端使用私钥进行验证是有意义的

然而,在我看到的每个示例和库中,似乎都是相反的。你知道为什么会这样吗?如果JWT使用私钥签名并使用公钥验证,那么这有什么意义?

您的建议:

使用发送到JWT的公钥对JWT进行签名是有意义的 客户端,并在服务器端使用私钥对其进行验证


这是不对的。签名使用发送方的私钥完成,加密使用接收方的公钥完成。这就是PKI通常的工作原理。

首先,抱歉,这个答案太长了

如果您使用RSA对令牌进行签名,并且连接的客户端是web浏览器,则客户端将永远看不到RSA密钥(公用或专用)。这是因为客户机可能不需要验证JWT是否有效,只有服务器需要验证。客户机只是抓住JWT,并在被请求时将其显示给服务器。然后,服务器在看到令牌时进行检查以确保其有效

那么,为什么JWT需要公钥/私钥组合呢?首先,您不需要使用公钥/私钥算法

您可以使用许多不同的算法对JWT进行签名,RSA就是其中之一。签署JWT的其他流行选择是ECDSA或HMAC算法(JWT标准支持)。具体而言,HMAC不是公钥/私钥方案。只有一个密钥,用于签名和验证令牌的密钥。您可以将其视为使用私钥对JWT进行签名和验证。无论如何,我不是这方面的专家,但以下是我最近通过自己的研究得出的结论:

使用HMAC很好,因为它是最快的选择。然而,为了验证JWT,你需要给某人一个万能的钥匙,与其他人共享这个钥匙意味着这个人现在也可以签署代币并假装他们就是你。如果您正在构建多个服务器应用程序,这些应用程序都需要能够验证JWT,那么您可能不希望每个应用程序都能够对令牌进行签名(不同的程序员可能正在维护不同的应用程序,与更多人共享签名能力是一种安全风险,等等)。在这种情况下,最好有一个严格控制的私钥(和一个进行签名的应用程序),然后与其他人共享公钥,让他们能够验证令牌。这里,私钥用于对令牌进行签名,公钥用于验证令牌。在这种情况下,您需要选择RSA或ECDSA

例如,您可能有一个应用程序生态系统,所有应用程序都连接到 相同的数据库。要让用户登录,每个应用程序都会将用户发送到一个应用程序, 专用的“登录”应用程序。此应用程序具有私钥。其他的 应用程序可以验证此人是否使用公钥登录(但 他们无法让人登录)

我所做的研究表明,在这种情况下,RSA是大多数JWT应用程序的更好选择。这是因为从理论上讲,您的应用程序将经常验证令牌。RSA在验证时比ECDSA快得多。ECDSA主要很好,因为密钥的大小较小。这使得HTTPS证书更好,因为您需要将公钥发送到客户端的浏览器。但在JWT场景中,密钥保留在服务器上,因此存储大小为n/a,验证速度更为重要


结论:如果您正在构建一个没有多个小型“微服务应用程序”的小型应用程序/您是唯一的开发人员,可能会选择HMAC来加密您的密钥。否则,可能会选择RSA。再说一遍,我不是专家,只是最近在谷歌上搜索过这个话题的人,所以对此持保留态度。

签名/验证和加密/解密数据之间有区别,但语义可能类似

您使用只有受控源才具有的私钥对数据进行签名,以便接收信息的任何人都可以使用您的公钥验证此信息是否确实由您发送,以及是否与您打算发送的信息相同

您使用公钥加密数据,并使用私钥解密。这听起来相反,但实际上遵循与签名相同的逻辑概念。如果您想在人员A和人员B之间发送数据,两人都有一对公钥/私钥,并且在见面时(握手)彼此共享公钥。A为B构造一条消息,并使用B的公钥对其进行加密并将其发送给B。现在,没有B的私钥的任何人都无法解密包含A的消息,即使他们最初发送了它

就JWT而言,JWT负载本身就是带有一些标准化字段的Base64编码JSON。签名允许有公共密钥的人验证信息没有被中间人更改。类似于校验和,但有一些额外的安全性为基础的温暖模糊的感觉。签名的JWT的内容很容易被看到(Base64是Unicode或UTF-8编码,而不是加密)给最终用户和中间的任何人,这就是为什么人们通常不赞成SE的原因。