2016-08-31 21 views
69

Używam Auth0 do obsługi uwierzytelniania w mojej aplikacji internetowej. Używam ASP.NET Core v1.0.0 i Angular 2 rc5 i nie wiem wiele na temat uwierzytelniania/bezpieczeństwa w ogóle.RS256 vs HS256: Jaka jest różnica?

W modelu Auth0 docs for ASP.NET Core Web Api można wybrać dwa algorytmy JWT: RS256 i HS256. To może być głupie pytanie, ale:

Jaka jest różnica między RS256 i HS256? Jakie są niektóre przypadki użycia (jeśli dotyczy)?

Odpowiedz

120

Obie opcje odnoszą się do algorytmu używanego przez dostawcę tożsamości do znaku JWT. Podpisywanie jest operacją kryptograficzną, która generuje "podpis" (część JWT), którą odbiorca tokena może zweryfikować, aby upewnić się, że token nie został naruszony.

  • RS256 (RSA podpisanie z SHA-256) jest asymmetric algorithm, i używa/para prywatnego klucza publicznego: dostawca tożsamości ma klucz prywatny (tajny) użyte do wygenerowania podpisu, a konsument z JWT otrzymuje klucz publiczny do sprawdzania poprawności podpisu. Ponieważ klucz publiczny, w przeciwieństwie do klucza prywatnego, nie musi być chroniony, większość dostawców tożsamości udostępnia go konsumentom w łatwy sposób do uzyskania i używania (zwykle poprzez adres URL metadanych).

  • HS256 (HMAC z SHA-256), z drugiej strony, to symmetric algorithm, z jednym (tajnym) kluczem, który jest dzielony między dwiema stronami. Ponieważ ten sam klucz służy zarówno do generowania podpisu, jak i do jego sprawdzania, należy zadbać o to, aby klucz nie został naruszony.

Jeśli będziesz rozwijał aplikację zużywającą JWT, możesz bezpiecznie używać HS256, ponieważ będziesz mieć kontrolę nad tym, kto używa tajnych kluczy. Jeśli z drugiej strony nie masz kontroli nad klientem lub nie masz możliwości zabezpieczenia tajnego klucza, RS256 będzie lepiej pasował, ponieważ konsument musi tylko znać klucz publiczny (udostępniony).

Ponieważ klucz publiczny jest zwykle udostępniany z punktów końcowych metadanych, klienci mogą być zaprogramowani do automatycznego pobierania klucza publicznego. Jeśli tak jest (tak jak w przypadku bibliotek .Net Core), będziesz miał mniej pracy do wykonania podczas konfiguracji (biblioteki będą pobierać klucz publiczny z serwera). Z drugiej strony, klucze symetryczne muszą być wymieniane poza pasmem (zapewniającym bezpieczny kanał komunikacji) i aktualizowane ręcznie, jeśli występuje rollover podpisywania kluczy.

Auth0 udostępnia metadane punktów końcowych dla protokołów OIDC, SAML i WS-Fed, w których można pobrać klucze publiczne. Te punkty końcowe można zobaczyć w "Ustawieniach zaawansowanych" klienta.

Punkt końcowy metadanych OIDC ma na przykład postać https://{account domain}/.well-known/openid-configuration. Jeśli przejdziesz do tego adresu URL, zobaczysz obiekt JSON z odniesieniem do https://{account domain}/.well-known/jwks.json, który zawiera klucz publiczny (lub klucze) konta.

Jeśli spojrzysz na próbki RS256, zobaczysz, że nie musisz konfigurować klucza publicznego w dowolnym miejscu: jest on automatycznie pobierany przez framework.

+12

przy użyciu rs256 NB - nie jest (lub występowało) [zagrożenie bezpieczeństwa] (https://auth0.com/blog/critical-vulnerabilities-in-json- web-token-libraries /) w wielu bibliotekach, które pozwoliły tokenowi określić, którego algorytmu użyć. Zasadniczo atakujący mógłby użyć publicznego klucza rs256 z kodowaniem hs256, aby udawać, że jest tajnym kluczem. Upewnij się więc, że twoja biblioteka nie ma takiego zachowania! – AlexFoxGill

16

W kryptografii istnieją dwa rodzaje algorytmów używanych:

symetryczne algorytmy

Pojedynczy klucz jest używany do szyfrowania danych. Po zaszyfrowaniu za pomocą klucza dane mogą zostać odszyfrowane przy użyciu tego samego klucza. Jeśli, na przykład, Mary szyfruje wiadomość za pomocą klucza "my-secret" i wysyła ją do Jona, będzie mógł poprawnie odszyfrować wiadomość za pomocą tego samego klucza - "my-secret".

asymetryczne algorytmy

Dwa przyciski służą do szyfrowania i deszyfrowania wiadomości. Podczas gdy jeden klucz (publiczny) jest używany do szyfrowania wiadomości, drugi klucz (prywatny) może być użyty tylko do jego odszyfrowania. Tak więc Jhon może generować klucze publiczne i prywatne, a następnie wysyłać tylko klucz publiczny do Mary, aby zaszyfrować swoją wiadomość. Wiadomość można odszyfrować tylko za pomocą klucza prywatnego.

HS256 i RS256 Scenariusz

algorytmy te nie są wykorzystywane do szyfrowania/dane decryt. Są raczej używane do weryfikacji pochodzenia lub autentyczności danych. Kiedy Mary musi wysłać otwartą wiadomość do Jhon i musi sprawdzić, czy wiadomość pochodzi z Mary, można użyć HS256 lub RS256.

HS256 może utworzyć podpis dla danej próbki danych za pomocą jednego klucza. Gdy wiadomość jest przesyłana wraz z podpisem, strona otrzymująca może użyć tego samego klucza do sprawdzenia, czy podpis jest zgodny z wiadomością.

RS256 używa pary kluczy, aby zrobić to samo. Podpis można wygenerować tylko za pomocą klucza prywatnego. A klucz publiczny musi być użyty do weryfikacji podpisu. W tym scenariuszu, nawet jeśli Jack znajdzie klucz publiczny, nie może utworzyć fałszywej wiadomości z podpisem podszywającym się pod Mary.

0

Występuje różnica w wydajności.

Po prostu wstaw HS256 jest o 1 rząd wielkości szybszy niż RS256 w celu weryfikacji, ale około 2 rzędy wielkości szybciej niż RS256 w celu wystawienia (podpisania).

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) 

Nie rozłączaj się na rzeczywistych liczbach, po prostu myśl o nich z szacunkiem dla siebie.

[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. 
     } 
    } 
} 
Powiązane problemy