Rocket.Chat 内部 JWT 签名包 @rocket.chat/jwt:源码实现、License v3 签发链路与版本演进解析

发布时间:2026/9/9 23:45:54

Rocket.Chat 内部 JWT 签名包 @rocket.chat/jwt:源码实现、License v3 签发链路与版本演进解析 Rocket.Chat 内部 JWT 签名包 rocket.chat/jwt源码实现、License v3 签发链路与版本演进解析【免费下载链接】Rocket.ChatThe Secure CommsOS™ for mission-critical operations项目地址: https://gitcode.com/GitHub_Trending/ro/Rocket.Chatrocket.chat/jwt是 Rocket.Chat 单体仓库monorepo中一个私有的、仅服务端使用的轻量 JWT 工具包它基于jose封装了 RS256 非对称签名的签发、验签与测试密钥生成能力。本文以该包的 CHANGELOG.md 为主线结合 源码、单元测试 及其核心消费方 License 库Enterprise Edition 包逐一拆解读完后你既能掌握该包三个 API 的完整用法与默认参数也能理清 Enterprise 许可证如何从 v2RSA 加密对象平滑迁移到 v3JWT 签名令牌、ABAC 能力为何依赖该包以及它随仓库工具链演进的完整版本史。包定位给谁用、解决什么问题Rocket.Chat 的根目录 package.json 使用 Yarn 与 Turborepo 管理多个 workspacepackages/jwt是其中规模最小的包之一。从其 package.json 可以确认它的核心属性包名rocket.chat/jwt当前版本0.2.1标记为private: true即不发布到公共 npm registry唯一运行时依赖为jose: ^4.15.9JavaScript 平台的 JOSE 标准库负责 PKCS8/SPKI 密钥导入、JWS 签名与验证等底层密码学操作提供buildtsc 编译到dist、test/testunitjest、typecheck、lint等标准脚本直接依赖 workspace 内的rocket.chat/jest-presets与rocket.chat/tsconfig与仓库的测试与 TS 编译体系对齐。从依赖关系上看rocket.chat/jwt唯一被声明为 workspace 依赖的包是 EE 侧 License 库 —— 见 ee/packages/license/package.json 中的rocket.chat/jwt: workspace:^。这正是理解该包价值的关键Rocket.Chat Enterprise 的许可证License与统计令牌都是以 JWT 形式分发的而该包承担了令牌的签发与验签这一安全底座职责并不面向普通消息收发链路。源码剖析三个极简 API 与一组安全默认值整个包的公开实现只有约 30 行集中在 src/index.ts共导出三个异步函数。sign用 PKCS8 私钥签发 JWTexport async function sign(keyObject: object, pkcs8: string, alg RS256) { const privateKey await importPKCS8(pkcs8, alg); const token await new SignJWT(keyObject as JWTPayload).setProtectedHeader({ alg, typ: JWT }).sign(privateKey); return token; }要点入参keyObject是任意可 JSON 序列化的对象会被整体放入 JWT 的payloadpkcs8是 PEM/DER 编码的PKCS8 私钥经jose.importPKCS8按alg导入为KeyLike算法默认值alg RS256RSA SHA-256同时写入受保护头部{ alg, typ: JWT }无显式exp/iat等声明因此产物是一个结构固定的、以业务对象为载荷的签名令牌。verify用 SPKI 公钥验签并取回载荷export async function verify(jwt: string, spki: string, alg RS256) { const publicKey await importSPKI(spki, alg); const { payload, protectedHeader } await jwtVerify(jwt, publicKey, {}); return [payload, protectedHeader]; }要点验签使用SPKISubjectPublicKeyInfo公钥与签发侧 PKCS8 私钥构成非对称密钥对jwtVerify内部自动校验签名完整性并返回[payload, protectedHeader]二元组前者即当初sign的原始业务对象后者可核对alg与typ是否匹配预期。getPairs仅供测试环境的密钥对生成器export async function getPairs(): Promise[string, string] { if (process.env.NODE_ENV ! test) { throw new Error(This function should only be used in tests); } const { publicKey, privateKey } await generateKeyPair(RS256); const spki await exportSPKI(publicKey); const pkcs8 await exportPKCS8(privateKey); return [spki, pkcs8]; }这是一个刻意限定运行环境的工具只有在NODE_ENV test时才会生成一对 RS256 密钥返回[SPKI 公钥, PKCS8 私钥]供测试代码构造自签自验的令牌。任何生产路径误用都会直接抛错This function should only be used in tests。用测试反推契约一份接近真实的 License v3 载荷单元测试 不仅是包本身正确性的证明还侧面展示了 License v3 载荷的完整结构。测试先通过jose的generateKeyPair(RS256)生成临时密钥对再调用sign与verify走通签发—验签闭环最终断言expect(protectedHeader).toEqual({ alg: RS256, typ: JWT }); expect(payload).toEqual(licenseV3);其中licenseV3载荷包含了information许可证编号、自动续期、试用标记、授权方与授权对象、法律文本、标签等、validation允许的服务器 URL、服务器版本、云端工作区 ID、有效期与统计上报要求、grantedModules授权模块清单例如auditing、ldap-enterprise、livechat-enterprise、voip-enterprise、device-management、federation以及第 20 项abac和limitsactiveUsers、guestUsers、roomsPerGuest、privateApps、marketplaceApps各自以{ max, behavior }阶梯式限量behavior取值如start_fair_policy、prevent_action、invalidate_license。这份载荷与 CHANGELOG 中 v0.1.0 与 v0.2.0 两个 Minor 版本的功能点一一呼应是理解下游用法的第一手样例。CHANGELOG 逐版本解读一次完整的功能演进史CHANGELOG.md 由 changesets 工具自动生成记录了包从诞生0.1.0到当前0.2.1的全部发布轨迹。逐条对照仓库代码可以还原出每次变更背后的业务含义。0.1.0 / 0.1.0-rc.0 —— 伴随 License 库与 v3 许可证格式落地两个版本对应同一条 Minor 记录并注明提交号5f81a0f3cbImplemented the License library, it is used to handle the functionality like expiration date, modules, limits, etc. Also added a version v3 of the license, which contains an extended list of features. v2 is still supported, since we convert it to v3 on the fly.这是包的首个正式版本即本包与 EE 侧 License 库处理到期时间、模块开关、用量上限等功能在同一次改动中引入。关键承诺是License 新增 v3 格式并携带更长的功能列表同时 v2 仍被支持——运行时会即时on the fly将 v2 转换升级为 v3 再处理。v2→v3 的转换实现位于 v2/convertToV3.ts输入旧的ILicenseV2输出version: 3.0的ILicenseV3旧字段被逐一映射url→validation.serverUrls[0]类型标为regexexpiry/trialEnd→visualExpiration或validPeriods[0].validUntilmaxActiveUsers/maxGuestUsers/maxRoomsPerGuest及apps.maxPrivateApps/apps.maxMarketplaceApps→ 对应limits条目且行为统一为prevent_action旧modules中的 bundle捆绑包会被展开成具体模块getBundleModules并补上outbound-messaging、teams-voip、contact-id-verification、hide-watermark等固定模块tag缺失时会从 bundle 反推出标签并着色getTagColor。这份转换逻辑正是 CHANGELOG 所称v2 is still supported, since we convert it to v3 on the fly的代码级注解。0.1.1 / 0.1.1-rc.0 ——rocket.chat/ui-kit并入主仓库对应记录正式版链接 PR #31138feat(uikit): Moverocket.chat/ui-kitpackage to the main monorepo本次为Patch补丁级别变更根因是把rocket.chat/ui-kit从外部迁移进当前 monorepoapps/meteor与ee/相关代码大量import ... from rocket.chat/ui-kit的路径随之调整。对rocket.chat/jwt而言这属于仓库结构调整带来的连锁重发布而非 API 变化。0.2.0 / 0.2.0-rc.0 —— 为私有频道与私有团队引入 ABAC对应记录PR #37091Adds Attribute Based Access Control (ABAC) for private channels private teams.这是包历史上第二次Minor 级别变更且与功能直接相关Rocket.Chat 需要为私有频道与私有团队的访问控制引入基于属性的访问控制ABAC支持。旁证来自仓库EE 侧存在独立的 ABAC 工具包rocket.chat/abac见 ee/packages/abac/package.json描述为 Rocket.Chat - Attribute Based Access Control (ABAC) support utilities在 jwt 单元测试 的示例 License v3 载荷里grantedModules明确包含{ module: abac }——即 ABAC 作为一项 Enterprise 授权模块出现需要由本包签发/验证的许可证令牌来开启。从源码结构可以推断ABAC 权限规则的授予与验权依赖 Enterprise 许可证对abac模块的授权而许可证令牌的签发与验签又落在rocket.chat/jwt之上——这正是 ABAC 变更需要连带升级本包 Minor 版本的原因。0.2.1 / 0.2.1-rc.0 —— ESLint 工具链升级对应记录PR #38989chore(eslint): Upgrades ESLint and its configuration属于工程化例行升级仓库将 ESLint 及其配置整体升级开发依赖中已使用eslint: ~9.39.5。对包的功能无影响仅保证在统一的新 lint 体系下通过检查。-rc.0后缀与发布节奏CHANGELOG 中每个正式版本前都有一个对应的-rc.0预发布版本这是changesets Turborepo 版本管理的标准产物monorepo 中相互依赖的包如rocket.chat/jwt与rocket.chat/license的 EE 版本会先以-rc.0候选版整体发布并验证再发布正式版在 EE 侧 License 库的 CHANGELOG 中即可看到rocket.chat/jwt以0.2.0 → 0.2.1等版本被联动引用的记录。阅读这类-rc.0条目时应将其视为对应正式版本变更的预发布副本内容一致。核心消费方拆解License 令牌的加密与解密全链路真正体现rocket.chat/jwt价值的是 EE 侧 token.ts。它负责企业许可证与统计令牌的加解密其中v3 走的就是本包的 JWT 通道解密运行时使用decrypt(encrypted: string)判断令牌是否以RCV3_前缀开头。若是则去掉前缀取 JWT 字符串调用verify(jwt, PUBLIC_LICENSE_KEY_V3)——这里的公钥PUBLIC_LICENSE_KEY_V3实际由内嵌的 v2 公钥PUBLIC_LICENSE_KEY_V2做 base64 解码得到形成一套只内置公钥、可在任意服务器离线验签的机制非RCV3_前缀的旧令牌则回退到crypto.publicDecrypt走 v2 的非对称解密流程v2 是直接 RSA 加密的 JSON 文本而非 JWT加密/签发仅测试环境encrypt(license: ILicenseV3)与encryptStatsToken(...)明确以process.env.NODE_ENV ! test抛错作为保护内部通过getPairs()获取临时密钥对再用sign(license, pkcs8)产出RCV3_JWT或纯 JWT 令牌——与包内getPairs的仅测试可用约定完全咬合统计令牌decryptStatsToken同样用verify SPKI 公钥完成解包并返回 JSON 字符串。由此形成清晰的职责划分真正的 RSA 密钥对生成在测试中即时完成生产环境只持有内置公钥用于验签私钥由签发方Rocket.Chat 云/离线授权工具保管二者通过rocket.chat/jwt的sign/verify实现安全互通。这也解释了为什么包内getPairs会如此刻意地拒绝非测试环境。开发者视角如何在仓库内验证与使用该包跑单元测试在仓库根目录执行yarn workspace rocket.chat/jwt test或在包目录下yarn testjest 会运行 jwt.spec.ts 完成生成密钥 → 签发 License v3 载荷 → 验签并断言 payload/header 一致的闭环测试同时也充当了 License v3 载荷结构的活文档类型与规范检查yarn workspace rocket.chat/jwt typecheck与lint分别对应tsc --noEmit与eslint .二次开发约束若其他 workspace 包需要签发/验签令牌应像ee/packages/license一样把rocket.chat/jwt声明为workspace:^依赖并沿用sign/verify的 RS256 默认算法与{ alg, typ: JWT }头部约定生产验签私钥绝不可硬编码在仓库内。小结CHANGELOG 之外的完整拼图版本变更类型核心内容仓库证据0.1.0MinorLicense 库落地新增 v3 格式并即时兼容 v2convertToV3.ts0.1.1Patchrocket.chat/ui-kit迁入主仓库PR #31138仓库目录结构调整0.2.0Minor为私有频道/团队引入 ABACPR #37091abac 包、测试载荷中的abac模块0.2.1Patch升级 ESLint 及配置PR #38989依赖eslint ~9.39.5如果把 CHANGELOG 比作发布日志那么 src/index.ts 与 token.ts 就是它的实现注脚sign负责把企业 License 变成可离线验签的 JWTverify负责用内置公钥还原载荷与头部getPairs负责把整套机制约束在测试闭环内。对企业版功能的读者而言理解rocket.chat/jwt的演进就等于理解 Rocket.Chat 许可证体系从 v2 加密对象走向 v3 JWT 标准、并向 ABAC 等精细化授权能力扩展的关键一步。【免费下载链接】Rocket.ChatThe Secure CommsOS™ for mission-critical operations项目地址: https://gitcode.com/GitHub_Trending/ro/Rocket.Chat创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/9/9 23:45:54

