RS256 vs HS256: Fark nedir?


255

Web uygulamamda kimlik doğrulaması yapmak için Auth0 kullanıyorum. ASP.NET Core v1.0.0 ve Angular 2 rc5 kullanıyorum ve genel olarak kimlik doğrulama / güvenlik hakkında fazla bir şey bilmiyorum.

In ASP.NET Çekirdek Web Api için Auth0 docs , RS256 ve HS256 olmak JWT algoritması için iki seçenek vardır. Bu aptalca bir soru olabilir ama:

RS256 ve HS256 arasındaki fark nedir? Bazı kullanım durumları nelerdir (varsa)?


Sunucu tarafında uygulama öğreticisinde firbase
Code Spy

Yanıtlar:


435

Her iki seçenek de kimlik sağlayıcısının JWT'yi imzalamak için kullandığı algoritmayı ifade eder . İmzalama, belirteç kurcalanmamasını sağlamak için belirteç alıcısının doğrulayabileceği bir "imza" (JWT'nin bir parçası) üreten bir şifreleme işlemidir.

  • RS256 ( SHA-256 ile RSA İmzası ) asimetrik bir algoritmadır ve genel / özel bir anahtar çifti kullanır: kimlik sağlayıcısının imzayı oluşturmak için kullanılan özel (gizli) bir anahtarı vardır ve JWT müşterisi ortak bir anahtar alır imzayı doğrulamak için. Ortak anahtarın, özel anahtarın aksine, güvende tutulması gerekmediğinden, çoğu kimlik sağlayıcısı tüketicilerin (genellikle bir meta veri URL'si aracılığıyla) edinmesini ve kullanmasını kolaylaştırır.

  • Öte yandan HS256 ( SHA-256 ile HMAC ), imza işlevi görecek karma oluşturmak için kullanılan iki taraf arasında paylaşılan bir karma işlev ve bir (gizli) anahtarın bir kombinasyonunu içerir. Aynı anahtar hem imzayı oluşturmak hem de onaylamak için kullanıldığından, anahtarın tehlikeye atılmamasına dikkat edilmelidir.

JWT'leri tüketen uygulamayı geliştirecekseniz, HS256'yı güvenle kullanabilirsiniz, çünkü gizli anahtarları kimin kullandığını kontrol edebilirsiniz. Öte yandan, istemci üzerinde kontrolünüz yoksa veya gizli bir anahtarı korumanın bir yolu yoksa, RS256 daha iyi bir seçim olacaktır, çünkü tüketicinin sadece ortak (paylaşılan) anahtarı bilmesi gerekir.

Genel anahtar genellikle meta veri uç noktalarından kullanılabilir olduğundan, istemciler genel anahtarı otomatik olarak almak üzere programlanabilir. Bu durumda (.Net Core kütüphanelerinde olduğu gibi), yapılandırma üzerinde daha az işiniz olacaktır (kütüphaneler ortak anahtarı sunucudan getirecektir). Öte yandan, simetrik anahtarların bant dışında değiştirilmesi (güvenli bir iletişim kanalı sağlanması) ve imza anahtarının üzerine gelindiğinde manuel olarak güncellenmesi gerekir.

Auth0, ortak anahtarların alınabildiği OIDC, SAML ve WS-Fed protokolleri için meta veri uç noktaları sağlar. Bu uç noktaları bir istemcinin "Gelişmiş Ayarlar" altında görebilirsiniz.

Örneğin, OIDC meta veri uç noktası https://{account domain}/.well-known/openid-configuration. Bu URL'ye göz atarsanız https://{account domain}/.well-known/jwks.json, hesabın genel anahtarını (veya anahtarlarını) içeren başvurusu olan bir JSON nesnesi görürsünüz .

RS256 örneklerine bakarsanız, ortak anahtarı herhangi bir yerde yapılandırmanız gerekmediğini göreceksiniz: çerçeve tarafından otomatik olarak alınır.


46
Not: rs256 kullanırken - tokenin hangi algoritmayı kullanacağını belirlemesine izin veren birçok kütüphanede bir güvenlik riski vardır (veya mevcuttu) . Aslında saldırgan gizli anahtar olduğunu iddia etmek için genel rs256 anahtarını bir hs256 kodlamasıyla kullanabilir. Bu yüzden kütüphanenizde bu davranış olmadığından emin olun!
AlexFoxGill

7
Bir küçük düzeltme, "HS256 (SHA-256 ile HMAC), simetrik bir algoritmadır" - HMAC simetrik bir anahtar algoritması kullanmaz (bu, imzayı tanımıyla şifrelemenize ve şifresini çözmenize izin verir). HMAC altında bir kriptografik hash fonksiyonu ve gizli bir kriptografik anahtar kullanır . Bu, eklenen bir gizli anahtarla mesaj üzerindeki karma (tek yönlü işlev) hesaplamasını ifade eder.
Kikoz

1
Google ile örnek: accounts.google.com/.well-known/openid-configuration adresine gidin ve jwks_uri adresine bakın; sizi anahtarları bulabileceğiniz googleapis.com/oauth2/v3/certs adresine yönlendirir . O zaman sadece iyi anahtarı çocuğu tarafından almanız gerekir.
Denis TRUFFAUT

HS256'nın iki taraf arasında bir anahtarı paylaşması , bu algoritmanın bir erişim_dokusunda birden fazla kitleyi desteklemesini sağlarken, RS256'nın birçok kitleyi destekleyebileceğini belirtmek gerekir. Bu, yapılandırma RS256 ise / userinfo uç noktasına yalnızca / userinfo uç noktasına bir istekte bulunmasına izin veren Kimlik istemcileri için önemlidir, çünkü api alanınızı bir aud olarak desteklemek için bu jetona ve aynı zamanda auth0 alanlarına ihtiyaç duyarlar.
jezpez

95

Kriptografide iki tür algoritma kullanılır:

Simetrik algoritmalar

Verileri şifrelemek için tek bir anahtar kullanılır. Anahtarla şifrelendiğinde, verilerin şifresi aynı anahtar kullanılarak çözülebilir. Örneğin, Mary "sırrım" anahtarını kullanarak bir mesajı şifreler ve John'a gönderirse, mesajın şifresini aynı "sırrım" ile doğru bir şekilde çözebilir.

Asimetrik algoritmalar

Mesajları şifrelemek ve şifresini çözmek için iki anahtar kullanılır. İletiyi şifrelemek için bir anahtar (genel) kullanılırken, diğer anahtar (özel) yalnızca şifresini çözmek için kullanılabilir. Böylece, John hem genel hem de özel anahtarlar üretebilir, ardından mesajını şifrelemek için Mary'ye yalnızca ortak anahtarı gönderebilir. Mesajın şifresi yalnızca özel anahtar kullanılarak çözülebilir.

HS256 ve RS256 Senaryosu

Bu algoritmalar verileri şifrelemek / şifrelerini çözmek için KULLANILMAZ. Bunun yerine, verilerin kökenini veya gerçekliğini doğrulamak için kullanılırlar. Mary'nin Jhon'a açık bir mesaj göndermesi gerektiğinde ve mesajın kesinlikle Mary'den geldiğini doğrulaması gerektiğinde, HS256 veya RS256 kullanılabilir.

HS256, tek bir anahtar kullanarak belirli bir veri örneği için imza oluşturabilir. Mesaj imza ile birlikte iletildiğinde, alıcı taraf imzanın mesajla eşleştiğini doğrulamak için aynı anahtarı kullanabilir.

RS256 aynısını yapmak için bir çift anahtar kullanır. İmza yalnızca özel anahtar kullanılarak oluşturulabilir. Ve genel anahtar imzayı doğrulamak için kullanılmalıdır. Bu senaryoda, Jack ortak anahtarı bulsa bile, Mary'yi taklit etmek için imzalı bir sahte mesaj oluşturamaz.


39

Performansta bir fark var.

Basitçe söylemek gerekirse HS256, RS256doğrulama için olandan yaklaşık 1 büyüklük sırası daha hızlı, ancak RS256verme (imzalama) için olandan daha büyük olan 2 büyüklük sırası daha hızlıdır .

 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)

