jwt - online - RS256 vs HS256: ¿Cuál es la diferencia?
jwt decode token online (3)
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 manipulado.
-
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á mejor, 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 de OIDC, por ejemplo, toma la forma de
https://{account domain}/.well-known/openid-configuration
.
Si explora 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 lugar: el marco la recupera automáticamente.
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)?
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 usando la clave "my-secret" y se lo envía a John, él 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 debe 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.
Hay una diferencia en el rendimiento.
En pocas palabras,
HS256
es aproximadamente 1 orden de magnitud más rápido que
RS256
para la verificación, pero aproximadamente 2 órdenes de magnitud más rápido que
RS256
para 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.
}
}
}