一串9引发的技术思考:数值溢出与边界测试

1. 先别急,这个标题到底在说什么我先说结论:这个“项目标题”一共14个9,没有别的字符。你把它丢给我,让我拆解背后的核心领域、技术点、应用场景,那我第一反应是——这根本不是传统意义上的项目名,而是一串…

2026/9/9 23:40:53

乐鑫ESP32模组智能交互实战:选型、语音、GUI与量产避坑指南

1. 乐鑫模组为什么总能出现在智能交互的第一线 做智能硬件这几年,我发现一个很有意思的现象:不管是做智能音箱、中控屏、离线语音开关,还是做雷达人体存在传感器,大家聊着聊着总会提到乐鑫。早些年大家用ESP8266做联网&#xff0c…

2026/9/10 0:36:01

PySide6开发桌面天气应用全攻略:从API对接、界面设计到打包部署

“桌面版天气预报应用”这个名字听起来简单,但真正动手做的时候,你会发现它几乎能逼你把桌面开发、网络请求、数据解析、状态管理、异常处理、打包分发这条路完整走一遍。我最初想做个桌面天气应用,纯粹是因为受够了手机天气推送的过度设计—…

2026/9/10 0:36:01

基于Simulink的光储联合系统虚拟同步机控制与削峰填谷仿真

