错误信息
The specified key byte array is 96 bits which is not secure enough for any JWT HMAC-SHA algorithm.
也可能输出为
- io.jsonwebtoken.security.WeakKeyException: The specified key byte array is 96 bits which is not secure enough for any JWT HMAC-SHA algorithm.
- io.jsonwebtoken.security.SignatureException: Unable to compute HS512 signature. Cause: The signing key's size is 256 bits which is not secure enough for the HS512 algorithm.
- io.jsonwebtoken.security.WeakKeyException: The signing key's size is 256 bits which is not secure enough for the HS512 algorithm.
位数随你的密钥而变化。`Keys.hmacShaKeyFor` 报出的是“…not secure enough for any JWT HMAC-SHA algorithm”。如果签名时显式指定的算法要求比你的密钥更长的密钥,消息中会写出该算法:JJWT 0.12+ 将其包装为“SignatureException: Unable to compute HS512 signature. Cause: The signing key's size is 256 bits…”,0.11 则直接抛出 `WeakKeyException`。
JJWT (Java) — io.jsonwebtoken.security.WeakKeyException from Keys.hmacShaKeyFor / signWith
含义
JJWT 拒绝用少于算法哈希输出位数的数据构建 HMAC 密钥:HS256 至少 256 位(32 字节),HS384 至少 384 位,HS512 至少 512 位。RFC 7518 §3.2 将此规定为必须(MUST),因为过短的共享密钥可以通过任意一个用它签名的令牌离线暴力破解出来——之后任何人都能签发有效的令牌。消息中的数字是你所提供字节的大小。
原因
人类可读的密钥
常见`secret`、`changeme` 这类值,或者教程中的简短口令,都远远不到 32 字节。它们的长度本身也说明,这些值从来就不是为生产环境准备的。
从 JJWT 0.9 升级
常见JJWT 0.9 接受以字符串形式传入的短密钥。0.10+ 强制执行 RFC 7518 规定的密钥长度,因此同样的配置在升级后会失败。
密钥长度够 HS256 用,但不够 HS512
偶见32 字节的密钥满足 HS256 的要求,但不满足 HS384/HS512。`signWith(key)` 会选择密钥所允许的最强算法;显式指定更强的算法则会失败。
修复方法
- 1.
生成长度合适的随机密钥
使用密码学安全的随机值(64 字节可满足所有 HMAC 变体),以 base64 编码后存入机密管理服务。
bash # 64 random bytes, base64-encoded: enough for HS256, HS384 and HS512 openssl rand -base64 64 | tr -d '\n' - 2.
把存储的密钥解码为字节
用解码后的字节创建密钥,而不是用 base64 文本,这样每个服务得到的都是同一个密钥。
java import io.jsonwebtoken.io.Decoders; import io.jsonwebtoken.security.Keys; javax.crypto.SecretKey key = Keys.hmacShaKeyFor(Decoders.BASE64.decode(System.getenv("JWT_SECRET_B64"))); String token = io.jsonwebtoken.Jwts.builder().subject("user-42").signWith(key).compact();