我使用Auth0在我的网络应用中处理身份验证。我使用的是ASP.NET Core v1.0.0和Angular 2 rc5,而且我对身份验证/安全性的了解并不多。
在Auth0 docs for ASP.NET Core Web Api中,JWT算法有两种选择:RS256和HS256。这可能是一个愚蠢的问题,但是:
RS256与HS256的区别是什么?有哪些用例(如果适用)?
答案 0 :(得分:312)
这两个选项都指的是身份提供商用于签署 JWT的算法。签名是一种加密操作,可生成"签名" (JWT的一部分)令牌的接收者可以验证以确保令牌没有被篡改。
RS256(带SHA-256的RSA签名)是asymmetric algorithm,它使用公钥/私钥对:身份提供者具有用于生成签名的私有(秘密)密钥,JWT的消费者获得了验证签名的公钥。由于与私钥相对的公钥不需要保持安全,因此大多数身份提供商使消费者可以轻松获取和使用(通常通过元数据URL)。
另一方面,HS256(HMAC与SHA-256)是symmetric algorithm,只有一个(秘密)密钥在双方之间共享。由于使用相同的密钥来生成签名并对其进行验证,因此必须注意确保密钥不受损害。
如果您要开发使用JWT的应用程序,您可以安全地使用HS256,因为您可以控制谁使用密钥。 另一方面,如果您无法控制客户端,或者您无法获得密钥,RS256将更适合,因为消费者只需要知道公共(共享)密钥
由于公钥通常可以从元数据端点获得,因此可以对客户端进行编程以自动检索公钥。如果是这种情况(与.Net Core库一样),您将在配置方面做的工作量较少(库将从服务器获取公钥)。另一方面,对称密钥需要在带外交换(确保安全的通信信道),并在有签名密钥翻转时手动更新。
Auth0为OIDC,SAML和WS-Fed协议提供元数据端点,可以检索公钥。您可以在"高级设置"下看到这些端点。客户。
例如,OIDC元数据端点采用https://{account domain}/.well-known/openid-configuration
的形式。如果浏览到该URL,您将看到一个引用https://{account domain}/.well-known/jwks.json
的JSON对象,其中包含该帐户的公钥(或多个密钥)。
如果您查看RS256示例,您将看到不需要在任何地方配置公钥:它由框架自动检索。
答案 1 :(得分:60)
在密码学中,使用了两种类型的算法:
对称算法
单个密钥用于加密数据。使用密钥加密时,可以使用相同的密钥解密数据。例如,如果Mary使用密钥" my-secret"加密消息。并将其发送给John,他将能够使用相同的密钥" my-secret"正确解密消息。
非对称算法
两个密钥用于加密和解密消息。虽然一个密钥(公共)用于加密消息,但另一个密钥(私有)只能用于解密它。因此,John可以生成公钥和私钥,然后只将公钥发送给Mary来加密她的消息。该消息只能使用私钥解密。
HS256和RS256场景
这些算法不用于加密/解密数据。相反,它们用于验证数据的来源或真实性。当Mary需要向Jhon发送开放消息并且他需要验证消息肯定来自Mary时,可以使用HS256或RS256。
HS256可以使用单个密钥为给定的数据样本创建签名。当消息与签名一起传输时,接收方可以使用相同的密钥来验证签名是否与消息匹配。
RS256使用一对键来做同样的事情。只能使用私钥生成签名。并且必须使用公钥来验证签名。在这种情况下,即使Jack找到了公钥,他也无法创建带有签名的欺骗邮件来冒充Mary。
答案 2 :(得分:25)
性能存在差异。
简单地说HS256
比RS256
快一个数量级用于验证,但比发布(签名)RS256
快约2个数量级。
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)
不要挂在实际的数字上,只要相互尊重它们。
[Program.cs中]
class Program
{
static void Main(string[] args)
{
foreach (var duration in new[] { 1, 3, 5, 7 })
{
var t = TimeSpan.FromSeconds(duration);
byte[] publicKey, privateKey;
using (var rsa = new RSACryptoServiceProvider())
{
publicKey = rsa.ExportCspBlob(false);
privateKey = rsa.ExportCspBlob(true);
}
byte[] key = new byte[64];
using (var rng = new RNGCryptoServiceProvider())
{
rng.GetBytes(key);
}
var s1 = new Stopwatch();
var n1 = 0;
using (var hs256 = new HMACSHA256(key))
{
while (s1.Elapsed < t)
{
s1.Start();
var hash = hs256.ComputeHash(privateKey);
s1.Stop();
n1++;
}
}
byte[] sign;
using (var rsa = new RSACryptoServiceProvider())
{
rsa.ImportCspBlob(privateKey);
sign = rsa.SignData(privateKey, "SHA256");
}
var s2 = new Stopwatch();
var n2 = 0;
using (var rsa = new RSACryptoServiceProvider())
{
rsa.ImportCspBlob(publicKey);
while (s2.Elapsed < t)
{
s2.Start();
var success = rsa.VerifyData(privateKey, "SHA256", sign);
s2.Stop();
n2++;
}
}
var s3 = new Stopwatch();
var n3 = 0;
using (var rsa = new RSACryptoServiceProvider())
{
rsa.ImportCspBlob(privateKey);
while (s3.Elapsed < t)
{
s3.Start();
rsa.SignData(privateKey, "SHA256");
s3.Stop();
n3++;
}
}
Console.WriteLine($"{s1.Elapsed.TotalSeconds:0} {n1,7:N0} {n1 / s1.Elapsed.TotalSeconds,9:N1} ops/s");
Console.WriteLine($"{s2.Elapsed.TotalSeconds:0} {n2,7:N0} {n2 / s2.Elapsed.TotalSeconds,9:N1} ops/s");
Console.WriteLine($"{s3.Elapsed.TotalSeconds:0} {n3,7:N0} {n3 / s3.Elapsed.TotalSeconds,9:N1} ops/s");
Console.WriteLine($"RS256 is {(n1 / s1.Elapsed.TotalSeconds) / (n2 / s2.Elapsed.TotalSeconds),9:N1}x slower (verify)");
Console.WriteLine($"RS256 is {(n1 / s1.Elapsed.TotalSeconds) / (n3 / s3.Elapsed.TotalSeconds),9:N1}x slower (issue)");
// RS256 is about 7.5x slower, but it can still do over 10K ops per sec.
}
}
}
答案 3 :(得分:0)
针对OAuth2的简短答案,