RS256 vs HS256: ¿Cuál es la diferencia?


255

Estoy usando Auth0 para manejar la autenticación en mi aplicación web. Estoy usando ASP.NET Core v1.0.0 y Angular 2 rc5 y no sé mucho sobre autenticación / seguridad en general.

En los documentos Auth0 para ASP.NET Core Web Api , hay dos opciones para que el algoritmo JWT sea RS256 y HS256. Esta puede ser una pregunta tonta pero:

¿Cuál es la diferencia entre RS256 y HS256? ¿Cuáles son algunos casos de uso (si corresponde)?


Encontré un Angular2-JWT con firbase / php-Jwt en el tutorial de aplicación del lado del servidor freakyjolly.com/…
Code Spy el

Respuestas:


435

Ambas opciones se refieren a qué algoritmo utiliza el proveedor de identidad para firmar el JWT. La firma es una operación criptográfica que genera una "firma" (parte del JWT) que el destinatario del token puede validar para garantizar que el token no haya sido alterado.

  • RS256 (Firma RSA con SHA-256 ) es un algoritmo asimétrico , y utiliza un par de claves pública / privada: el proveedor de identidad tiene una clave privada (secreta) utilizada para generar la firma, y ​​el consumidor del JWT obtiene una clave pública para validar la firma. Dado que la clave pública, a diferencia de la clave privada, no necesita mantenerse protegida, la mayoría de los proveedores de identidad hacen que sea fácil de obtener y usar para los consumidores (generalmente a través de una URL de metadatos).

  • HS256 ( HMAC con SHA-256), por otro lado, implica una combinación de una función de hashing y una clave (secreta) que se comparte entre las dos partes utilizadas para generar el hash que servirá como firma. Dado que la misma clave se usa tanto para generar la firma como para validarla, se debe tener cuidado para garantizar que la clave no se vea comprometida.

Si va a desarrollar la aplicación que consume los JWT, puede usar HS256 de forma segura, ya que tendrá control sobre quién usa las claves secretas. Si, por otro lado, no tiene control sobre el cliente, o no tiene forma de asegurar una clave secreta, RS256 será una mejor opción, ya que el consumidor solo necesita conocer la clave pública (compartida).

Dado que la clave pública generalmente está disponible desde puntos finales de metadatos, los clientes pueden programarse para recuperar la clave pública automáticamente. Si este es el caso (como sucede con las bibliotecas .Net Core), tendrá menos trabajo que hacer en la configuración (las bibliotecas buscarán la clave pública del servidor). Las claves simétricas, por otro lado, deben intercambiarse fuera de banda (asegurando un canal de comunicación seguro), y actualizarse manualmente si hay una renovación de clave de firma.

Auth0 proporciona puntos finales de metadatos para los protocolos OIDC, SAML y WS-Fed, donde se pueden recuperar las claves públicas. Puede ver esos puntos finales en la "Configuración avanzada" de un cliente.

El punto final de metadatos OIDC, por ejemplo, toma la forma de https://{account domain}/.well-known/openid-configuration. Si navega a esa URL, verá un objeto JSON con una referencia a https://{account domain}/.well-known/jwks.json, que contiene la clave pública (o claves) de la cuenta.

Si observa las muestras RS256, verá que no necesita configurar la clave pública en ningún lado: el marco la recupera automáticamente.


46
NB al usar rs256: hay (o hubo) un riesgo de seguridad en muchas bibliotecas que permitió que el token determinara qué algoritmo usar. Esencialmente, el atacante podría usar la clave pública rs256 con una codificación hs256 para fingir que es la clave secreta. ¡Así que asegúrese de que su biblioteca no tenga este comportamiento!
AlexFoxGill

77
Una pequeña corrección, "HS256 (HMAC con SHA-256), por otro lado, es un algoritmo simétrico" - HMAC no utiliza un algoritmo de clave simétrica (que le permitiría cifrar y descifrar la firma por su definición). Utiliza una función de cifrado hash y una clave criptográfica secreta debajo de HMAC . Lo que implica el cálculo del hash (función unidireccional) sobre el mensaje con una clave secreta adjunta.
Kikoz

1
Ejemplo con Google: vaya a accounts.google.com/.well-known/openid-configuration y mire jwks_uri; te reenvía a googleapis.com/oauth2/v3/certs donde puedes encontrar claves. Entonces solo tienes que recuperar la clave buena por su hijo.
Denis TRUFFAUT

