RS256 vs HS256:有什么区别?

Ric*_*ler 216 jwt auth0 asp.net-core-webapi

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

ASP.NET Core Web ApiAuth0文档中, JWT算法有两种选择:RS256和HS256.这可能是一个愚蠢的问题但是:

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

Nic*_*ena 389

两种选择都指的是身份提供者用于签署 JWT的算法.签名是一种加密操作,可生成令牌接收者可以验证的"签名"(JWT的一部分),以确保令牌未被篡改.

  • RS256(带SHA-256的 RSA签名)是一种非对称算法,它使用公钥/私钥对:身份提供者有一个用于生成签名的私有(秘密)密钥,JWT的消费者获得一个公钥验证签名.由于与私钥相对的公钥不需要保持安全,因此大多数身份提供商使消费者可以轻松获得和使用(通常通过元数据URL).

  • 另一方面,HS256(HMAC与SHA-256)是对称算法,只有一个(秘密)密钥在双方之间共享.由于使用相同的密钥来生成签名并对其进行验证,因此必须注意确保密钥不受损害.

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

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

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

例如,OIDC元数据端点采用的形式https://{account domain}/.well-known/openid-configuration.如果浏览到该URL,您将看到一个带有引用的JSON对象https://{account domain}/.well-known/jwks.json,其中包含该帐户的公钥(或多个密钥).

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

  • 注意当使用rs256时 - 许多库中存在(或曾经)[安全风险](https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/)确定使用哪种算法.基本上,攻击者可以使用带有hs256编码的公共rs256密钥来假装它是密钥.因此,请确保您的库没有此行为! (40认同)
  • 一个小的修正,“ HS256(另一方面,具有SHA-256的HMAC)是一种对称算法”-HMAC不使用对称密钥算法(这将允许您通过其定义来加密和解密签名)。它在[HMAC](https://en.wikipedia.org/wiki/HMAC)下面利用了加密哈希函数和秘密加密密钥。这意味着使用附加的密钥计算消息上的哈希(单向函数)。 (4认同)
  • 以 Google 为例:转到 https://accounts.google.com/.well-known/openid-configuration 并查看 jwks_uri ;它将您转发到 https://www.googleapis.com/oauth2/v3/certs ,您可以在其中找到密钥。然后你只需要通过它的孩子取回好钥匙即可。 (2认同)

Cha*_*lie 77

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

对称算法

单个密钥用于加密数据.使用密钥加密时,可以使用相同的密钥解密数据.例如,如果Mary使用密钥"my-secret"加密消息并将其发送给John,他将能够使用相同的密钥"my-secret"正确解密消息.

非对称算法

两个密钥用于加密和解密消息.虽然一个密钥(公共)用于加密消息,但另一个密钥(私有)只能用于解密它.因此,John可以生成公钥和私钥,然后只将公钥发送给Mary来加密她的消息.该消息只能使用私钥解密.

HS256和RS256场景

这些算法不用于加密/解密数据.相反,它们用于验证数据的来源或真实性.当Mary需要向Jhon发送开放消息并且他需要验证消息肯定来自Mary时,可以使用HS256或RS256.

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

RS256使用一对键来做同样的事情.只能使用私钥生成签名.并且必须使用公钥来验证签名.在这种情况下,即使Jack找到了公钥,他也无法创建带有签名的欺骗邮件来冒充Mary.

  • 任何人都可以访问公钥并用于加密。但私钥由服务器保存,用于解密公钥加密的内容。私钥永远不会被泄露。 (2认同)

Joh*_*ren 30

性能有所不同.

简单地说HS256RS256验证快一个数量级,但比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)
Run Code Online (Sandbox Code Playgroud)

不要挂在实际数字上,只要相互尊重它们.

[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.
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @RobEvans是的,不要挂在这里的性能数字。选择正确的解决方案来解决您的问题。这只是一个观察,而不是建议您使用HS256而不是RS256的建议,您必须根据自己的情况做出决定。 (4认同)
  • @MatthewMarkMiller 请记住,尽管它们在使用上并不相同。他们有不同的特点。RS256 是非对称的,因此在仅共享公钥的客户端/服务器样式通信中,它是更好的选择。HS256 需要共享可以签名和验证的密钥 - 仅当您信任双方或不需要其中一方解密任何内容时才有用。 (3认同)

Hir*_*ran 6

简短的回答,特定于 OAuth2,

  • HS256用户客户端密钥用于生成令牌签名,并且需要相同的密钥来在后端验证令牌。因此,您应该在后端服务器中拥有该机密的副本来验证签名。
  • RS256使用公钥加密对令牌进行签名。签名(哈希)将使用私钥创建,并且可以使用公钥进行验证。因此,不需要将私钥或客户端密钥存储在后端服务器中,但后端服务器将从租户中的 openid 配置 url 中获取公钥 ( https://[tenant]/.well-known/openid -configuration)来验证令牌。access_toekn 中的 KID 参数将用于从 openid 配置中检测正确的密钥(公共)。


归档时间:

查看次数:

128231 次

最近记录:

6 年,4 月 前