尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

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

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),仅供参考
返回列表