我们直接进入正题。光伏电站并网,遇到的两个老大难问题:一是并网后系统惯性低,电网一有波动站里就跟着抖;二是发电曲线和负荷曲线对不上,中午猛发、傍晚急跌,俗称"鸭子曲线"。用储能配合虚拟同步…

2026/9/10 0:36:01

C# WinForms医院挂号管理系统开发实战解析

简介:这是一份基于C# WinForm开发的医院挂号管理系统项目,采用C/S架构与MVC分层设计,覆盖用户管理、科室管理、医生管理以及门急诊挂号、挂号查询、修改口令、挂号单打印和帮助文档等核心模块,适合正在学习C#桌面应用或医疗管理系…

2026/9/10 0:36:01

用Triton手写21个Kernel,Qwen3.5推理提速至223 tokens/s

我花了两周时间,用 Triton 手写了 21 个 kernel,把 Qwen3.5-0.8B 的完整推理链路从 PyTorch 的自动调度里一层层剥出来,最终在单张消费级显卡上把生成速度压到了 223 tokens/s。整个过程远没有标题看起来那么光鲜,中途遇到过 NaN …

2026/9/9 13:11:35

超人会飞不算本事:系统稳定依赖清晰规则与边界设计

开头先不绕弯子。“#斯坦李吐槽dc 所以超人是无缘无故会飞的嘛哈哈哈哈哈哈哈锤哥真是技术人才啊!#雷神 #复联”这类调侃式短标题,第一波冲击力在于它把两个宇宙的角色塞进同一个吐槽箱里,但细想一下就能发现,它真正碰到的根本不是…

