Cuando comparo HS256 vs RS256, no empiezo preguntando cuál es “más seguro” en abstracto. Empiezo por la arquitectura: quién necesita firmar tokens, quién solo debe verificarlos y a cuántos sistemas tengo que distribuir material sensible.
Esa pregunta suele decidir más que el nombre del algoritmo.
Mi modelo mental de HS256
HS256 es HMAC con SHA-256. El mismo secret se usa para firmar y verificar.
shared secret
├── firma JWT
└── verifica JWT
Si entrego el secret a una API para verificar, también le doy material suficiente para producir firmas que otros holders del mismo secret podrían aceptar.
Puede ser perfectamente válido en una frontera pequeña y controlada. Se vuelve más importante cuando crece el número de verificadores.
Mi modelo mental de RS256
RS256 usa RSA PKCS#1 v1.5 con SHA-256.
private key -> firma
public key -> verifica
Puedo distribuir public keys a muchas APIs sin repartir la private signing key. Por eso suelo preferir un esquema asymmetric cuando un IdP central emite tokens para muchos servicios independientes.
La primera pregunta: ¿quién puede emitir tokens confiables?
Si un único servicio firma y verifica dentro del mismo boundary, HS256 puede ser simple y adecuado.
Si un authorization server firma para muchas APIs, normalmente quiero que esas APIs verifiquen sin adquirir signing authority. Eso me lleva a RS256 u otro esquema asymmetric.
Para mí la elección es una decisión sobre distribución de autoridad, no solo criptografía.
Cuándo considero HS256
- signer y verifier están dentro de un mismo boundary estrecho;
- el secret se distribuye a muy pocos sistemas;
- no necesito publicar una public key;
- la simplicidad operativa pesa;
- acepto conscientemente que cada holder del secret puede firmar.
El secret debe ser fuerte y aleatorio. RFC 8725 advierte de secrets HMAC humanos o débiles por ataques de guessing offline.
Cuándo me encaja RS256
- un IdP central firma;
- muchas APIs verifican;
- los verificadores no deben poder emitir tokens;
- necesito publicar public keys;
- quiero rotar claves mediante JWK/JWKS.
Una public key RSA expuesta no debería permitir crear firmas RS256 válidas. La credencial crítica sigue siendo la private key.
Por qué no digo “RS256 siempre es más seguro”
HS256 falla operativamente cuando el secret es débil, se copia por demasiados servicios, cada verifier se convierte en signer, o el verifier acepta algorithms inesperados.
RS256 falla cuando la private key está mal protegida, se confían public keys arbitrarias, hay JWKS obsoleto tras rotation, se omiten issuer/audience o la policy viene del token.
Elijo el key model que encaja y luego protejo ese modelo correctamente.
Fijo el algoritmo desde configuración confiable
Nunca dejo que un JWT no verificado decida la policy.
Si mi aplicación espera RS256:
allowed algorithms = [RS256]
No cambio dinámicamente a HS256 porque el header lo pida. RFC 8725 recomienda un conjunto explícito de algorithms permitidos.
Distribución de secret en HS256
auth server -- shared secret --> API A
-- shared secret --> API B
-- shared secret --> API C
Si cuatro sistemas conocen el secret, cuatro sistemas tienen potencial de signing. HMAC no está roto; la frontera de confianza es amplia.
Si no quiero ese modelo, cambio la arquitectura.
Distribución de key en RS256
auth server mantiene private key
|
+--> API A recibe public key
+--> API B recibe public key
+--> API C recibe public key
Este diseño encaja bien con JWKS y key rotation.
Dónde entra kid
Con keys rotatorias puedo recibir:
{
"alg": "RS256",
"kid": "2026-key-03"
}
Uso kid para seleccionar una candidate key dentro de un JWKS confiable. No lo uso como prueba de confianza. La guía de JWT kid explica este paso y JWKS Validator lo reproduce localmente.
Ambos se pueden decodificar sin clave
HS256 y RS256 cambian la firma, no cifran el header/payload normal. Puedo leer ambos con el JWT Decoder. La clave aparece cuando paso de “qué dice” a “quién firmó esto”.
La guía de decodificación sin secreto cubre esa separación.
Mi checklist para HS256
- secret fuerte y aleatorio;
- número de sistemas que lo reciben;
- si cada verifier puede ser signer;
- encoding exacto del secret;
- algorithm allowlist;
- rotation y eliminación de copias antiguas.
Mi checklist para RS256
- protección de private key;
- origen de public keys;
- selección por
kiddurante rotation; - binding entre issuer y key source;
- rechazo de algorithms inesperados;
- issuer, audience y time validation después de la firma.
Si una firma falla, sigo la guía de invalid signature en lugar de probar algorithms hasta que alguno pase.
Mi regla final es: HS256 vs RS256 trata principalmente de key ownership y trust distribution.