jwt的解密和RSA签名验证

2023-05-16

为了 理解jwt的验签过程,自己写的测试验证代码如下:

#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File : jwt_test.py
@Contact : boweiqiang@163.com
@MTime : 2020-04-26 11:32
@Author: boweiqiang
@Version: 1.0
@Desciption:
jwt的签名算法JWT 的签名算法有三种:
1.对称加密HMAC【哈希消息验证码】  HS256/HS384/HS512
2.非对称加密RSASSA【RSA签名算法】RS256/RS384/RS512
3.ECDSA【椭圆曲线数据签名算法】 ES256/ES384/ES512,RSA签名
这里实验的是RSA签名和验签的过程
注意:本文中用的jwt是:https://pypi.org/project/jwt/,安装方法为:pip3 install jwt
注意与python-jwt区别:https://pypi.org/project/python-jwt/,安装方法为:pip install python_jwt
'''
import time

import base64
from Crypto.PublicKey import RSA
from jwt import JWT, jwk_from_pem

print('-----------生成RSA密钥对--------------')
rsa_key = RSA.generate(1024)
rsa_private_key = rsa_key.export_key()
rsa_public_key = rsa_key.public_key().export_key()
print(rsa_private_key.decode('utf-8'))
print(rsa_public_key.decode('utf-8'))

print('-----------生成jwt--------------')
exp_time = int(time.time() + 60)
payload_origin = {'userId': 123456, 'name': 'mogui', 'exp': exp_time}
jwt_pri_key = jwk_from_pem(rsa_private_key)

jwt = JWT()
jwt_token = jwt.encode(payload_origin, jwt_pri_key, alg='RS256', optional_headers={'ent': 'esign'})
print('token:', jwt_token)

# # 事先准备好经过rsa私钥加签过的jwt token
# jwt_token = 'eyJhbGciOiJSUzI1NiJ9.eyJvcGVyYXRpb25Vc2VySWQiOiJlZTgzMjYyYThkNGIxMWU3YTdiMzZjOTJiZjMxNjA3YiIsInBob25lIjoiMTU3NTcxNjA1MzEiLCJsb2dpbk5hbWUiOiIxNTc1NzE2MDUzMSIsIm5hbWUiOiLmtYvor5XmlLkxIiwiZXhwIjoxNTg3NzA5OTY3LCJyb2xlTmFtZXMiOiJjY-i_kOiQpeS6uuWRmCzku5PnrqHlkZgs5ZWG5ZOB566h55CG5ZGYLOacuuaehOi0n-i0o-S6uizmtYvor5XlkZgs57O757uf566h55CG5ZGYLOiuouWNleeuoeeQhizotYTmlpnnrqHnkIblkZgifQ.Ugzrowz1TD38IK5yuHAxoCURGxByBm0Ep9JtvitijhFw3MGqooaRDxKIOUk6aAFVuV6zfpY7y23oCk3-KsBvVR1oVLIAWSxiRJlVs-sne2vTEplH2xuzQv2N1HuAGvrbYlhMu2rIqitP7D5xQjVruBTmalO9TZUgsc8ONIMBZH4'
# print('token:', jwt_token)
# # 将事先准备好的公钥标准化
# rsa_public_key_str = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC84nyOnK4BGDuk/EsKNxgTjoeLqSmHWR++H0VgLdfk+as8tuBLD0HSv42wYWfBi+ICqwo+ylHFD9TM6Xx2J2ojxO6uHirCgmsdD9WzCAqannNU3YuNjFYBJI+b7N23IaAfB4ZRQKr4h0ZO2f4ruW8JUUSbMZunhtBTErurRfqK7QIDAQAB'
# if isinstance(rsa_public_key_str, str):
#     rsa_public_key = rsa_public_key_str.encode()
# if not rsa_public_key.startswith(b'-'):
#     rsa_public_key = b'-----BEGIN PUBLIC KEY-----\n' + rsa_public_key + b'\n-----END PUBLIC KEY-----'

print('-----------base64解密jwt中的header和payload--------------')
# 知识点:jwt token分为三个部分,用.分隔:header, payload, signature
jwt_token_parts = jwt_token.split('.')
header = jwt_token_parts[0]
payload = jwt_token_parts[1]
signature = jwt_token_parts[2]
print('header:', header)
print('payload:', payload)
print('sign:', signature)

'''
知识点:jwt三个部分其实都是base64加密的字符串,并且是urlsafe的base64加密字符串
知识点:什么是urlsafe的base64?标准的Base64并不适合直接放在URL里传输,因为URL编码器会把标准Base64中的“/”和“+”字符变为形如“%XX”的形式,而这些“%”号在存入数据库时还需要再进行转换,因为ANSI SQL中已将“%”号用作通配符。
为解决此问题,可采用一种用于URL的改进Base64编码,它去除了在末尾填充'='号,并将标准Base64中的“+”和“/”分别改成了“-”和“_”,这样就免去了在URL编解码和数据库存储时所要作的转换,避免了编码信息长度在此过程中的增加,并统一了数据库、表单等处对象标识符的格式。
如果要解密urlsafe的base64加密字符串,可以用python系统lib已经封装好的urlsafe_b64decode方法,当然我们也可以先转成标准的base64,再decode
'''

# python中有urlsafe_b64decode方法,里面封装了对从-到+,从_到/的转换
# jwt中把=给trim了,需要重新补回来,否则base64解码时会报错incorrect padding
header_padded = header + '=' * (4 - len(header) % 4)
payload_padded = payload + '=' * (4 - len(header) % 4)
print('padded header:', header_padded)
print('padded payload:', payload_padded)

text_header = base64.urlsafe_b64decode(header_padded)
text_payload = base64.urlsafe_b64decode(payload_padded)
print('header_text:', text_header.decode('utf-8'))
print('payload_text:', text_payload.decode('utf-8'))

print('--------------自行写将urlsafe的base64字符串转化为标准base64编码------------------')
# 自行写代码将urlsafe的base64字符串转化为标准base64编码
standard_base64_str_header = header.replace('-', '+').replace('_', '/') + '=' * (4 - len(header) % 4)
print('header_std:', standard_base64_str_header)

standard_base64_str_payload = payload.replace('-', '+').replace('_', '/') + '=' * (4 - len(payload) % 4)
print('payload_std', standard_base64_str_payload)
print('--------------------------------')

print('--------------行base64解密,在不验签的情况下就可以解密出明文,所以jwt作用不是防泄密,而是防篡改-------------------')
# 进行base64解密,在不验签的情况下就可以解密出明文,所以jwt作用不是防泄密,而是防篡改
text_header = base64.b64decode(standard_base64_str_header.encode('utf-8'))
print('header_text:', text_header.decode('utf-8'))

text_payload = base64.b64decode(standard_base64_str_payload.encode('utf-8'))
print('payload_text:', text_payload.decode('utf-8'))
print('--------------------------------')

print('-----------用公钥验证jwt--------------')

print('1. 用jwt库里封装好的方法解密和验签,如果验证失败,会抛出异常')
rsa_public_key_obj = RSA.importKey(rsa_public_key)
jwt_pub_key = jwk_from_pem(rsa_public_key_obj.export_key())
jwt_pub_key = jwk_from_pem(rsa_public_key)

try:
    payload_json = jwt.decode(jwt_token, key=jwt_pub_key, do_time_check=True)
    # payload_json = jwt.decode(jwt_token, key=jwt_pub_key, do_time_check=False)
    print('验签成功:', payload_json)
except Exception as e:
    print('验签失败:', e)

print('2. 自行用RSA公钥进行验证,如果验证失败,结果是False')
from Crypto import Hash
from Crypto.Hash import SHA256
from Crypto.Signature import PKCS1_v1_5

# 用utf-8和ascii都可以,base64中没有双字节的字符,所以encode出来的都是一样的
message = '{}.{}'.format(header, payload)
print('message(header.payload):', message)
print('signature:', signature)
message_bytes = message.encode('ascii')
# signature_bytes = base64.urlsafe_b64decode(signature.encode('ascii') + b'=' * (4 - len(signature) % 4))
signature_bytes = base64.urlsafe_b64decode((signature + '=' * (4 - len(signature) % 4)).encode('ascii'))

rsa_public_key_obj = RSA.importKey(rsa_public_key)
verifier = PKCS1_v1_5.new(rsa_public_key_obj)
message_hash = Hash.SHA256.new(message_bytes)
print('message_hash hex:', message_hash.hexdigest())
verify_result = verifier.verify(message_hash, signature_bytes)
print('RSA验签结果:', verify_result)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

jwt的解密和RSA签名验证 的相关文章

  • -bash: conda: command not found

    其实是因为你没有加路径 执行一条 export PATH 61 PATH usr local miniconda2 bin 就OK啦 额 其实还不行 你要给conda加一个软链接 转换python2和3要创建虚拟环境
  • Sequence2Sequence 学习

    转载至 https blog csdn net MebiuW article details 52832847 1 前言 这个深度学习 xff0c 其实是来自每周Paper笔记的整理版 xff0c 即文章的主要内容其实是我对一篇文章的整理
  • Foreign Exchange (UVA - 10763)

    include lt iostream gt include lt bits stdc 43 43 h gt define maxn 500002 using namespace std int N1 maxn int N2 maxn in
  • 如何正确安装Microsoft Office 2019

    昨天作死 xff0c 因为Excel经常弹出一些奇奇怪怪的弹窗 xff0c 我去百度搜索 xff0c 没有找到答案 然后我发现大家都说最有效的办法是卸载了重新安装 xff0c 于是一键就卸载完了 然而 xff0c 最让我担心的事情发生了 x
  • 如何用java打印出JSON文件

    应老师要求 xff0c 需要打印出被剪枝的结点 xff0c 临时上网上查了资料 xff0c 我们需要下面的东西 xff1a 1 org json jar 下载之后把所有文件单独放在项目新建的文件夹org json下即可 2 我们需要知道两个
  • 关于apt update 的产生的一个问题

    E Release file for http mirrors 163 com ubuntu dists bionic updates InRelease is not valid yet invalid for another 1天 12
  • python在打开GBK格式的txt文件时无法用UTF-8格式读取

    如标题 xff0c 可以曲线救国 xff0c 把GBK文件转换成UTF 8文件 方法 xff1a 打开记事本 xff0c 点击另存为 xff0c 下面有编码 xff0c 选择UTF 8即可 美滋滋
  • dpkg和pip在ubuntu下查找所安装的包

    目录 原因结论 原因 这些天在弄ubuntu的时候 xff0c 想查看一些包的版本 xff0c 然后上网查了一下如何去做 一开始 xff0c 我就搜到利用下面这个语句 dpkg span class token operator span
  • Docker容器挂载本地共享文件夹

    Docker挂载本地目录的方法 Docker容器启动时 xff0c 我们可以使用 v参数来挂载主机下的一个目录 比如 xff0c 我需要启动一个ubuntu的容器 xff0c 并把 opt文件挂载在这个容器上做共享文件夹 a3551444f
  • 【论文解读 ICEIT2022】Heterogeneous Graph Based Knowledge Tracing基于异构图的知识追踪

    文章目录 摘要1 引言2 相关工作2 1 知识追踪2 2 异构图嵌入 3 基于异构图嵌入的知识追踪4 实验5 结论 依然是两阶段 摘要 最近 xff0c 随着在线辅导系统的发展 xff0c 对知识追踪 Knowledge Tracing 的
  • 【AAAI22】Interpretable Knowledge Tracing: Simple and Efficient Student Modeling with Causal Relations

    文章目录 摘要1 引言 可解释的知识追踪 xff1a 简单高效的因果关系学生建模 摘要 智能辅导系统在未来的学习环境中已变得至关重要 知识追踪是该系统的重要组成部分 它是关于推断学生的技能掌握和预测他们的表现 xff0c 以相应地调整课程
  • stm32CubeIDE 在自己工程中添加.c 和.h文件

    stm32CubeIDE发布已经有一段时间了 xff0c 网上也出现了好多使用教程 xff0c 但是大多数教程都是从软件的安装 gt 汉化 gt 改软件皮肤 gt 新建工程 gt 在工程的main 函数添加自己的测试代码 gt 设置调试配置
  • 快充芯片IP5328P的寄存器数据读写[用于DIY数显快充充电宝]

    本帖DIY因为有一定的危险性 xff0c 非专业人员请勿自行尝试 如有侵权 联系删除 IP5328P是一款最大18W的快充芯片 xff0c 主要用于快充充电宝的产品 xff0c 基本支持市面上绝大部分主流的快充协议 因为能看到本帖的想必都是
  • 使用汇编开发STM32

    使用汇编开发STM32系列文章 xff0c 会长期连载 xff0c 本文作为跳转用的目录 目录 一 说明二 系列文章跳转链接1 STM32涉及到的汇编基础知识2 STM32启动文件详解3 STM32不使用启动文件点亮一个LED灯并闪烁4 S
  • STM32F10x启动文件详解

    本文为使用汇编开发STM32系列文章之 启动文件详解篇 xff0c 全部文章目录点此跳转 本文不会像其他文章一样只是简单的说一下启动文件的每个部分是什么 xff0c 说了很多却又像没说一样 本文将对启动文件中的每句话的作用及其如此编写的原因
  • 泰克示波器TDS210更换IPS彩色屏幕

    本文将介绍如何为泰克示波器TDS210更换当前流行的IPS彩色屏幕 xff0c 甚至在以后准备将屏幕图像转换为HDMI输出 xff0c 彻底对以往的老旧屏幕说拜拜 文章如有侵权请联系我删除 目录 一 缘起1 与TDS210的相遇2 改装预想
  • debian安装小记

    debian安装小记 前段时间学习debian xff0c 发现安装的过程很是痛苦 有感于网上的资料过于古老 xff0c 或者语有不详 xff0c 所以想新起一贴 xff0c 记录一下 xff0c 以供大家参考 感谢学习过程帮助过我的人们
  • 泰克示波器TDS210改装便携示波器

    前面发布过一篇文章写了起因和屏幕更换方法 xff0c 点此查看 目录 一 改装打算二 进度 一 改装打算 1 只保留TDS210的主板 xff0c 将按键板 屏幕以及电源全部替换 xff0c 按键板自己设计绘制更紧凑的 xff0c 屏幕更换
  • matlab代码文件中function是什么

    在 MATLAB 中 xff0c function 是一个用于定义函数的关键字 通过 function 关键字 xff0c 可以在 MATLAB 代码文件中创建一个函数 xff0c 函数可以接受输入参数 xff0c 并可以返回输出结果 在
  • JAVA日期格式校验正则表达式方法,yyyy年MM月,yyyy-MM-dd格式等

    今天校验了日期格式 xff0c 故记录下 xff1b 一 校验yyyy年MM月 xff1b yyyy年MM月 或者 yyyy年M月 private static final String MONTH REGEX 61 34 1 9 d 3

随机推荐