2026/9/8 7:15:15

超人VS蜘蛛侠:拆解超级IP的影响力与传播方法论

把“蜘蛛侠 vs 超人”放在 CSDN 上聊,可能很多人第一反应是走错片场了。但如果把这两个角色看成“两个持续运营了 80 多年的文化产品”,你会发现,这场比较本质上是两个不同 IP 策略的长期结果对比:超人赢在定义了整个超级英雄题材…

2026/9/9 16:31:09

基于CNN的调制信号识别:MATLAB实现时频图分类实战

简介:本资源是一套面向通信工程与信号处理方向学习者、研究者的深度学习实践方案,聚焦调制信号自动检测与识别这一典型无线通信任务,解决传统方法依赖人工特征、低信噪比下性能下降等痛点。压缩包共12个文件(10.73MB)&…

2026/9/10 0:00:55

目录对比去重实战:用哈希算法精准清理重复文件

我电脑里现在还有一块换了三次机的“数据墓地”硬盘,里面存着2016年以前所有旧笔记本的完整备份。平时不觉得有什么,直到前阵子想把它整理归档,发现同一个安装包、同一批照片、同一份论文草稿,在几个不同的备份目录里反复出现。更…

2026/9/10 0:00:55

Leaflet离线地图完整Demo合集:内网部署与坐标纠偏实战

简介:这是一份面向Web GIS开发者的LeafLet离线地图示例合集,帮助开发者快速掌握离线地图从搭建到交互的完整流程。压缩包共723个文件,大小14.06MB,以319个js脚本、175个html页面和29个css样式文件为主体,配合png/svg图…

2026/9/10 0:00:55

MATLAB读取Rinex 3.02观测文件:多系统GNSS数据解析实战

简介:基于MATLAB开发的Rinex3.02版观测文件(o文件)读取代码包,面向卫星定位导航方向的学习者与研究人员,用于解决新版观测文件的数据解析、历元提取与时间转换问题。压缩包共4个文件,包含两个m脚本、一个19…

2026/9/7 16:23:03

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

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

2026/9/7 22:46:00

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

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

2026/9/9 10:21:54

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

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

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

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

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