Tink Python JWT 签名示例实战:密钥生成、Token 签发与 JWK Set 验证全流程

发布时间:2026/9/22 11:35:39

Tink Python JWT 签名示例实战:密钥生成、Token 签发与 JWK Set 验证全流程 密码学【免费下载链接】tinkTink is a multi-language, cross-platform, open source library that provides cryptographic APIs that are secure, easy to use correctly, and hard(er) to misuse.项目地址https://gitcode.com/gh_mirrors/tink1/tink点击查看免费下载本文围绕仓库中 python/examples/jwt 目录下的官方示例系统讲解如何在 Tink 中生成与验证 JSON Web TokenJWT从tinkey创建测试密钥、Bazel 构建三个命令行工具到使用私钥签发 Token、将公钥导出为 JWK Set、再以 JWK Set 完成跨系统验证。读完本文你将掌握 Tink 的加载密钥材料 → 获取 primitive → 使用 primitive 执行密码学操作这一标准三步用法并能直接复现一套完整的 JWT 签名与验证流程。示例概览一次演示 Tink 的标准使用方式该示例的核心意图正如其文档所述展示如何用 Tink 生成和验证 JWT同时演示使用 Tink 的基本步骤——加载密钥材料、获取 primitive、用 primitive 做密码学操作。目录下共包含三个可执行工具对应 BUILD.bazel 中的三个py_binarytarget工具职责输入输出jwt_sign_cli使用私钥 keyset 签发 JWT Token私钥 keyset、audience写入 Token 文本文件jwt_generate_public_jwk_set将公钥 keyset 转换为 JWK Set 格式公钥 keysetTink JSON 格式JWK Set JSON 文件jwt_verify_cli使用 JWK Set 格式的公钥验证 Token公钥 JWK Set、audience、Token 文件验证结果成功/失败退出码配套资源还包括一对测试密钥 jwt_test_private_keyset.json 与 jwt_test_public_keyset.json以及覆盖正反用例的端到端测试脚本 jwt_signature_test.sh。第一步用 tinkey 生成测试密钥材料示例附带的密钥由 Tink 的密钥管理工具tinkey仓库中对应实现位于 tools/tinkey生成原文给出的完整命令如下$ tinkey create-keyset --key-template JWT_ES256 --out-format JSON \ --out jwt_test_private_keyset.json $ tinkey create-public-keyset --in jwt_test_private_keyset.json \ --in-format JSON --out jwt_test_public_keyset.json --out-format JSON第一条命令以JWT_ES256模板生成私钥 keyset第二条命令从私钥 keyset 派生出公钥 keyset。从模板命名可以看出密钥类型是 ECDSA 签名的 P-256 曲线 SHA-256 哈希对应 JWT 头中的alg: ES256。打开生成的 jwt_test_private_keyset.json可以看到 Tink JSON keyset 的典型结构{ primaryKeyId: 1742360595, key: [ { keyData: { typeUrl: type.googleapis.com/google.crypto.tink.JwtEcdsaPrivateKey, value: GiBgVYdAPg3Fa2FVFymGDYrI1trHMzVjhVNEMpIxG7t0HRJGIiBeoDMF9LS5BDCh6YgqE3DjHwWwnEKEI3WpPf8izEx1rRogbjQTXrTcw/1HKiiZm2Hqv41w7Vd44M9koyY/VsPSAQAQ, keyMaterialType: ASYMMETRIC_PRIVATE }, status: ENABLED, keyId: 1742360595, outputPrefixType: TINK } ] }各字段含义primaryKeyId标识当前主密钥keyData.typeUrl指向协议定义的JwtEcdsaPrivateKey类型keyMaterialType为ASYMMETRIC_PRIVATEstatus为ENABLEDoutputPrefixType为TINK表示输出 Token 时携带 Tink 前缀用于定位密钥。对应的公钥 keyset 结构相同仅typeUrl变为JwtEcdsaPublicKey、keyMaterialType变为ASYMMETRIC_PUBLIC。重要Tink JSON keyset 与 JWK Set 是两种不兼容的格式文档特别强调上述 keyset 使用 Tink 的 JSON keyset 格式它与 JSON Web Key setJWK Set格式完全不同、互不兼容。Tink JSON keyset 描述的是 Tink 内部的密钥状态机keyData、status、outputPrefixType等而 JWK Set 是 RFC 7517 定义的开放标准格式供非 Tink 生态的系统共享公钥使用。因此直接用 Tink 公钥 keyset 给其他系统做 JWT 验证是不行的必须先完成格式转换见第四步。第二步Bazel 构建示例在仓库的python/examples目录下执行$ bazel build ...构建产物位于bazel-bin下。从 BUILD.bazel 可见三个工具均声明为py_binary依赖absl-py、tink_py//tink:tink_python与tink_py//tink/jwt其中jwt_sign_cli额外依赖tink_py//tink:secret_key_access因为签发需要接触私钥明文。此外还定义了两个sh_testjwt_signature_test与jwt_signature_test_package后者针对pip3 install安装的 Tink 包运行分别将三个 CLI 与两个 keyset 文件作为参数传给 jwt_signature_test.sh。第三步签发 JWTjwt_sign_cli 源码解析生成一个使用私钥 keyset 签名的 JWT Token$ touch token_file.txt $ ./bazel-bin/jwt/jwt_sign_cli \ --private_keyset_path ./jwt/jwt_test_private_keyset.json \ --audience audience --token_path token_file.txt运行成功后Token 被写入token_file.txt。其核心实现 jwt_sign_cli.py 完整体现了 Tink 的标准三步用法# 1. 初始化 Tink注册 JWT 签名所需的 key manager 与 wrapper jwt.register_jwt_signature() # 2. 加载密钥材料读取明文 keyset示例演示用途生产环境不推荐 with open(_PRIVATE_KEYSET_PATH.value, rt) as keyset_file: text keyset_file.read() keyset_handle tink.json_proto_keyset_format.parse( text, secret_key_access.TOKEN) now datetime.datetime.now(tzdatetime.timezone.utc) # 3. 获取 primitive 并使用 jwt_sign keyset_handle.primitive(jwt.JwtPublicKeySign) raw_jwt jwt.new_raw_jwt( audiences[_AUDIENCE.value], expirationnow datetime.timedelta(seconds100)) token jwt_sign.sign_and_encode(raw_jwt)流程要点初始化jwt.register_jwt_signature()注册签名类 key manager 与 wrapper。从 python/tink/jwt/init.py 看它内部调用_jwt_signature_key_manager.register()与_jwt_signature_wrappers.register()对称 MAC 场景则对应register_jwt_mac()。加载密钥tink.json_proto_keyset_format.parse(text, secret_key_access.TOKEN)将 JSON 文本解析为KeysetHandle。签发需要私钥因此必须显式传入secret_key_access.TOKEN即秘密密钥访问令牌这是 Tink 强制开发者显式声明访问敏感材料的安全设计。任何tink.TinkError都会被捕获并记录日志。构造 RawJwtjwt.new_raw_jwt(audiences[...], expiration...)只负责载荷claims与部分头部不含alg、kid等依赖密钥的头部——这些由签名时自动选择从而保证更换密钥无需改动业务代码。从 python/tink/jwt/_raw_jwt.py 的实现看iss、sub、jti必须是字符串exp、nbf、iat必须是数值且落在[0, 253402300799]即 9999 年 12 月 31 日范围内aud必须是字符串或非空字符串列表。签名jwt_sign.sign_and_encode(raw_jwt)完成签名与编码返回紧凑序列化的 JWT 字符串。示例中过期时间设为当前 UTC 时间后 100 秒。第四步将公钥 keyset 导出为 JWK Set文档指出把公钥 keyset 转成 JWK Set 格式对与不使用 Tink 的一方共享公钥非常有用并且该功能在 Tink v1.7.0 之后才加入。原文命令如下$ touch public_jwk_set.json $ ./bazel-bin/jwt/jwt_generate_public_jwk_set \ --public_keyset_path ./jwt/jwt_test_private_keyset.json \ --public_jwk_set_path public_jwk_set.json注意该工具期望传入的是公钥 keyset。在 jwt_signature_test.sh 中对应的正式调用传入的是jwt_test_public_keyset.json即应使用tinkey create-public-keyset导出的公钥文件方为规范用法。核心实现 jwt_generate_public_jwk_set.py 只有两步# 读取公钥 keyset不涉及秘密材料无需 secret_key_access public_keyset_handle tink.json_proto_keyset_format.parse_without_secret(text) # 导出为 JWK Set 字符串 public_jwk_set jwt.jwk_set_from_public_keyset_handle(public_keyset_handle) with open(_PUBLIC_JWK_SET_PATH.value, wt) as public_jwk_set_file: public_jwk_set_file.write(public_jwk_set)与签发工具的关键差异在于这里使用parse_without_secret公钥非机密无需访问令牌并通过jwt.jwk_set_from_public_keyset_handle完成格式转换。该函数在 python/tink/jwt/init.py 中映射到_jwk_set_converter.from_public_keyset_handle实现底层由 python/tink/jwt/_jwk_set_converter.py 承担 RFC 7517 格式的序列化。第五步用 JWK Set 公钥验证 Token使用 JWK Set 格式的公钥验证此前签发的 Token$ ./bazel-bin/jwt/jwt_verify_cli \ --public_jwk_set_path public_jwk_set.json \ --audience audience --token_path token_file.txt验证逻辑位于 jwt_verify_cli.py# 从 JWK Set 文本还原为 Tink 公钥 KeysetHandle格式反向转换 keyset_handle jwt.jwk_set_to_public_keyset_handle(text) jwt_verify keyset_handle.primitive(jwt.JwtPublicKeyVerify) # 构造验证器声明期望的 audience验证时强制执行 validator jwt.new_validator(expected_audience_AUDIENCE.value) verified_jwt jwt_verify.verify_and_decode(token, validator) expires_in verified_jwt.expiration() - now logging.info(Token is valid and expires in %s seconds, expires_in.seconds)验证过程有三个强制检查点签名必须与公钥匹配、audience 必须等于验证器声明值、Token 未过期。jwt.jwk_set_to_public_keyset_handle是第四步jwk_set_from_public_keyset_handle的逆操作底层由_jwk_set_converter.to_public_keyset_handle实现。验证成功返回退出码 0 并输出剩余有效期任何失败签名不合法、audience 不符、过期等都会抛tink.TinkError被捕获后返回退出码 1。端到端测试正反用例全覆盖BUILD.bazel 中的sh_test将三个 CLI 与密钥文件打包成一条完整测试链路。脚本 jwt_signature_test.sh 依次验证了五个场景generate_token用私钥 keyset 签发 Token预期成功generate_public_jwk_set从公钥 keyset 生成 JWK Set预期成功verification_with_public_jwt_set用 JWK Set 验证合法 Token预期成功verification_fails_with_invalid_token篡改 Token写入ABCABCABCD后验证预期失败verification_fails_with_incorrect_audience将 audience 换成invalid audience后验证预期失败generating_token_fails_with_invalid_keyset用公钥 JWK Set 冒充私钥 keyset 签发预期失败私钥缺失无法签名verify_fails_with_a_invalid_keyset把私钥 keyset 当作公钥 JWK Set 传入验证预期失败格式不兼容。这组用例恰好印证了前文的两个关键论断签发必须持有私钥、Tink JSON keyset 与 JWK Set 格式不可混用。在仓库中执行bazel test //jwt:jwt_signature_test即可一键复现全部场景。扩展Python Tink JWT 模块 API 一览除示例使用的 API 外python/tink/jwt/init.py 还导出了完整的 JWT 能力面注册register_jwt_signature()非对称签名与register_jwt_mac()对称 MAC对象RawJwt、VerifiedJwt、JwtValidator、JwtInvalidError构造new_raw_jwt(...)与new_validator(...)格式互转jwk_set_from_public_keyset_handle/jwk_set_to_public_keyset_handlejwk_set_from_keyset_handle、jwk_set_to_keyset_handle为已弃用的旧名称密钥模板覆盖对称jwt_hs256_template、jwt_hs384_template、jwt_hs512_template与非对称jwt_es256_template、jwt_es384_template、jwt_es512_template、jwt_rs256_2048_f4_template、jwt_ps256_2048_f4_template等两大类后缀数字表示 RSA 密钥位数raw_前缀版本表示不含固定头部。示例中JWT_ES256模板即对应jwt_es256_template。安全提示与最佳实践示例中的三个 CLI 均为演示用途直接以明文cleartext方式从磁盘读取私钥 keyset脚本注释明确写着this is not recommended!。生产环境应改用 KMS 加密的密钥仓库中 integration/gcpkms、integration/awskms 提供了对接实现或通过tink.KmsClient解封后使用。验证端应始终通过new_validator声明expected_audience并设置合理的过期策略避免签名有效但受众不符或过期 Token 仍被接受两类风险。与第三方系统共享公钥时务必使用JWK Set 格式导出v1.7.0而非 Tink 私有 keyset 格式反之将外部 JWK Set 接入 Tink 验证链路时需先经jwk_set_to_public_keyset_handle转换。签发与验证两侧的 audience 必须一致密钥模板的算法族ECDSA/RSA-PSS/HMAC需与对端支持能力匹配否则会像测试脚本展示的那样在验证阶段直接失败。赞分享密码学【免费下载链接】tinkTink is a multi-language, cross-platform, open source library that provides cryptographic APIs that are secure, easy to use correctly, and hard(er) to misuse.项目地址https://gitcode.com/gh_mirrors/tink1/tink点击查看免费下载相关推荐Tink Java JWT 签名示例实战从密钥生成到签发与验证Tink Java JWT 签名示例实战从密钥生成到签发与验证 本指南以 Tink 官方 Java JWT 签名示例 java_src/examples/j密码学atproto/jwk 全解析AT Protocol 中 JWK/JWK Set 校验与 JWT 签名验签库的版本演进与源码实现atproto/jwk 全解析AT Protocol 中 JWK/JWK Set 校验与 JWT 签名验签库的版本演进与源码实现 atproto/jwk后端社交Fleet 许可证License密钥生成完全指南ES256 签名的 JWT 密钥原理与实战Fleet 许可证License密钥生成完全指南ES256 签名的 JWT 密钥原理与实战 Fleet 是开源的设备管理平台open device ma后端前端企业应用运维网络安全上一篇5 分钟跑通 OpenProject目录、启动与配置一次讲清下一篇Complete Python 3 Bootcamp架构演进模块化课程体系与教学优化技术路线创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/9/22 11:35:39

