Skip to main content

jwt工具类,支持HS256、RS256、SM3(SM3+HMAC)、SM2(SM3+SM2)、SM4(SM3+SM4)五种签名算法

Project description

JWT的签发与验证组件

1. 组件整体说明

py-jwt-helper 是一个轻量级的 JWT 工具库,封装了密钥生成、JWT 签发、验签、载荷提取以及 JWKS 构建与解析等完整流程。

核心特性:

  • 统一 Base64 密钥格式 — 对称密钥与非对称公私钥对外均以 Base64 字符串传递,内部按算法自动解析
  • 五种签名算法 — HS256、RS256、SM3(SM3+HMAC)、SM2(SM3+SM2)、SM4(SM3+SM4)
  • JWK/JWKS 标准兼容 — 支持 RFC 7517 格式的 JWKS 构建、解析与 kid 自动匹配
  • 非侵入式国密扩展 — 通过 PyJWT 的 register_algorithm() 注入国密算法,不修改 PyJWT 源码
  • FastAPI 集成 — 提供多系统签发隔离的鉴权依赖注入

2. 组件依赖加载

安装

# 基础安装
pip install py-jwt-helper

# 如需 FastAPI 集成
pip install py-jwt-helper[fastapi]

运行时依赖

依赖 版本要求 用途
PyJWT[crypto] >= 2.8.0 JWT 编解码与算法框架
cryptography >= 46.0.5 RSA 密钥生成与 PEM 解析
gmssl >= 3.2.2 国密 SM2/SM3/SM4 算法实现

国密算法注册

使用 SM2、SM3、SM4 算法前,需先注册国密扩展:

from py_jwt_helper.jwt.extensions import register_sm_crypto_algorithms

register_sm_crypto_algorithms()

建议在应用启动时调用一次即可。

导入

from py_jwt_helper import JwtHelper, JwtPayload, JwkHelper, JwkKeyEntry

3. 核心接口功能说明

3.1. 算法支持与加签逻辑

3.1.1. 支持的算法说明

算法 类型 密钥长度 签名方式 JWK kty
HS256 对称 32 字节 HMAC-SHA256(key, msg) oct
SM3 对称 32 字节 HMAC-SM3(key, msg),与 HS256 结构相同 oct
SM4 对称 16 字节 SM4-CBC 加密取最后分组作 MAC oct
RS256 非对称 2048 位 RSASSA-PKCS1-v1_5,SHA-256哈希 + RSA私钥签名 RSA
SM2 非对称 私钥 32 字节 / 公钥 64 字节 SM3哈希 + SM2椭圆曲线签名 EC (crv=SM2)
  • 对称算法:加签与验签使用同一密钥
  • 非对称算法:私钥加签,公钥验签;SM2 由于内部 prepare_key 兼容,私钥也可用于验签

3.1.2. 生成各算法的密钥的接口和结果说明

JwtHelper.generate_key_or_keypair(alg)

根据算法名生成密钥,统一返回 Base64 编码格式。

参数:

参数 类型 说明
alg str 算法名称,支持 HS256SM3SM4RS256SM2

返回值:

  • 对称算法(HS256 / SM3 / SM4):返回 str — Base64 编码的密钥字符串
  • 非对称算法(RS256 / SM2):返回 Dict[str, str],结构为:
{
    "private_key": "Base64编码的私钥",
    "public_key":  "Base64编码的公钥"
}

调用示例:

from py_jwt_helper import JwtHelper
from py_jwt_helper.jwt.extensions import register_sm_crypto_algorithms

register_sm_crypto_algorithms()

## 对称算法 — 返回单个 Base64 字符串
hs256_key = JwtHelper.generate_key_or_keypair("HS256")
## 例: "KU49TG81ii+VKtP2WV4/jaZGh4AOvyW5WUXcxnvsqMs="

sm3_key = JwtHelper.generate_key_or_keypair("SM3")
sm4_key = JwtHelper.generate_key_or_keypair("SM4")

