RS256 vs HS256: Quelle est la différence?

255

J'utilise Auth0 pour gérer l'authentification dans mon application Web. J'utilise ASP.NET Core v1.0.0 et Angular 2 rc5 et je ne connais pas grand-chose à l'authentification / sécurité en général.

Dans les documents Auth0 pour ASP.NET Core Web Api , l'algorithme JWT est RS256 et HS256. Cela peut être une question stupide mais:

Quelle est la différence entre RS256 et HS256? Quels sont certains cas d'utilisation (le cas échéant)?

Rico Kahler
la source
J'ai trouvé un Angular2-JWT avec firbase / php-Jwt sur le tutoriel d'application côté serveur freakyjolly.com/…
Code Spy

Réponses:

435

Les deux choix font référence à l'algorithme utilisé par le fournisseur d'identité pour signer le JWT. La signature est une opération cryptographique qui génère une "signature" (partie du JWT) que le destinataire du jeton peut valider pour s'assurer que le jeton n'a pas été falsifié.

  • RS256 (signature RSA avec SHA-256 ) est un algorithme asymétrique , et il utilise une paire de clés publique / privée: le fournisseur d'identité a une clé privée (secrète) utilisée pour générer la signature, et le consommateur du JWT obtient une clé publique pour valider la signature. Étant donné que la clé publique, contrairement à la clé privée, n'a pas besoin d'être sécurisée, la plupart des fournisseurs d'identité la rendent facilement accessible et utilisable par les consommateurs (généralement via une URL de métadonnées).

  • HS256 ( HMAC avec SHA-256), d'autre part, implique une combinaison d'une fonction de hachage et d'une clé (secrète) qui est partagée entre les deux parties utilisées pour générer le hachage qui servira de signature. Étant donné que la même clé est utilisée à la fois pour générer la signature et pour la valider, il faut veiller à ce que la clé ne soit pas compromise.

Si vous développez l'application consommant les JWT, vous pouvez utiliser le HS256 en toute sécurité, car vous aurez le contrôle sur qui utilise les clés secrètes. Si, en revanche, vous n'avez pas de contrôle sur le client, ou si vous n'avez aucun moyen de sécuriser une clé secrète, RS256 conviendra mieux, car le consommateur n'a besoin que de connaître la clé publique (partagée).

Étant donné que la clé publique est généralement disponible à partir des points de terminaison de métadonnées, les clients peuvent être programmés pour récupérer la clé publique automatiquement. Si tel est le cas (comme c'est le cas avec les bibliothèques .Net Core), vous aurez moins de travail à faire sur la configuration (les bibliothèques chercheront la clé publique sur le serveur). Les clés symétriques, en revanche, doivent être échangées hors bande (garantissant un canal de communication sécurisé) et mises à jour manuellement en cas de roulement de clé de signature.

Auth0 fournit des points de terminaison de métadonnées pour les protocoles OIDC, SAML et WS-Fed, où les clés publiques peuvent être récupérées. Vous pouvez voir ces points de terminaison sous les "Paramètres avancés" d'un client.

Le point de terminaison des métadonnées OIDC, par exemple, prend la forme de https://{account domain}/.well-known/openid-configuration. Si vous accédez à cette URL, vous verrez un objet JSON avec une référence à https://{account domain}/.well-known/jwks.json, qui contient la clé publique (ou les clés) du compte.

Si vous regardez les exemples RS256, vous verrez que vous n'avez pas besoin de configurer la clé publique n'importe où: elle est récupérée automatiquement par le framework.

Nico Sabena
la source
46
NB lors de l'utilisation de rs256 - il y a (ou était) un risque de sécurité dans de nombreuses bibliothèques qui permettait au token de déterminer l'algorithme à utiliser. L'attaquant pourrait essentiellement utiliser la clé publique rs256 avec un codage hs256 pour prétendre qu'il s'agit de la clé secrète. Assurez-vous donc que votre bibliothèque n'a pas ce comportement!
AlexFoxGill
7
Une petite correction, "HS256 (HMAC avec SHA-256), d'autre part, est un algorithme symétrique" - HMAC n'utilise pas d'algorithme à clé symétrique (qui vous permettrait de crypter et décrypter la signature par sa définition). Il utilise une fonction de hachage cryptographique et une clé cryptographique secrète sous HMAC . Ce qui implique le calcul du hachage (fonction unidirectionnelle) sur le message avec une clé secrète ajoutée.
Kikoz
1
Exemple avec Google: accédez à accounts.google.com/.well-known/openid-configuration et regardez jwks_uri; il vous redirige vers googleapis.com/oauth2/v3/certs où vous pouvez trouver les clés. Ensuite, il vous suffit de récupérer la bonne clé par son enfant.
Denis TRUFFAUT
Il convient de noter que le HS256 partage une clé entre deux parties, ce qui rend cet algorithme incapable de prendre en charge plusieurs audiences dans le même access_token, tandis que RS256 peut prendre en charge de nombreuses audiences. Cela concerne les clients Identity comme Auth0 qui n'autorisent une requête vers le point de terminaison / userinfo en utilisant un access_token que si la configuration est RS256, car ils ont besoin de ce jeton pour prendre en charge votre domaine api en tant qu'aud, ainsi que leur domaine auth0.
jezpez
95

En cryptographie, deux types d'algorithmes sont utilisés:

Algorithmes symétriques

Une seule clé est utilisée pour crypter les données. Une fois chiffrées avec la clé, les données peuvent être déchiffrées à l'aide de la même clé. Si, par exemple, Mary crypte un message à l'aide de la clé "my-secret" et l'envoie à John, il pourra décrypter le message correctement avec la même clé "my-secret".

Algorithmes asymétriques

Deux clés sont utilisées pour crypter et décrypter les messages. Alors qu'une clé (publique) est utilisée pour crypter le message, l'autre clé (privée) ne peut être utilisée que pour le décrypter. Ainsi, John peut générer des clés publiques et privées, puis envoyer uniquement la clé publique à Mary pour crypter son message. Le message ne peut être déchiffré qu'à l'aide de la clé privée.

Scénario HS256 et RS256

Ces algorithmes ne sont PAS utilisés pour crypter / décrypter les données. Ils sont plutôt utilisés pour vérifier l'origine ou l'authenticité des données. Lorsque Mary doit envoyer un message ouvert à Jhon et qu'il doit vérifier que le message provient bien de Mary, HS256 ou RS256 peuvent être utilisés.

Le HS256 peut créer une signature pour un échantillon de données donné à l'aide d'une seule clé. Lorsque le message est transmis avec la signature, le destinataire peut utiliser la même clé pour vérifier que la signature correspond au message.

RS256 utilise une paire de clés pour faire de même. Une signature ne peut être générée qu'à l'aide de la clé privée. Et la clé publique doit être utilisée pour vérifier la signature. Dans ce scénario, même si Jack trouve la clé publique, il ne peut pas créer un message d'usurpation d'identité avec une signature pour usurper l'identité de Mary.

Charlie
la source
39

Il y a une différence de performances.

Autrement dit, il HS256est environ 1 ordre de grandeur plus rapide que RS256pour la vérification, mais environ 2 ordres de grandeur plus rapide que RS256pour l'émission (signature).

 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)

