无需在 PyJWT 库中解码即可验证 JWT 令牌签名

Verify the JWT token signature without decoding it in the PyJWT library

是否可以在 PyJWT 库中不解码的情况下验证 JWT 令牌签名?

我不知道我是否明白你的要求,但无论如何我都会尝试。

整个 JWT 标准在此 link 中得到了很好的解释。 本质上,如果我明白你在问什么,你想在不解码令牌本身的情况下检查签名。 为了回答您的问题,我将使用在 link.

中找到的一些内容

在其紧凑的形式中,一个 JSON 网络令牌由三个部分组成,由点 (.) 分隔,它们是:

  • Header:通常由两部分组成,token的类型,也就是JWT,以及使用的签名算法,比如HMAC SHA256或者RSA(你用的是RSA ).

  • 有效负载:包含声明。声明是关于一个实体的陈述(这就是你正在解码以找到 public 我认为的 public 键的内容)

  • 签名:要创建签名部分,您必须采用编码的 header、编码的有效负载、秘密、header 中指定的算法,然后对其进行签名.例如,如果你想使用 HMAC SHA256 算法,签名将按以下方式创建:

    HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(有效载荷), 秘密)

签名用于验证消息在传输过程中没有被更改,并且,对于使用私钥签名的令牌,它还可以验证 JWT 的发送者是它说的是谁。

这三个元素经过base64编码,由“.”连接。因此 JWT 是这样的:akuhsdk.wqkhkwje.sajgdhwqj

因此,如果我想签署一条消息以证明它来自我,我可以使用我自己的私钥生成签名。任何有兴趣验证消息的人都可以使用我的 public 密钥来确认签名是否有效。

此时,接收方可以通过解密签名并检查它是否有效来验证签名(大多数加密库会抛出错误)。如果不是,那么用于加密它的私钥不是来自 key-pair.

的私钥

示例

import jwt

token = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJ1c2VyX2lkIjoxMjN9.HT1kBSdGFAznrhbs2hB6xjVDilMUmKA-_36n1pLLtFTKHoO1qmRkUcy9bJJwGuyfJ_dbzBMyBwpXMj-EXnKQQmKlXsiItxzLVIfC5qE97V6l6S0LzT9bzixvgolwi-qB9STp0bR_7suiXaON-EzBWFh0PzZi7l5Tg8iS_0_iSCQQlX5MSJW_-bHESTf3dfj5GGbsRBRsi1TRBzvxMUB6GhNsy6rdUhwoTkihk7pljISTYs6BtNoGRW9gVUzfA2es3zwBaynyyMeSocYet6WJri97p0eRnVGtHSWwAmnzZ-CX5-scO9uYmb1fT1EkhhjGhnMejee-kQkMktCTNlPsaUAJyayzdgEvQeo5M9ZrfjEnDjF7ntI03dck1t9Bgy-tV1LKH0FWNLq3dCJJrYdQx--A-I7zW1th0C4wNcDe_d_GaYopbtU-HPRG3Z1SPKFuX1m0uYhk9aySvkec66NBfvV2xEgo8lRZyNxntXkMdeJCEiLF1UhQvvSvmWaWC-0uRulYACn4H-tZiaK7zvpcPkrsfJ7iR_O1bxMPziKpsM4b7c7tmsEcOUZY-IHEI9ibd54_A1O72i08sCWKT5CXyG70MAPqyR0MFlcV7IuDtBW3LCqyvfsDVk4eIj8VcSU1OKQJ1Gl-CTOHEyN-ncV3NslVLaT9Q1C4E7uK2QpS8z0'
public_key = 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCcjWidoIPNRc3IN1hoGeOdSvDkBDK3W3P7/4HxLf62nvUQVczL3FG+dG9KSRnzuvRoUi1o3TASO3Yn72FSfaLPE/JmOtpu/IGuB/oF/CrJqEHA/08n0xkNQK8kwdIqayKPS84PVOm8XomNijMpUCahqu9cGZDPhlgqD8PAxw4e1ZQSizWj0hTSCR78dmHAEr5oXryP6uD0Mw/KGKYel/KTMu00dShWPzHnJeLaYvKgMJKPN6pqhsWFQsNUDnKd9tgn3NSPeHECnnBbUxB2BeuVz72+HnyFWah3mpGH4Dr+9rjRXiPg2AYxgR3U93AEQ6osefxeIKUSCXWx1txNV07QzwFVag4vPBmrA9XktC7i5EP91wxUOsyzhG8geXKuDHmE+/7U3AsExHYFkBLqMnW92CaTeQ408xsRXjxWjSNHpfqhZVxGY5Eh8L3NVqgRg1LdnZYHpovi1iP4Zx2Z7Nb5F9ejuMsA+v/D0WL3c6bhwU8BKdD7YZDG2tpzq6PHt+NarGkcWWh9/p/SIJoZi+e35mjcUMfnRD8w/ouL0sTnxebT7xBCVucfRoMPA67USoChDpc+pNsdtsqlQOZMgpPZYfjIyCThv5mwjEKHnytBq46ULOFlHt0opplDANnDsvWwqEobhACZM+n2ZNtu36eoc3bC/Hak8ACEi5DixirF0w== miguel@MS90J8G8WL'

payload = jwt.decode(token, public_key, algorithms=['RS256'])

print(payload)

所以,是的,你可以做到。

但是要用代码完成你所要求的,你必须使用其他一些库(加密),因为 pyJWT 只提供 decode 方法,它需要一个完整的令牌(header+payload+signature),就像示例中那样。此外,您必须存储在第一次读取令牌期间获得的 header 以获取使用的加密算法(如果更改)。

但是,您为什么不想再次解码呢?这样你甚至可以检查它是否与签名的相同并且没有人篡改消息。