# 非对称算法 — 返回 dict
rsa_keys = JwtHelper.generate_key_or_keypair("RS256")
# 例: {"private_key": "LS0tLS1CRUdJTi...", "public_key": "LS0tLS1CRUdJTi..."}

sm2_keys = JwtHelper.generate_key_or_keypair("SM2")
# 例: {"private_key": "IesuWFlC5RgjS7IX...", "public_key": "BHzn7neIZZX6t3VA..."}
JwtHelper.get_public_key_from_private(secret_key, alg)

基于非对称算法的私钥推导其对应的公钥。

参数:

参数 类型 说明
secret_key str Base64 编码的私钥字符串
alg str 算法类型,仅支持 RS256SM2

返回值: str — Base64 编码的公钥字符串

调用示例:

sm2_keys = JwtHelper.generate_key_or_keypair("SM2")
pub_key = JwtHelper.get_public_key_from_private(sm2_keys["private_key"], "SM2")
assert pub_key == sm2_keys["public_key"]

3.1.3. 基于各算法生成 JWT 的接口说明

JwtHelper.create_jwt(secret_key, sub, expire_second, ...)

创建一个完整的 JWT 字符串。

参数:

参数 类型 必填 说明
secret_key str Base64 编码的密钥。对称算法为共享密钥;非对称算法为私钥
sub str JWT 主题内容或标识,通常存放业务数据
expire_second int 有效期(秒)。负值可生成已过期的 token 用于测试
iss str 签发者身份标识
before_second int 延迟生效时间(秒),生成 nbf 声明。必须小于 expire_second
alg str 签名算法,默认 "RS256"
kid str 密钥 ID,写入 JWT Header,用于 JWKS 场景中按 kid 匹配验签密钥

返回值: str — 编码后的 JWT 字符串

调用示例:

from py_jwt_helper import JwtHelper

# 对称算法签名
key = JwtHelper.generate_key_or_keypair("HS256")
token = JwtHelper.create_jwt(
    secret_key=key,
    sub="user_001",
    expire_second=3600,
    iss="my_service",
    alg="HS256",
    kid="hs256-key-1"
)

# 非对称算法签名(私钥签发)
rsa_keys = JwtHelper.generate_key_or_keypair("RS256")
token = JwtHelper.create_jwt(
    secret_key=rsa_keys["private_key"],
    sub="user_002",
    expire_second=1800,
    iss="auth_server",
    alg="RS256",
    kid="rsa-key-1"
)

# sub 中存放 JSON 业务数据
import json
payload_data = {"providerId": "hr", "id": "00001", "name": "张三"}
token = JwtHelper.create_jwt(
    secret_key=rsa_keys["private_key"],
    sub=json.dumps(payload_data, ensure_ascii=False),
    expire_second=86400 * 30,
    alg="RS256"
)

3.2. 验签相关逻辑

3.2.1. 多密钥/公钥 + kid 生成 JWKS 信息说明

JwkKeyEntry — JWKS 构建入参实体
字段 类型 说明
alg str 算法名称(HS256 / SM3 / SM4 / RS256 / SM2)
kid str 密钥 ID,用于在 JWKS 中唯一标识该密钥
key str Base64 编码的验签密钥。对称算法为共享密钥,非对称算法为公钥
JwkHelper.build_jwks(keys)

根据传入的验签密钥列表构建标准的 JWKS(JSON Web Key Set)结构。

参数:

参数 类型 说明
keys List[JwkKeyEntry] JwkKeyEntry 列表

返回值: Dict — 标准 JWKS 结构

{
    "keys": [
        {
            "alg": "HS256",
            "kid": "hs256-1",
            "use": "sig",
            "kty": "oct",
            "k": "<Base64Url 编码的对称密钥>"
        },
        {
            "alg": "RS256",
            "kid": "rsa-1",
            "use": "sig",
            "kty": "RSA",
            "n": "<Base64Url 编码的模数>",
            "e": "<Base64Url 编码的指数>"
        },
        {
            "alg": "SM2",
            "kid": "sm2-1",
            "use": "sig",
            "kty": "EC",
            "crv": "SM2",
            "x": "<Base64Url 编码的 X 坐标>",
            "y": "<Base64Url 编码的 Y 坐标>"
        }
    ]
}

