ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

基于 libwebsockets 的 JWE 加解密实战:minimal-crypto-jwe 命令行工具详解

基于 libwebsockets 的 JWE 加解密实战:minimal-crypto-jwe 命令行工具详解 人工智能AI Agent多模态语音AI 应用【免费下载链接】ten-frameworkOpen-source framework for conversational voice AI agents项目地址https://gitcode.com/TEN-framework/ten-framework点击查看免费下载本文围绕 libwebsocketslibwebsockets 以第三方依赖的形式随 ten-framework 仓库一起提供自带的minimal-crypto-jwe示例展开介绍如何用命令行完成 JWEJSON Web Encryption与 JWKJSON Web Key的加密、解密覆盖密钥生成、五种命令行选项、加密/解密的数据流模型并结合main.c源码梳理lws_jwe_encrypt/lws_jwe_auth_and_decrypt的完整调用链。读完本文你将能独立构建该工具、生成 RSA/EC/AES 密钥、加密任意明文并验证解密回读同时理解 JWE Compact Serialization 的五段式结构与 libwebsockets 的 JOSE 实现细节。示例概述一套完整的 JWE JWK 命令行工具链minimal-crypto-jwe是 libwebsockets 官方 minimal examples 中 crypto 类别下的一个示例位于仓库的 third_party/libwebsockets/minimal-examples/crypto/minimal-crypto-jwe 目录。它演示了如何使用 JWE 与 JWK 完成加密和解密最终产物是一个名为lws-crypto-jwe的命令行工具输入侧从stdin读取数据——加密时读取明文解密时读取 JWE 密文输出侧向stdout写出结果——加密时输出 JWE解密时输出明文密钥侧通过-k参数指定一个 JWK 密钥文件。该目录一共包含 4 个文件麻雀虽小、五脏俱全文件作用README.md示例的构建、使用说明与选项表main.c工具完整实现约 290 行 C 代码CMakeLists.txt构建脚本声明依赖LWS_WITH_JOSEkey-rsa-4096.private / key-rsa-4096.pub配套提供的一对 RSA-4096 公私钥 JWK配套的密钥生成工具lws-crypto-jwk位于同级目录 minimal-crypto-jwk用于生成 RSA、EC、OCT对称三类 JWK 密钥本文第 4 节会详细展开。构建一条 cmake 命令README 给出的构建方式非常直接$ cmake . make其底层要求由 CMakeLists.txt 保证它通过find_package(libwebsockets CONFIG REQUIRED)查找已安装的 libwebsockets 开发包并用require_lws_config(LWS_WITH_JOSE 1 requirements)强制要求目标库开启了 JOSE 支持。如果检测不满足requirements为假整个示例将不会编译。这意味着构建示例前你的 libwebsockets 库必须以启用LWS_WITH_JOSE的方式编译例如 cmake 配置时开启该选项构建完成后会生成可执行文件lws-crypto-jwe。在 ten-framework 仓库中libwebsockets 以third_party依赖的形式随源码提供包含完整的 include 头文件与实现因此无论是阅读源码还是重新构建都能在同一仓库内完成闭环。数据流模型stdin 进、stdout 出这个工具刻意设计成 Unix 管道风格Stdin 是输入源Stdout 是输出端而日志一律写到 stderr保证 stdout 上只有纯净的业务数据。具体语义为加密模式stdin 提供明文stdout 输出 JWE解密模式stdin 提供 JWEstdout 输出明文。这样的设计让它可以无缝接入管道$ echo -n plaintext0123456 | ./lws-crypto-jwe -k key-rsa-4096.pub -e RSA1_5 A128CBC-HS256 | ./lws-crypto-jwe -k key-rsa-4096.private即左侧工具加密后的 stdout直接成为右侧工具解密的 stdin最终把明文打印回 stdout。README 特别强调加密时-k必须传入包含公钥部分的 JWK解密时-k必须传入私钥JWK。对于非对称密钥公钥负责加密、私钥负责解密。这一约束在 main.c 中有对应实现无论加密还是解密密钥都通过同一处lws_jwk_load(jwe.jwk, p, NULL, NULL)加载解密路径最终由lws_jwe_auth_and_decrypt()完成认证与解密若传入的是公钥认证步骤自然会失败。密钥准备用 lws-crypto-jwk 生成三类 JWK示例目录内已预置了一对 RSA-4096 密钥key-rsa-4096.private/key-rsa-4096.pub可以直接上手。但实际使用中通常需要自己生成密钥README 给出了三类密钥的生成方法全部基于同目录的 JWK 工具lws-crypto-jwkRSA 非对称密钥默认类型$ lws-crypto-jwk -t RSA -b 4096 --public key-rsa-4096.pub key-rsa-4096.privateEC 椭圆曲线密钥-v指定曲线密钥位数由曲线隐含$ lws-crypto-jwk -t EC -v P-256 --public key-ecdh-p-256.pub key-ecdh-p-256.privateOCT 对称密钥AES$ lws-crypto-jwk -t OCT -b 128 key-aes-128.private这里的关键在于--public file选项工具会把完整私钥写到 stdout同时把剥离了私钥部分的公钥版本写入指定文件并且会调整key_ops与use元数据去掉需要私钥才能执行的操作例如把[sign,verify]调整为只含[verify]。对于 OCT 对称密钥公/私之分没有意义所以--public仅在kty ! LWS_GENCRYPTO_KTY_OCT时生效见 minimal-crypto-jwk/main.c。lws-crypto-jwk生成的 JWK 会按RFC 7638 规定的字典序输出各元素kty、n、e、d等字段严格排序这是某些应用的硬性要求。仓库内现成的 key-rsa-4096.pub 就是一个很好的样例其内容形如{e:AQAB,kid:my kid,kty:RSA,n:2_YjG_D1sOWJxs6cohikupHf5WJfWSFfSCrnNZ7WR7AyT...}可以看到字段按字母序排列e→kid→kty→n这正是 RFC 7638 字典序的体现。命令行选项速查README 给出的选项表如下这是该工具最核心的操作手册命令行选项含义-d loglevel十进制调试日志级别例如-d15-e cek cipher alg payload enc alg加密模式默认为解密。例如-e RSA1_5 A128CBC-HS256。解密时密文算法信息来自输入 JWE 自身-k jwk file用于加密或解密的 JWK 密钥文件-c将 JWE 输出为可换行的 C 字符串格式-f输出 flattened扁平化表示而非默认的 compact紧凑表示几个值得展开的细节-e缺省即解密工具启动时enc 0只有当命令行中出现-e时才进入加密分支main.c。所以解密时不需要也不应该指定-e算法信息完全从输入的 JWE 头部解析而来。-e的参数是两个算法第一个是 CEKContent Encryption Key内容加密密钥的密钥封装算法如RSA1_5第二个是载荷加密算法如A128CBC-HS256。两者之间必须以空格分隔main.c 用strchr(p, )拆解找不到空格会直接报错退出。-c与-f是输出格式选项-c调用format_c()把紧凑 JWE 转成适合直接嵌入 C 源码的字符串字面量对{、}、、,做转义并按每行 60 字符左右折行-f则在渲染阶段改用lws_jwe_render_flattened()输出扁平化 JSON 形式。加密实战一条命令 一段真实输出README 给出了完整的加密示例。加密 15 字节明文plaintext0123456$ echo -n plaintext0123456 | ./lws-crypto-jwe -k key-rsa-4096.private -e RSA1_5 A128CBC-HS256 [2018/12/19 16:20:25:6519] USER: LWS JWE example tool [2018/12/19 16:20:25:6749] NOTICE: Creating Vhost default (serving disabled), 1 protocols, IPv6 off eyJhbGciOiJSU0ExXzUiLCAiZW5jIjoiQTEyOENCQy1IUzI1NiJ9.ivFr7qzx-pQ4V_edbjpdvR9OwWL9KmojPE2rXQM52oLtW0BtnxZu2_ezqhsAelyIcaworgfobs3u4bslXHMFbeJJjPb5xD0fBDe64OYXZH1NpUGTMJh9Ka4CrJ2B3xhxe7EByGAuGqmluqE0Yezj7rhSw7vlr5JAwuOJ8FaGa8aZ8ldki5G5h_S2Furlbjdcw3Rrxk7mCoMHcLoqzfZtggMPwGAMFogCqcwUo7oSLbBeGaa6hpMbfSysugseWdr8TzObQKPM52k6iVAlGwRaOg_qdLMgZiYRhHA6nFKTQd7XBbNY6qAS8sPuj7Zz344tF3RSfJ0zX_telG71sOtVv5fMpeDU-eCdpOWlCBfu6J6FQfAFu6SJryM4ajGOif09CwFI5qUQ33SOfQfS_M3nqSyd6Vu5M4lsDrb5wK7_XX5gqUwvI9wicf_8WWR-CQomRF-JvEASnA2SIf8QqYfa8R2rP9q6Md4vwO4EZrtxIsMDPsH-4ZEFu7vDjyy09QfIWWsnEb8-UgpVXensgt2m_2bZ76r1VB8-0nZLMwMyEhaH2wra9vX2FWao5UkmNJ7ht300f4_V6QzMFoePpwCvsufWBW6jcQLB-frCWe6uitWaZHEB4LxmNPKzQSz4QwwTKhpF1jNn8Xh1-w1m-2h0gj-oe-S8QBwPveqhPI1p2fI.snuhUTXHNu5mJ6dEPQqg6g.yl36qC4o0GE4nrquQ2YyCg.Vf0MoT7_kUrZdCNWXhq1DQ这段输出包含两个值得注意的点前两行日志来自 stderrUSER: LWS JWE example tool、NOTICE: Creating Vhost ...它们只是 libwebsockets 上下文初始化的日志真正写进 stdout 的只有最后一行 JWE。这正是管道模式能够成立的前提。输出的 JWE 是典型的Compact Serialization由.分隔成五段其中第一段eyJhbGciOiJSU0ExXzUiLCAiZW5jIjoiQTEyOENCQy1IUzI1NiJ9经过 base64url 解码后正是 JOSE 头{alg:RSA1_5, enc:A128CBC-HS256}与-e传入的算法完全对应。解密实战直接解密与管道接力解密同样简单——不传-e把 JWE 通过 stdin 喂给工具即可$ ./lws-crypto-jwe -k key-rsa-4096.private 上面输出的 JWE plaintext0123456更优雅的用法是把加密输出直接管道给解密一次完成“加密 → 解密”的闭环验证$ echo -n plaintext0123456 | \ ./lws-crypto-jwe -k key-rsa-4096.pub -e RSA1_5 A128CBC-HS256 | \ ./lws-crypto-jwe -k key-rsa-4096.private plaintext0123456注意第二个命令没有-e参数——它进入解密分支从输入 JWE 的头部中读取算法信息再用key-rsa-4096.private完成解密最终把明文plaintext0123456打印在 stdout 上。这也再次印证了“公钥加密、私钥解密”的密钥分工。源码级原理一条完整的加解密调用链minimal-crypto-jwe的价值不仅在于“能用”更在于它把 libwebsockets 的 JOSE 相关 API 全部串了起来。下面结合 main.c 梳理两条路径。JWE Compact Serialization 的五段结构先看 lws-jwe.h 头部注释给出的权威定义BASE64URL(UTF8(JWE Protected Header)) || . || BASE64URL(JWE Encrypted Key) || . || BASE64URL(JWE Initialization Vector) || . || BASE64URL(JWE Ciphertext) || . || BASE64URL(JWE Authentication Tag)即保护头含 alg/enc→ 加密后的 CEK → 初始向量 IV → 密文 → 认证标签。对照上面示例输出五段依次为JOSE 头、RSA1_5 加密后的密钥512 字节 RSA-4096 密文、16 字节 IV、CBC 密文、HMAC 认证标签。main.c 中的解密分支用lws_jws_compact_decode(in, n, jwe.jws.map, jwe.jws.map_b64, ...) ! 5校验解出的段数必须为 5正好对应这五段结构。加密路径随机 CEK → 双算法加密 → 渲染输出main.c 的加密分支main.c做了四件事构造 JOSE 头用lws_gencrypto_jwe_alg_to_definition()与lws_gencrypto_jwe_enc_to_definition()把-e的两个算法字符串解析为枚举定义并分配LJWS_JOSE元素写入{alg:%s,enc:%s}生成随机 CEKCEK 长度由载荷加密算法的哈希/HMAC 尺寸决定——lws_gencrypto_bits_to_bytes(jwe.jose.enc_alg-keybits_fixed)然后lws_jws_randomize_element()填充LJWE_EKEY元素执行加密调用lws_jwe_encrypt()一次性完成 CEK 的密钥封装RSA1_5 等与明文的载荷加密渲染输出默认lws_jwe_render_compact()输出紧凑形式传-f则改用lws_jwe_render_flattened()传-c再叠加format_c()转成 C 字符串。lws_jwe_encrypt()的契约在 lws-jwe.h 中有定义输入 JOSE 头部信息与 JWE 各元素含指向 JWK 的指针返回 temp 的使用量出错返回 -1。main.c 还特别把明文直接指到 stdin 读入的缓冲区jwe.jws.map.buf[LJWE_CTXT] in。解密路径解析 → 认证 → 输出明文解密分支main.c同样清晰解析输入紧凑形式走lws_jws_compact_decode()校验 5 段并解出 b64 与解码映射-f扁平化形式则走lws_jwe_json_parse()认证并解密调用lws_jwe_auth_and_decrypt(jwe, ...)。按 lws-jwe.h 的注释该函数是一个高层解密 API若认证通过明文会回填到jws.map.buf[LJWE_CTXT]长度写入jws.map.len[LJWE_CTXT]输出明文把LJWE_CTXT缓冲区原样写到 stdout。LJWE_CTXT等元素枚举定义在 lws-jws.hJWE 命名空间下依次为LJWE_JOSE、LJWE_EKEY、LJWE_IV、LJWE_CTXT、LJWE_ATAG、LJWE_AAD与 Compact Serialization 的段序一一对应。多接收者与长度限制的设计意图从 lws-jwe.h 的struct lws_jwe可以看到两个值得一提的设计结构体专门保留了uint8_t cek[...]与cek_valid标志注释明确说明保留 CEK 副本是为了在“多接收者”场景下复用同一个 CEK 去执行多次密钥封装recip字段记录接收者编号各密钥元素有明确的上限宏LWS_JWE_LIMIT_RSA_KEY_BITS 4096、LWS_JWE_LIMIT_AES_KEY_BITS (512 64)RFC 3394 密钥封装额外占用 64 位、LWS_JWE_LIMIT_EC_KEY_BITS 528521 位取整到字节边界、LWS_JWE_LIMIT_HASH_BITS以及LWS_JWE_LIMIT_KEY_ELEMENT_BYTES4096/8 512 字节。main.c 在随机化 CEK 时正是以LWS_JWE_LIMIT_KEY_ELEMENT_BYTES作为元素上限。openssl 与 mbedtls 后端的互操作性README 明确给出一个工程上很重要的保证JWEs produced with openssl and mbedtls backends are completely interchangeable.即libwebsockets 在编译时可以选择 openssl 或 mbedtls 作为底层密码学后端两者在 JOSE 特性上均已实现无论用哪个后端加密产生的 JWE都可以被另一个后端解密。这意味着基于 libwebsockets 的 JWE 数据可以在不同构建配置的部署之间自由流转不必担心后端差异导致的不兼容。小结与延伸阅读minimal-crypto-jwe用不到 300 行代码完整示范了 libwebsockets JOSE 栈的“密钥生成 → 加密 → 解密”闭环密钥lws-crypto-jwk生成 RSA/EC/OCT 三类 JWK--public自动剥离私钥部分加密-e RSA1_5 A128CBC-HS256 公钥 JWK输出五段式 Compact JWE解密私钥 JWK 输入 JWElws_jwe_auth_and_decrypt()完成认证与解密管道友好stdin/stdout 数据流 stderr 日志分离天然可组合进 shell 脚本。如果你想继续深入 libwebsockets 的密码学示例家族仓库内还有一系列同级示例可以对照阅读生成/格式化任意 JWK 密钥的 minimal-crypto-jwk、JWS 签名验证的 minimal-crypto-jws、COSE 签名与密钥的 minimal-crypto-cose-sign、minimal-crypto-cose-key以及证书处理的 minimal-crypto-x509它们共同构成了 libwebsockets 在 JOSE/COSE 领域的完整参考实现。赞分享人工智能AI Agent多模态语音AI 应用【免费下载链接】ten-frameworkOpen-source framework for conversational voice AI agents项目地址https://gitcode.com/TEN-framework/ten-framework点击查看免费下载相关推荐libwebsockets 加密最小示例指南JWE / JWK / JWS / X.509 命令行实战libwebsockets 加密最小示例指南JWE / JWK / JWS / X.509 命令行实战 本文以 libwebsocketslws官方仓库中人工智能AI Agent多模态语音AI 应用libwebsockets COSE 签名与验签实战minimal-crypto-cose-sign 命令行工具全解析libwebsockets COSE 签名与验签实战minimal crypto cose sign 命令行工具全解析 本篇指南围绕 libwebsocket人工智能AI Agent多模态语音AI 应用Apache APISIX jwe-decrypt 插件实战基于 JWERFC 7516的请求头解密与安全认证Apache APISIX jwe decrypt 插件实战基于 JWERFC 7516的请求头解密与安全认证 jwe decrypt 是 Apache后端微服务云原生上一篇工具调用与函数执行LangChain4j-examples中Tool注解的深度解析下一篇Apache bRPC 社区治理指南Committer 与 PPMC 成员的发展流程全解析创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表