Gerçek sayılara takılmayın, sadece birbirlerine saygı gösterin.

[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.
        }
    }
}

Bunlar önemli sayılar. teşekkür ederim. Şifrelemenin az ya da çok şeffaf wrt verimi olduğunu düşünüyorum, ancak araştırmanız, intermachine iletişimi imzalamak için R256 kullanmanın atlama başına 1 ms eklediğini ima ediyor.
Matthew Mark Miller

1
@MatthewMarkMiller Kullanımda eşit olmadıklarını unutmayın. Farklı özellikleri vardır. RS256 asimetriktir ve bu nedenle yalnızca ortak anahtarı paylaştığınız istemci / sunucu tarzı iletişimde daha iyi bir seçenektir. HS256, hem imzalayan hem de doğrulayabilen anahtarı paylaşmayı gerektirir - yalnızca iki tarafa güveniyorsanız veya herhangi bir şeyin şifresini çözmek için taraflardan birine ihtiyacınız yoksa yararlıdır.
Rob Evans

7
@RobEvans evet, buradaki performans numaralarına takılma. Sorununuza doğru çözümü seçin. Bu sadece bir gözlem, HS256'yı RS256 yerine tercih etmek için bir öneri değil, bu kararı bağlamınıza göre vermelisiniz.
John Leidegren

1
Protokol seçimi, fazladan bir kilometrelik bir kabloyla gecikme üzerinde aynı etkiye sahip olabiliyorsa, özellikle bu günlerde uzun çağrı zincirleri ve sıkı TTL'lerde bilmeye değer.
Matthew Mark Miller

0

OAuth2'ye özgü kısa cevap,

  • Belirteç imzasını oluşturmak için HS256 kullanıcı istemcisi sırrı ve belirteci arka uçta doğrulamak için aynı sır gereklidir. Bu nedenle, imzayı doğrulamak için arka uç sunucunuzda bu sırrın bir kopyasına sahip olmalısınız.
  • RS256 , jetonu imzalamak için ortak anahtar şifrelemesini kullanır. İmza (karma) özel anahtar kullanarak oluşturulur ve genel anahtar kullanılarak doğrulanabilir. Bu nedenle, arka uç sunucuda saklamak için özel anahtara veya istemci sırrına gerek yoktur, ancak arka uç sunucusu, ortak anahtarı kiracıdaki openid yapılandırma URL'sinden alır ( https: // [kiracı] /.well-known/openid -configuration ) belirtin . Access_toekn içindeki KID parametresi, openid yapılandırmasından doğru anahtarı (genel) algılamak için kullanır.
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.