关于JWT标准算法与OpenSSL dgst对齐及算法匹配的技术问询
解答:JWT算法与OpenSSL dgst的对齐方式
首先必须明确:绝对不能忽略HS/RS/ES/PS这些前缀,只看后面的位数来匹配OpenSSL的哈希选项。JWT算法的前缀代表的是签名的核心机制,后面的数字才对应哈希算法的类型(SHA256/SHA384/SHA512),二者是绑定在一起的,不能拆分单独使用。
先拆解JWT算法的命名逻辑
JWT的算法名格式是[前缀][哈希位数],其中:
- HS:HMAC(对称签名机制)——用同一个密钥完成签名和验证,本质是将哈希值与密钥做HMAC运算
- RS:RSA(非对称签名机制)——用私钥对哈希值做RSA签名,公钥验证
- ES:ECDSA(椭圆曲线非对称签名机制)——基于椭圆曲线对哈希值做签名,比RSA更轻量化
- PS:RSASSA-PSS(带概率签名方案的RSA)——RSA的安全变种,抗攻击能力更强
而后面的256/384/512,才对应OpenSSL里的-sha256/-sha384/-sha512哈希算法选项。
不同JWT算法对应的OpenSSL dgst命令示例
下面是几种常见JWT算法的具体OpenSSL操作,你可以对照理解:
1. HS256(HMAC-SHA256)
这是对称签名,需要用-hmac参数指定密钥:
# 生成签名:对base64url编码的Header.Payload做HMAC-SHA256 echo -n "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ" | openssl dgst -sha256 -hmac "your-secret-key"
2. RS256(RSA-SHA256)
这是非对称签名,需要用私钥对哈希值做签名,不能只用-sha256(那只是单纯哈希,不是签名):
# 生成签名:用RSA私钥对Header.Payload的SHA256哈希做签名 echo -n "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ" | openssl dgst -sha256 -sign ./rsa-private-key.pem
验证时用公钥:
# 验证签名:用RSA公钥验证签名的合法性 echo -n "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ" | openssl dgst -sha256 -verify ./rsa-public-key.pem -signature ./signature.bin
3. ES256(ECDSA-SHA256)
需要使用椭圆曲线密钥,OpenSSL需要对应曲线支持(比如secp256r1):
# 生成ES256签名 echo -n "<Header.Payload>" | openssl dgst -sha256 -sign ./ec-private-key.pem
4. PS256(RSASSA-PSS-SHA256)
这是RSA的变种,需要指定PSS填充模式:
# 生成PS256签名 echo -n "<Header.Payload>" | openssl dgst -sha256 -sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:-1 -sign ./rsa-private-key.pem
你的操作误区
你提到用openssl dgst -sha256处理RS256的JWT头部,这其实只完成了哈希计算,而RS256需要的是用RSA私钥对这个哈希值做签名——单纯的哈希结果并不是JWT的签名,所以这样的操作是无效的。
总结一下:位数只是对应哈希算法的类型,但前缀决定了哈希值的使用方式(是做HMAC、RSA签名还是ECDSA签名),必须根据JWT的alg字段完整选择对应的OpenSSL命令参数,不能只看位数忽略前缀。
内容的提问来源于stack exchange,提问作者Alex_P
相关产品推荐
相关产品推荐