调用示例:

from py_jwt_helper import JwtHelper, JwkHelper, JwkKeyEntry

# 生成各算法密钥
hs256_key = JwtHelper.generate_key_or_keypair("HS256")
sm3_key = JwtHelper.generate_key_or_keypair("SM3")
rsa_keys = JwtHelper.generate_key_or_keypair("RS256")
sm2_keys = JwtHelper.generate_key_or_keypair("SM2")

# 构建入参列表(非对称算法使用公钥)
entries = [
    JwkKeyEntry(alg="HS256", kid="hs256-1", key=hs256_key),
    JwkKeyEntry(alg="SM3", kid="sm3-1", key=sm3_key),
    JwkKeyEntry(alg="RS256", kid="rsa-1", key=rsa_keys["public_key"]),
    JwkKeyEntry(alg="SM2", kid="sm2-1", key=sm2_keys["public_key"]),
]

jwks = JwkHelper.build_jwks(entries)
# jwks 可直接作为 JSON 响应暴露到 /.well-known/jwks.json 端点

3.2.2. 基于带有 kid 的 JWT 或 JWKS 中匹配验签密钥/公钥的说明

JwkHelper.get_key_from_jwk(jwk)

从单个 JWK 字典中提取验签密钥。

参数:

参数 类型 说明
jwk Dict 单个 JWK 字典(非 JWKS,需从 jwks["keys"][i] 获取)

返回值: str — Base64 编码的验签密钥字符串

JwkHelper.resolve_key_from_jwks(jwks, token)

根据 JWT Header 中的 kid 从 JWKS 中自动匹配对应的 JWK,并提取验签密钥。

参数:

参数 类型 说明
jwks Dict 标准 JWKS 字典 {"keys": [...]}
token str JWT 字符串(Header 中需包含 kid

返回值: str — Base64 编码的验签密钥字符串

调用示例:

from py_jwt_helper import JwtHelper, JwkHelper, JwkKeyEntry

# 1. 构建多密钥 JWKS
rsa_keys = JwtHelper.generate_key_or_keypair("RS256")
sm2_keys = JwtHelper.generate_key_or_keypair("SM2")

entries = [
    JwkKeyEntry(alg="RS256", kid="rsa-1", key=rsa_keys["public_key"]),
    JwkKeyEntry(alg="SM2", kid="sm2-1", key=sm2_keys["public_key"]),
]
jwks = JwkHelper.build_jwks(entries)

# 2. 用私钥签发带 kid 的 JWT
token = JwtHelper.create_jwt(
    secret_key=rsa_keys["private_key"],
    sub="user_001",
    expire_second=3600,
    alg="RS256",
    kid="rsa-1"
)

# 3. 根据 token 中的 kid 自动匹配并提取验签密钥
resolved_key = JwkHelper.resolve_key_from_jwks(jwks, token)
# resolved_key 将匹配 kid="rsa-1" 对应的公钥

# 4. 验签
payload = JwtHelper.verify_jwt(token, resolved_key)

3.2.3. JWT 验签和 Payload 信息获取的结构说明

JwtHelper.verify_jwt(token, secret_key)

校验 JWT 的签名有效性、过期时间、生效时间等。校验失败会抛出 jwt.exceptions.PyJWTError 的相关子类。

参数:

参数 类型 说明
token str JWT 字符串
secret_key str Base64 编码的验签密钥。对称算法为共享密钥;非对称算法为公钥

返回值: JwtPayload — 载荷实体对象

可能抛出的异常:

异常类 说明
jwt.exceptions.DecodeError token 格式错误或 Header 缺少算法
jwt.exceptions.ExpiredSignatureError token 已过期
jwt.exceptions.ImmatureSignatureError token 尚未生效(nbf)
jwt.exceptions.InvalidSignatureError 签名不匹配
JwtHelper.extract_payload(token)

忽略签名,仅提取 JWT 的 Payload 部分(适用于不需要验签的调试场景)。

参数:

参数 类型 说明
token str JWT 字符串

返回值: JwtPayload — 载荷实体对象

JwtPayload — 载荷实体

继承自 dict,可直接作为字典使用,同时提供以下便捷属性:

属性 类型 说明
exp_time datetime | None 过期时间(UTC),对应 exp 声明
iat_time datetime | None 签发时间(UTC),对应 iat 声明
nbf_time datetime | None 生效时间(UTC),对应 nbf 声明
iss str | None 签发者,对应 iss 声明
sub str | None 主题内容,对应 sub 声明

所有标准 JWT 声明及自定义字段均可通过字典访问,如 payload["sub"]payload.get("custom_field")

调用示例:

from py_jwt_helper import JwtHelper

# 验签并获取 payload
try:
    payload = JwtHelper.verify_jwt(token, public_key)
    print(payload.sub)           ## "user_001"
    print(payload.iss)           ## "auth_server"
    print(payload.exp_time)      ## datetime(2026, 5, 26, 12, 0, 0, tzinfo=UTC)
    print(payload.iat_time)      ## datetime(2026, 5, 25, 12, 0, 0, tzinfo=UTC)
    print(payload["sub"])        ## 字典方式访问,等价于 payload.sub
except jwt.exceptions.ExpiredSignatureError:
    print("Token 已过期")
except jwt.exceptions.InvalidSignatureError:
    print("签名无效")

# 仅提取 payload(不验签)
payload = JwtHelper.extract_payload(token)
print(payload.sub)

完整端到端示例:

from py_jwt_helper import JwtHelper, JwkHelper, JwkKeyEntry
from py_jwt_helper.jwt.extensions import register_sm_crypto_algorithms

register_sm_crypto_algorithms()

# 1. 生成密钥
rsa_keys = JwtHelper.generate_key_or_keypair("RS256")

# 2. 构建入参并生成 JWKS
entries = [JwkKeyEntry(alg="RS256", kid="rsa-1", key=rsa_keys["public_key"])]
jwks = JwkHelper.build_jwks(entries)

# 3. 签发 JWT
token = JwtHelper.create_jwt(
    secret_key=rsa_keys["private_key"],
    sub="user_001",
    expire_second=3600,
    iss="auth_server",
    alg="RS256",
    kid="rsa-1"
)

# 4. 从 JWKS 中自动匹配密钥并验签
resolved_key = JwkHelper.resolve_key_from_jwks(jwks, token)
payload = JwtHelper.verify_jwt(token, resolved_key)
print(f"用户: {payload.sub}, 签发者: {payload.iss}, 过期: {payload.exp_time}")

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

py_jwt_helper-0.1.2.tar.gz (12.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

py_jwt_helper-0.1.2-py3-none-any.whl (16.5 kB view details)

Uploaded Python 3

File details

Details for the file py_jwt_helper-0.1.2.tar.gz.

File metadata

  • Download URL: py_jwt_helper-0.1.2.tar.gz
  • Upload date:
  • Size: 12.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.8.8

File hashes

Hashes for py_jwt_helper-0.1.2.tar.gz
Algorithm Hash digest
SHA256 5fc3594deaf6ec0a7f9f0fedc1c5950cd7cf26459a56d537533b348767d59bf0
MD5 33d16aaaa343daf54c99041e867535a2
BLAKE2b-256 bb0cb946dfd95933366402174d86ce1873af2365f72aeee8a7118a15e1ec2a27

See more details on using hashes here.

File details

Details for the file py_jwt_helper-0.1.2-py3-none-any.whl.

File metadata

File hashes

Hashes for py_jwt_helper-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 ddc9fb8a68b1e5c304740f2a03843a57aa8203ce8d89bf2a71f198acbcccb364
MD5 5f8b6ccfa31259dee0d069979246cf54
BLAKE2b-256 a073632b2df925f25b294134f328e6bcde9fae23c62b36eefa78e7a712fee97e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page