Vale la pena señalar que ya que HS256 comparte una clave entre dos partes que hace que este algoritmo no pueda admitir múltiples audiencias en el acceso_token, mientras que RS256 puede admitir muchas audiencias. Esto es importante para los clientes de Identidad como Auth0 que solo permiten una solicitud al punto final / userinfo usando access_token si la configuración es RS256, ya que necesitan este token para admitir su dominio api como aud, así como su dominio auth0.
jezpez

95

En criptografía hay dos tipos de algoritmos utilizados:

Algoritmos simétricos

Se utiliza una sola clave para cifrar datos. Cuando se cifra con la clave, los datos se pueden descifrar con la misma clave. Si, por ejemplo, Mary cifra un mensaje con la clave "my-secret" y se lo envía a John, podrá descifrar el mensaje correctamente con la misma clave "my-secret".

Algoritmos asimétricos

Se usan dos claves para cifrar y descifrar mensajes. Mientras que una clave (pública) se usa para cifrar el mensaje, la otra clave (privada) solo se puede usar para descifrarlo. Entonces, John puede generar claves públicas y privadas, luego enviar solo la clave pública a Mary para cifrar su mensaje. El mensaje solo se puede descifrar con la clave privada.

Escenario HS256 y RS256

Estos algoritmos NO se utilizan para cifrar / descifrar datos. Más bien se utilizan para verificar el origen o la autenticidad de los datos. Cuando Mary necesita enviar un mensaje abierto a Jhon y él necesita verificar que el mensaje sea de Mary, se puede usar HS256 o RS256.

HS256 puede crear una firma para una muestra de datos dada usando una sola clave. Cuando el mensaje se transmite junto con la firma, la parte receptora puede usar la misma clave para verificar que la firma coincida con el mensaje.

RS256 usa un par de claves para hacer lo mismo. Una firma solo se puede generar utilizando la clave privada. Y la clave pública debe usarse para verificar la firma. En este escenario, incluso si Jack encuentra la clave pública, no puede crear un mensaje falso con una firma para hacerse pasar por Mary.


39

Hay una diferencia en el rendimiento.

En pocas palabras, HS256es aproximadamente 1 orden de magnitud más rápido que RS256para la verificación, pero aproximadamente 2 órdenes de magnitud más rápido que RS256para la emisión (firma).

 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)

No se obsesione con los números reales, solo piense en ellos con respeto mutuo.

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

Estos son números importantes. gracias. Tiendo a pensar que el cifrado es un rendimiento de wrt más o menos transparente, pero su investigación implica que usar R256 para firmar comunicaciones entre máquinas agrega 1 ms por salto.
Matthew Mark Miller

1
@MatthewMarkMiller Tenga en cuenta que no son iguales en uso. Tienen diferentes caracteristicas. RS256 es asimétrico y, por lo tanto, en una comunicación de estilo cliente / servidor donde solo comparte la clave pública, es una mejor opción. HS256 requiere compartir la clave que puede firmar Y verificar, solo útil si confía en las dos partes o no necesita que una de las partes descifre nada.
Rob Evans

77
@RobEvans sí, no te obsesiones con los números de rendimiento aquí. Elija la solución adecuada a su problema. Esto es solo una observación, no una recomendación para favorecer HS256 sobre RS256, debe tomar esa decisión en función de su contexto.
John Leidegren

1
Cuando la elección del protocolo puede tener el mismo impacto en la latencia que un kilómetro adicional de cable, vale la pena saberlo, especialmente en estos días de largas cadenas de llamadas y TTL apretados.
Matthew Mark Miller el

0

respuesta corta, específica de OAuth2,

  • El secreto del cliente del usuario HS256 para generar la firma del token y el mismo secreto son necesarios para validar el token en el back-end. Por lo tanto, debe tener una copia de ese secreto en su servidor de fondo para verificar la firma.
  • RS256 usa el cifrado de clave pública para firmar el token. La firma (hash) se creará usando una clave privada y se puede verificar usando una clave pública. Por lo tanto, no necesita una clave privada o secreto de cliente para almacenar en el servidor de fondo, pero el servidor de fondo buscará la clave pública de la url de configuración de openid en su inquilino ( https: // [inquilino] /.well-known/openid -configuración ) para verificar el token. El parámetro KID dentro de access_toekn se usará para detectar la clave correcta (pública) de la configuración de openid.
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.