4k视频播放器实战:解决API变动痛点与最佳实践

4k视频播放器实战:解决API变动痛点与最佳实践 最近接手一个老项目升级,刚把依赖库从 1.0 版本升到 2.0,结果整个播放核心模块直接崩了。控制台疯狂报错, play() 方法失效,事件监听全部断连。这种 版本升级后 API 全变了…

2026/9/22 11:30:37

3步拆解杭州轻轨2026最新考点,告别StackTrace报错

3步拆解杭州轻轨2026最新考点,告别StackTrace报错 屏幕一片红字,StackTrace 堆叠得像乱麻,看着就头晕。 很多老铁还在死磕文档,其实你缺的是 杭州轻轨 项目背后的底层逻辑。 别慌,这篇 2026最新…

2026/9/22 11:30:37

3步搞懂js返回上一个页面,面试必问避坑指南

3步搞懂js返回上一个页面,面试必问避坑指南 配置环境就卡半天?别急,很多老手在写个简单的“返回上一页”功能时,都可能在 history.back() 和 history.go(-1) 之间纠结半天,甚至被跨域、SEO…

2026/9/22 12:25:43

低压无刷水泵驱动芯片选型指南:FOC控制与EMC设计关键要点

1. 低压无刷水泵驱动芯片选型这件事,到底难在哪干了十几年电机驱动方案,我见过太多整机厂在选型阶段踩坑。一个低压无刷水泵项目,硬件工程师拍脑袋选了颗驱动芯片,结果样机跑到第三版才发现EMC过不了、FOC算法跑不动、低速启动抖得…

