Jwt RS256 vs HS256:What';有什么区别?

Jwt RS256 vs HS256:What';有什么区别?,jwt,auth0,asp.net-core-webapi,Jwt,Auth0,Asp.net Core Webapi,我正在使用Auth0在我的web应用程序中处理身份验证。我使用的是ASP.NET Core v1.0.0和Angular 2 rc5,一般来说,我对身份验证/安全性了解不多 在中,JWT算法有两种选择:RS256和HS256。这可能是一个愚蠢的问题,但: RS256和HS256之间有什么区别?有哪些用例(如果适用)?这两个选项都是指身份提供者使用什么算法对JWT进行签名。签名是一种加密操作,它生成一个“签名”(JWT的一部分),令牌接收方可以验证该签名,以确保令牌未被篡改 RS256(RSA

我正在使用Auth0在我的web应用程序中处理身份验证。我使用的是ASP.NET Core v1.0.0和Angular 2 rc5,一般来说,我对身份验证/安全性了解不多

在中,JWT算法有两种选择:RS256和HS256。这可能是一个愚蠢的问题,但:


RS256和HS256之间有什么区别?有哪些用例(如果适用)?

这两个选项都是指身份提供者使用什么算法对JWT进行签名。签名是一种加密操作,它生成一个“签名”(JWT的一部分),令牌接收方可以验证该签名,以确保令牌未被篡改

  • RS256(RSA Signature with)是一个,它使用公钥/私钥对:身份提供者有一个用于生成签名的私钥,JWT的使用者获得一个公钥来验证签名。由于与私钥相反,公钥不需要保持安全,因此大多数身份提供者使消费者可以轻松获取和使用公钥(通常通过元数据URL)

  • 另一方面,HS256(具有SHA-256)涉及散列函数和一个(秘密)密钥的组合,该密钥在用于生成用作签名的散列的双方之间共享。由于生成签名和验证签名都使用相同的密钥,因此必须小心确保密钥不被泄露

如果要开发使用JWTs的应用程序,可以安全地使用HS256,因为您可以控制谁使用密钥。 另一方面,如果您无法控制客户端,或者无法保护密钥,则RS256更适合,因为使用者只需要知道公共(共享)密钥

由于公钥通常可从元数据端点获得,因此可以对客户端进行编程以自动检索公钥。如果是这种情况(就像.Net核心库一样),您需要做的配置工作将更少(库将从服务器获取公钥)。另一方面,对称密钥需要在带外交换(确保安全的通信通道),如果存在签名密钥翻转,则需要手动更新

Auth0为OIDC、SAML和WS-Fed协议提供元数据端点,在这些协议中可以检索公钥。您可以在客户端的“高级设置”下看到这些端点

例如,OIDC元数据端点的形式为
https://{account domain}/.well-known/openid配置
。如果浏览到该URL,您将看到一个JSON对象,其中引用了
https://{account domain}/.well-known/jwks.JSON
,其中包含帐户的公钥


如果查看RS256示例,您将发现不需要在任何地方配置公钥:它由框架自动检索。

在密码学中,使用了两种算法:

对称算法

一个密钥用于加密数据。使用密钥加密时,可以使用相同的密钥对数据进行解密。例如,如果Mary使用密钥“my secret”加密消息并将其发送给John,他将能够使用相同的密钥“my secret”正确解密消息

非对称算法

两个密钥用于加密和解密消息。虽然一个密钥(public)用于加密消息,但另一个密钥(private)只能用于解密消息。因此,John可以生成公钥和私钥,然后只将公钥发送给Mary以加密她的消息。只能使用私钥对消息进行解密

HS256和RS256方案

这些算法不用于加密/解密数据。而是用来验证数据的来源或真实性。当Mary需要向Jhon发送开放式消息,并且Jhon需要验证消息是否确实来自Mary时,可以使用HS256或RS256

HS256可以使用单个密钥为给定的数据样本创建签名。当消息与签名一起传输时,接收方可以使用相同的密钥验证签名是否与消息匹配


RS256使用一对密钥执行相同的操作。只能使用私钥生成签名。必须使用公钥来验证签名。在这种情况下,即使Jack找到了公钥,他也无法创建带有签名的欺骗消息来冒充Mary。

性能有所不同

简单地说,
HS256
RS256
快约1个数量级用于验证,但比
RS256
快约2个数量级用于签发(签名)

不要被实际的数字所困扰,只要考虑到他们之间的相互尊重

[Program.cs]

类程序
{
静态void Main(字符串[]参数)
{
foreach(新[]{1,3,5,7}中的var持续时间)
{
var t=从秒开始的时间跨度(持续时间);
字节[]公钥,私钥;
使用(var rsa=new RSACryptoServiceProvider())
{
publicKey=rsa.ExportCspBlob(false);
privateKey=rsa.ExportCspBlob(true);
}
字节[]键=新字节[64];
使用(var rng=new RNGCryptoServiceProvider())
{
rng.GetBytes(键);
}
var s1=新秒表();
var n1=0;
使用(var hs256=新的HMACSHA256(键))
{
而(s1.0 640,251  91,464.3 ops/s
  86,123  12,303.3 ops/s (RS256 verify)
   7,046   1,006.5 ops/s (RS256 sign)