跳到主要内容
ecdsa.com
PyJWT (Python)JWT 库

错误信息

Signature verification failed

PyJWT (Python) — jwt.exceptions.InvalidSignatureError

含义

PyJWT 解码了令牌的结构并执行了签名检查,但检查没有通过:签名与密钥和载荷不匹配。InvalidSignatureError 是 DecodeError 的子类,因此范围过宽的 except DecodeError 可能会把它误标为解析问题——实际上这是密钥与内容不匹配。ES256 令牌还有一个额外的细节:JWS 签名必须是 64 字节的原始 r‖s 格式,所以由自行编写、输出 ASN.1 DER 的签名代码生成的令牌,即使密钥正确,也会在这一步验证失败。

原因

修复方法

  1. 1.

    在两端分别计算密钥指纹

    输出验证方加载的公钥的 SHA-256 指纹,并与颁发者的指纹比较。不一致,问题就查清了;一致,则说明问题出在令牌的字节上。

    python
    import hashlib
    from cryptography.hazmat.primitives import serialization
    
    public_key = serialization.load_pem_public_key(pem_bytes)  # the key the verifier uses
    spki = public_key.public_bytes(serialization.Encoding.DER, serialization.PublicFormat.SubjectPublicKeyInfo)
    print(hashlib.sha256(spki).hexdigest())  # compare with the issuer's
  2. 2.

    先检查 kid,再怀疑令牌损坏

    读取未经验证的头部,确认你用来验证的正是令牌所指定的密钥。如果颁发者有多个密钥,就通过 PyJWKClient 按 kid 查找。

    python
    import jwt
    
    header = jwt.get_unverified_header(token)
    print(header)  # {'alg': 'ES256', 'kid': '...'}
    
    from jwt import PyJWKClient
    key = PyJWKClient("https://issuer.example/.well-known/jwks.json") \
        .get_signing_key_from_jwt(token).key
    payload = jwt.decode(token, key, algorithms=["ES256"], audience="api://orders")

相关错误

浏览完整的签名错误库