2026/9/22 12:25:43

3天搞定office2003绿色版下载源码剖析面试必问

3天搞定office2003绿色版下载源码剖析面试必问 配置环境就卡半天,这大概是每个后端开发者都经历过的至暗时刻。你以为是网络问题,重启路由器;以为是权限问题,右键以管理员运行。折腾了半小时,软件依然打不开。更让人崩溃的是,当面试官甩出一…

2026/9/22 12:25:43

面试必问耳机l底层逻辑,3招破解项目难题

面试必问耳机l底层逻辑,3招破解项目难题 看了一堆教程还是不会写项目?别慌,这不是你的错。很多刚入门的朋友,明明背熟了语法,一上手真实业务就抓瞎。更扎心的是,面试官最爱问的【面试必问】细节,往往就藏在你忽略的底层机制里。…

2026/9/22 12:25:43

搞定继电器控制电路:3个高频面试题帮你避坑

搞定继电器控制电路:3个高频面试题帮你避坑 刚学完编程语法,脑子热乎得很,觉得写几个 if-else 就能去搞项目了。结果一接触实际业务,比如给工地上的设备写个自动开关逻辑,直接懵圈。…

2026/9/22 12:20:43

戴的笔顺图解原理:3步搞定从零到上线

戴的笔顺图解原理:3步搞定从零到上线 看了一堆教程还是不会写项目?这是很多初学者最大的痛点。别慌,今天咱们不玩虚的,直接上手。很多新手卡在“戴的笔顺”这种看似简单却极易出错的细节上,导致代码逻辑混乱,最后项目跑不起来。其实,只要搞懂背后的图…

