Juan, parte de este gran equipo, nos ha hecho el favor de escribir este artículo ya que domina muy bien este tema.
Solución:
Ambas opciones se refieren al algoritmo que 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 asegurarse de que el token no haya sido manipulado.
-
RS256 (RSA Signature with SHA-256) es un algoritmo asimétrico y utiliza un público / privado key par: el proveedor de identidad tiene un privado (secreto) key utilizado para generar la firma, y el consumidor del JWT obtiene un público key para validar la firma. Dado que el publico key, a diferencia de lo privado key, no necesita mantenerse seguro, la mayoría de los proveedores de identidad lo ponen a disposición de los consumidores para que lo obtengan y usen (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 hash y una (secreta) key que se comparte entre las dos partes que se utiliza para generar el hash que servirá como firma. Ya que el mismo key se utiliza tanto para generar la firma como para validarla, se debe tener cuidado para asegurar que el key no está comprometido.
Si va a desarrollar la aplicación que consume los JWT, puede usar HS256 de manera segura, porque tendrá control sobre quién usa el secreto keys. Si, por otro lado, no tiene control sobre el cliente, o no tiene forma de asegurar un secreto key, RS256 encajará mejor, ya que el consumidor solo necesita conocer al público (compartido) key.
Dado que el publico key generalmente está disponible desde los puntos finales de metadatos, los clientes pueden programarse para recuperar el público key automáticamente. Si este es el caso (como ocurre con las bibliotecas .Net Core), tendrá menos trabajo que hacer en la configuración (las bibliotecas buscarán el público key desde el servidor). Simétrico keys, por otro lado, deben intercambiarse fuera de banda (lo que garantiza un canal de comunicación seguro) y actualizarse manualmente si hay una firma key dese la vuelta.
Auth0 proporciona puntos finales de metadatos para los protocolos OIDC, SAML y WS-Fed, donde el público keys se puede recuperar. 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 navega a esa URL, verá un objeto JSON con una referencia a https://account domain/.well-known/jwks.json
, que contiene el público key (o keys) de la cuenta.
Si observa las muestras de RS256, verá que no necesita configurar el público key en cualquier lugar: el marco lo recupera automáticamente.
En criptografía se utilizan dos tipos de algoritmos:
Algoritmos simétricos
Un solo key se utiliza para cifrar datos. Cuando se cifra con el key, los datos se pueden descifrar utilizando el mismo key. Si, por ejemplo, Mary cifra un mensaje con el key “my-secret” y se lo envía a John, él podrá descifrar el mensaje correctamente con el mismo key “mi secreto”.
Algoritmos asimétricos
Dos keys se utilizan para cifrar y descifrar mensajes. Mientras uno key(público) se utiliza para cifrar el mensaje, el otro key(privado) solo se puede usar para descifrarlo. Entonces, John puede generar públicos y privados keys, luego envía solo al público key a Mary para cifrar su mensaje. El mensaje solo se puede descifrar utilizando el privado key.
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 es seguramente de Mary, se puede utilizar HS256 o RS256.
HS256 puede crear una firma para una muestra determinada de datos utilizando un único key. Cuando el mensaje se transmite junto con la firma, la parte receptora puede utilizar el mismo key para verificar que la firma coincide con el mensaje.
RS256 utiliza un par de keys hacer lo mismo. Una firma solo se puede generar usando el privado key. Y el publico key debe utilizarse para verificar la firma. En este escenario, incluso si Jack encuentra al público key, no puede crear un mensaje falso con una firma para hacerse pasar por Mary.
Hay una diferencia en el rendimiento.
Simplemente pon HS256
es aproximadamente 1 orden de magnitud más rápido que RS256
para verificación, pero aproximadamente 2 órdenes de magnitud más rápido que RS256
para emitir (firmar).
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:N1x slower (verify)");
Console.WriteLine($"RS256 is (n1 / s1.Elapsed.TotalSeconds) / (n3 / s3.Elapsed.TotalSeconds),9:N1x slower (issue)");
// RS256 is about 7.5x slower, but it can still do over 10K ops per sec.
Sección de Reseñas y Valoraciones
Más adelante puedes encontrar las acotaciones de otros programadores, tú asimismo puedes insertar el tuyo si te gusta.