Lir*_*hen 21 rsa digital-signature jwt
我正在JWT(JsonWebToken)计划的帮助下实现登录系统.基本上在用户登录/登录后,服务器签署JWT并将其传递给客户端.
然后,客户端返回每个请求的令牌,服务器在发回响应之前验证令牌.
这几乎是你所期望的,但我对这个过程的逻辑有一些问题.从我读过的所有数学文章来看,似乎RSA签名使用非对称密钥进行签名.正如其名称所示,公钥暴露给客户端并且私钥保留在服务器上,使用发送到客户端的公钥对JWT进行签名并使用服务器端验证它是有意义的.私钥.
然而,在每个示例和库中,我看到它似乎是另一种方式,任何想法为什么它是这样的?如果JWT使用私钥签名并与公共密钥进行验证,那么这一点是什么?
Joh*_*ohn 40
首先,道歉,这个答案相当长.
如果您使用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.尽管如此,我不是专家,只是最近搜索过这个话题的人,所以带着一点点盐.
小智 13
签名/验证和加密/解密数据之间存在差异,但语义可能相似。
您使用只有受控来源拥有的私钥对数据进行签名,因此接收信息的任何人都可以使用您的公钥来验证此信息确实是由您发送的,并且与您打算发送的信息相同。
您使用公钥加密数据并使用私钥解密。这听起来相反,但实际上遵循与签名相同的逻辑概念。如果要在人 A 和人 B 之间发送数据,则双方都有一个公钥/私钥对,并且他们在见面(握手)时彼此共享公钥。A 为 B 构造一条消息,并使用 B 的公钥对其进行加密,然后将其发送给 B。现在,没有 B 的私钥,任何人都无法解密包括 A 在内的消息——即使他们最初发送了消息。
就 JWT 而言,JWT 负载本身只是带有一些标准化字段的 Base64 编码 JSON。签名允许拥有公钥的人验证信息未被中间人更改。类似于校验和,但具有一些额外的基于安全的温暖模糊感觉。签名的 JWT 的内容对最终用户和中间的任何人都很容易看到(base64 是像 unicode 或 utf-8 一样的编码,而不是加密),这就是为什么通常不赞成在 JWT 中发送敏感数据,如密码或个人身份信息。
正如其他人所提到的,大多数 JWT 包含的信息并非面向客户端,而是帮助促进 RESTful 服务的无状态部分。通常,JWT 将包含 accountid、userid 和通常作为“声明”的权限。API 端点可以验证签名并合理地相信声明不会被客户端更改。让客户端为每个请求发送 JWT 可以节省端点来回执行大量数据库的工作,只需简单地使用公钥验证签名即可获得它们所在的位置。
此外,可以加密签名的 JWT。根据JWE 规范,有效载荷在签名后加密,然后在验证前解密。这里的权衡是所有端点还必须拥有私钥来解密 JWT,但最终用户将无法看到 JWT 的内容。我说权衡是因为一般来说,私钥是为了保持安全,而广泛分布的私钥就不太安全。加密的安全性、风险评估和成本/收益完全是另一回事:)
Han*_* Z. 11
你的建议:
使用发送到客户端的公钥对JWT进行签名并使用私钥在服务器端验证它是有意义的.
是不正确的.使用服务器的私钥进行签名,使用客户端的公钥进行加密.这就是PKI的一般工作方式.