2026/9/22 10:02:42

GAMP 5 基于风险的计算机化系统验证:软件分类与审计追踪实践

简介:《A Risk-Based Approach to Compliant GxP Computerized Systems》即业内熟知的GAMP 5指南,面向制药企业质量与IT合规人员、验证工程师及计算机化系统管理者,用于解决GxP法规环境下系统合规性难以科学落地的问题。文档以风险管理为主线…

2026/9/22 9:07:39

安全托管MSSP实战:从静态防御到人机协同的攻防运营与应急响应

简介:这份PPT围绕互联网业务安全托管服务展开,面向企业安全负责人、IT运维人员及关注MSSP/MSS选型的读者,重点回应传统安全过度依赖人工、碎片化静态防御难以对抗产业化攻击等痛点。资源共1个pptx文件,包体约30.63MB,以…

2026/9/22 0:04:49

输电线路在线监测高频面试题拆解 3秒抓住官方文档重点

输电线路在线监测高频面试题拆解 3秒抓住官方文档重点 官方文档几百页翻到头还是懵?面试问到 输电线路在线监测 的数据链路时,脑子一片空白?别慌,这种 高频面试题 我整理了10年,专门治各种“文档太长抓不住重点”的毛病。…

2026/9/22 0:04:49

中介房源管理系统重构避坑:3个关键步骤搞定API变更

中介房源管理系统重构避坑:3个关键步骤搞定API变更 版本升级后 API 全变了,这种痛只有真做过的人懂。 很多团队在接手老旧房产项目时,最崩溃的不是代码烂,而是底层框架升级后,原本熟悉的接口调用方式彻底失效。 这份 保姆级教程…

2026/9/22 0:04:49

3个坑点带你一文搞懂55gg小游戏源码

3个坑点带你一文搞懂55gg小游戏源码 盯着控制台满屏的红色报错,看着那一长串 StackTrace ,是不是脑子瞬间宕机?别急,这种时候最忌讳的就是盲目改代码。很多刚入行的前端同学,面对 55gg 小游戏这类轻量级 H5…

2026/9/20 4:54:47

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/21 18:32:12

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/21 10:29:02

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码