JWT.encode 和 JWT.decode 基于 Ruby 的 openssl gem,支持 256/384/512 的 HS、RS、PS 和 ES 以及 ES256K。EdDSA 已不再属于 jwt gem:只加载 jwt 3.3.0 时,用 EdDSA 编码报错 Unsupported signing method,添加 jwt-eddsa 后才能正常工作——但它的原生依赖 ed25519 在安装时需要 C 编译器,而 slim 容器镜像中没有。
验证时必须指明算法:不带 algorithm: 调用 JWT.decode(token, key, true) 报错 Expected a different algorithm。未签名的令牌在验证时会被拒绝,只有关闭验证(JWT.decode(token, nil, false))才能读取,而对于要信任的令牌,代码绝不应这样做。密钥类型会被检查:用 EC 密钥的 PEM 文本伪造的 HS256 令牌,在验证密钥为 EC 密钥对象时报错 HMAC key expected to be a String——但把 PEM 字符串作为 HS256 密钥传入时,它验证通过了,因此要把密钥保存为 OpenSSL::PKey 对象。ES256 在签名时会拒绝 P-384 密钥。
声明检查需要显式启用:没有容差,而且除非列入 required_claims,否则 exp 是可选的——示例就把它和颁发者一起列了进去。任意长度的 HMAC 密钥都会被接受——5 字节的密钥签名和验证都没有任何警告——因此要用 JWT 密钥检测工具检查密钥。
ES256 签名是 64 字节的原始 r‖s;DER 签名会报错 Signature verification failed。把令牌粘贴到 JWT 调试器中,即可查看它采用哪种编码。