Ne vous attardez pas sur les chiffres réels, pensez-y simplement avec respect l'un pour l'autre.

[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.
        }
    }
}
John Leidegren
la source
Ce sont des chiffres importants. Merci. J'ai tendance à penser que le chiffrement est un débit wrt plus ou moins transparent, mais vos recherches impliquent que l'utilisation du R256 pour signer les communications entre machines ajoute 1 ms par saut.
Matthew Mark Miller
1
@MatthewMarkMiller Gardez à l'esprit que leur utilisation n'est pas égale. Ils ont des caractéristiques différentes. RS256 est asymétrique et donc dans une communication de type client / serveur où vous ne partagez que la clé publique, c'est une meilleure option. Le HS256 nécessite le partage de la clé qui peut à la fois signer ET vérifier - utile uniquement si vous faites confiance aux deux parties ou si vous n'avez besoin d'aucune des parties pour décrypter quoi que ce soit.
Rob Evans
7
@RobEvans oui, ne vous attardez pas sur les chiffres de performance ici. Choisissez la bonne solution à votre problème. Ceci est juste une observation, pas une recommandation de privilégier HS256 sur RS256, vous devez prendre cette décision en fonction de votre contexte.
John Leidegren
1
Lorsque le choix du protocole peut avoir le même impact sur la latence qu'un kilomètre de câble supplémentaire, cela vaut la peine d'être connu, en particulier en ces temps de longues chaînes d'appel et de TTL serrés.
Matthew Mark Miller
0

réponse courte, spécifique à OAuth2,

  • Secret client utilisateur HS256 pour générer la signature de jeton et le même secret est requis pour valider le jeton en back-end. Vous devez donc avoir une copie de ce secret sur votre serveur principal pour vérifier la signature.
  • RS256 utilise le cryptage à clé publique pour signer le jeton. La signature (hachage) crée à l'aide d'une clé privée et peut vérifier à l'aide de la clé publique. Ainsi, pas besoin de clé privée ou de secret client à stocker sur le serveur principal, mais le serveur principal récupérera la clé publique de l'URL de configuration openid dans votre client ( https: // [tenant] /.well-known/openid -configuration ) pour vérifier le jeton. Le paramètre KID à l'intérieur de access_toekn utilisera pour détecter la bonne clé (publique) de la configuration openid.
Hiran
la source