发布 0.3.0 并增加 RSA 签名验证

This commit is contained in:
mid
2026-08-13 13:32:56 +08:00
parent 32b7cc827c
commit 0ae6db36cb
27 changed files with 2025 additions and 274 deletions
+27 -20
View File
@@ -4,7 +4,7 @@
一个匿名访问、自托管的浏览器本地工具箱。支持多人同时使用;除全局导航顺序外,文本、密钥、文件、图片和计算结果均只存在于各自浏览器中,不会发送到服务端。
当前应用版本:`0.2.1`。
当前应用版本:`0.3.0`。
## 内置工具
@@ -14,6 +14,7 @@
- CRC-8/16/32/64 预设与自定义参数,支持 BIN 和多 block Intel HEX
- 固件 SHA-256 / SHA-512,支持 Intel HEX 有效数据和带地址/长度的 Block 校验头
- RSA 2048/3072/4096 位密钥对,导出 PEM,以及可分别复制的 N/E Hex 或代码字节数组
- RSA 签名验证,支持 PKCS#1 v1.5、RSA-PSS(默认)、SHA-256/384/512、PEM/X.509/N-E 公钥,以及文本、Hex、原始文件、Intel HEX 有效数据和 Block 校验头
- 密码学安全随机数,默认 16 字节,支持连续 Hex、空格 Hex 和代码字节数组
- JSON 格式化、压缩、校验和语法着色
- XML 格式化、压缩、校验和语法着色
@@ -28,6 +29,7 @@
```text
src/ Vue 3 前端源码
components/ 所有工具共用的 UI 组件
composables/ 可复用的 Vue 状态与异步生命周期管理
lib/ 可测试的纯计算与浏览器辅助逻辑
tools/ 每个工具一个独立 Vue 组件
workers/ 大文件计算使用的浏览器后台线程
@@ -49,9 +51,9 @@ CHANGELOG.md 版本变更、修复和验证记录
## 架构约束
- Vue 3、TypeScript、Vite 前端;Node.js 标准库服务端;不引入数据库。
- 工具组件彼此独立并懒加载,公共交互使用 `ToolPage`、`ModeTabs`、`TextEditor` 和 `src/styles.css` 中的现有样式。
- 工具组件彼此独立并懒加载,公共交互使用 `ToolPage`、`ModeTabs`、`TextEditor`、`FileDropField` 和 `src/styles.css` 中的现有样式。CRC、固件 Hash 与 RSA 签名验证的文件模式共用 `FileDropField` 的文件选择、摘要、拖入更换和清空交互;PNG/ICO 的图片工作区有独立的预览与转换流程,不属于该共用控件范围。
- 工具的计算、解析和文件生成逻辑放在 `src/lib/`,Vue 组件只负责状态与交互。
- 大文件或长时间计算必须放入 `src/workers/` 的 Web Worker,避免阻塞页面交互;Worker 仍只在浏览器本地处理数据。
- 大文件或长时间计算必须放入 `src/workers/` 的 Web Worker,避免阻塞页面交互;Worker 仍只在浏览器本地处理数据。协议符合“解析后复用同一 Worker 计算”的文件工具应使用 `useTransactionalFileWorker` 管理候选 Worker、活动 Worker 和请求 ID,同时保留各工具独立的 Worker 协议、计算逻辑及 Vue 状态。
- 路由和左侧导航由工具目录自动生成,增加普通工具时不得手工新增路由。
- 工具输入只在浏览器内存中处理,不得发送给服务端、遥测服务或第三方接口。
- 服务端只持久化导航顺序,文件为 `/data/navigation.json`,写入采用临时文件和原子替换。
@@ -71,16 +73,18 @@ CHANGELOG.md 版本变更、修复和验证记录
- Base64 支持标准和 URL-safe 形式;解码结果可显示为严格 UTF-8、连续 Hex 或 `0x48, 0x9F, ...` 字节数组。无效字符、错误填充和非规范编码必须报错。
- AES-CMAC 密钥长度可选 128、192 或 256 位,默认 128 位,并分别严格要求 16、24 或 32 字节;不自动补零或截断。密钥和 Hex 消息接受连续 Hex,或空格、换行、英文/中文逗号分隔,并允许片段使用可选的 `0x` 前缀。CMAC 标签始终为 128 位;AES-128 向量遵循 RFC 4493,AES-192/256 向量遵循 NIST SP 800-38B。
- CRC 支持 BIN 和多 block Intel HEX,提供 CRC-8/16/32/64 预设,并允许自定义 `Width`、`Poly`、`Init`、`XorOut`、`RefIn` 和 `RefOut`。`RefIn`/`RefOut` 在页面中标为输入/输出位反转,不表示字节顺序或整个数据倒序。总 CRC 对按地址升序拼接的有效数据计算,不填充地址空洞,同时输出每个 block 的结果。
- 固件 Hash 只接受 Intel HEX,输出 SHA-256 和 SHA-512。“有效数据”与“Block 校验头”模式的确切字节流见“固件 Hash 固定语义”;默认校验头字节序为 Big Endian。
- RSA 只允许 2048、3072、4096 位密钥,公钥指数固定为 65537。优先使用 Web Crypto,只有本地提供者不可用或失败时才动态加载 `node-forge` 回退,其随机种子仍只来自 `crypto.getRandomValues`;公钥为 SPKI PEM,私钥为 PKCS#8 PEM,N/E 可分别显示为连续 Hex 或代码字节数组。
- 固件 Hash 只接受 Intel HEX,输出 SHA-256 和 SHA-512。“有效数据”与“Block 校验头”模式的确切字节流见“Intel HEX 与 Block 校验头固定语义”;默认校验头字节序为 Big Endian。
- RSA 密钥对工具只生成 2048、3072、4096 位密钥,公钥指数固定为 65537。优先使用 Web Crypto,只有本地提供者不可用或失败时才动态加载 `node-forge` 回退,其随机种子仍只来自 `crypto.getRandomValues`;公钥为 SPKI PEM,私钥为 PKCS#8 PEM,N/E 可分别显示为连续 Hex 或代码字节数组。
- RSA 签名验证工具只执行验证,不接收私钥或生成签名。它默认选择 RSA-PSS,并支持切换到 RSA PKCS#1 v1.5;Hash 支持 SHA-256/384/512,不支持 SHA-1。PSS 的 Salt Length 必须显式给出,默认取 Hash 长度与当前模数编码上限中的较小值,并受当前模数与 Hash 的编码上限约束。公钥可使用单个 SPKI `PUBLIC KEY`、PKCS#1 `RSA PUBLIC KEY`、X.509 `CERTIFICATE` PEM 块或 N/E Hex 参数;E 按无符号 Hex 整数解析,奇数位输入会在最左侧补一个 `0`,因此 `10001`、`010001` 均表示十进制 65537,其他 Hex 字节输入仍要求偶数位。X.509 只用于提取 RSA 公钥和展示 Subject、序列号、有效期,不验证证书链、颁发者、用途或可信状态。验证接受 1024 至 8192 位 RSA 公钥,低于 2048 位时显示兼容性警告。
- 签名可输入 Hex、Base64 或 Base64 URL。待验证数据可为 UTF-8 原文、Hex 字节、原始文件字节、Intel HEX 按 32 位绝对地址升序拼接的有效数据,或带 Block 校验头的 Intel HEX 数据。“Intel HEX 有效数据”不填充地址空洞,也不加入校验头;“Block 校验头”对每个 block 加入与固件 Hash 相同的 8 字节二进制地址/长度头,默认 Big Endian,可显式切换 Little Endian。文件语义必须由用户明确选择,工具不得按扩展名自动推断或切换。
- 安全随机数必须来自浏览器 `crypto.getRandomValues`,默认 16 字节,允许长度为 1 至 65,536 字节,支持连续 Hex、空格 Hex 和代码字节数组;切换显示格式不得重新生成随机数据。安全随机源不可用或抛错时直接失败,不使用普通伪随机回退。
- JSON/XML 的格式化、压缩和校验均在浏览器本地完成。合法 XML 可以使用 `parsererror` 作为元素名;只把浏览器专用解析错误命名空间中的节点视为解析失败。语法着色超过资源限制时只能降级为完整纯文本,不能截断结果。
- 文件选择、文件更换、清空、模式切换和组件卸载都可能使异步任务失效。旧 Worker、旧图像解码和旧密钥生成结果不得覆盖当前输入或已清空状态。
- 文件选择、文件更换、清空、模式切换和组件卸载都可能使异步任务失效。旧 Worker、旧图像解码和旧密钥生成结果不得覆盖当前输入或已清空状态。CRC、固件 Hash 与 RSA 签名验证的文件模式在已有文件时支持把新文件直接拖入摘要区域;候选文件解析成功后才替换当前文件并清除旧结果,解析失败时保留当前文件和结果。
## 多人使用与状态边界
- 每个浏览器标签页拥有独立的 Vue 组件状态、文件对象、图像对象和 Web Worker。不同用户、浏览器或标签页不会共享工具输入与结果。
- CRC、固件 Hash、RSA、AES-CMAC、随机数、PNG/ICO、编码转换和格式化都在浏览器中执行;服务端没有工具计算接口。
- CRC、固件 Hash、RSA 密钥生成与签名验证、AES-CMAC、随机数、PNG/ICO、编码转换和格式化都在浏览器中执行;服务端没有工具计算接口。
- `/tools/setting` 保存的是所有访问者共享的导航配置。同一服务进程会按进入导航操作队列的顺序串行处理读写,最后排队的保存生效;不提供版本冲突合并。
- 旧导航配置中的历史工具 ID `ascii-hex` 会在读取时原位迁移为 `utf8-hex`,保留原分类和排序;新配置和应用路由只使用 `utf8-hex`。
- 原子替换保证读取者看到完整的旧配置或新配置,不会看到写到一半的 JSON;它不保证保留多个用户各自的排序修改。
@@ -93,11 +97,14 @@ CHANGELOG.md 版本变更、修复和验证记录
| 功能 | 当前限制 | 超限行为 |
| --- | --- | --- |
| CRC 固件文件 | 最大 64 MiB | 选择时拒绝,不保留旧文件结果 |
| CRC 固件文件 | 最大 64 MiB | 首次选择时拒绝;替换时保留当前文件和结果 |
| Intel HEX 非空记录 | 最多 500,000 条 | Worker 停止解析并显示错误 |
| Intel HEX 数据块 | 最多 1,024 个 block | Worker 停止解析并显示错误 |
| Intel HEX 合并后的有效数据 | 最大 64 MiB | 合并分配前拒绝,Worker 停止解析并显示错误 |
| 固件 Hash 文件及有效数据 | 文件最大 64 MiB,有效数据最大 64 MiB | 选择或计算时拒绝 |
| 固件 Hash 文件及有效数据 | 文件最大 64 MiB,有效数据最大 64 MiB | 首次选择或计算时拒绝;替换解析失败时保留当前文件和结果 |
| RSA 签名验证内联数据 | UTF-8 或 Hex 解析后最大 1 MiB;原始输入最多 6 MiB 字符 | 在分配超限结果前拒绝,并提示改用文件模式 |
| RSA 签名验证文件 | 原始文件或 Intel HEX 文件最大 64 MiB;Intel HEX 有效数据或加入 Block 校验头后的验签数据最大 64 MiB | 首次选择时拒绝;替换失败时保留当前文件和结果 |
| RSA 签名验证输入 | PEM 最大 64 KiB;N/E 与签名输入各最大 16 KiB;RSA 模数 1024 至 8192 位 | 解析或验证前拒绝 |
| PNG 压缩文件 | 最大 32 MiB | 创建预览前拒绝 |
| PNG 尺寸 | 单边最大 16,384 像素,总计最大 32,000,000 像素 | 浏览器解码前拒绝 |
| 安全随机数 | 默认 16 字节,每次 1 至 65,536 字节 | 拒绝无效长度或不安全回退 |
@@ -255,10 +262,10 @@ docker compose restart web-tools
## 离线镜像
若交付目录包含 `personal-web-tools-0.2.1-amd64.tar`,可直接导入:
若交付目录包含 `personal-web-tools-0.3.0-amd64.tar`,可直接导入:
```bash
docker load -i personal-web-tools-0.2.1-amd64.tar
docker load -i personal-web-tools-0.3.0-amd64.tar
docker compose up -d --no-build
```
@@ -312,13 +319,13 @@ npm audit --audit-level=low
`npm run check` 会依次运行全部 Vitest 测试、TypeScript/Vue 类型检查和生产构建。服务端测试使用随机本地端口验证 SPA 直达路由、静态资源 404 与缓存策略、导航 API、请求大小限制及跨源浏览器写入拦截。
自动化测试还覆盖标准算法向量、Base64 规范性、Intel HEX 记录与 block 边界、固件 Hash 与大小端 Block 头向量、PNG 头部与像素限制、导航排序纯函数、目录/图标/懒加载组件一致性,以及原子写入失败后的临时文件清理。
自动化测试还覆盖标准算法向量、Base64 规范性、Intel HEX 记录与 block 边界、固件 Hash 与大小端 Block 头向量、RSA PKCS#1 v1.5/PSS 三种 Hash、PEM/X.509/N-E 公钥解析、签名编码与 PSS 盐长边界、原始文件、Intel HEX 有效数据与大小端 Block 校验头的验签字节语义、文件替换成功提交、失败保留旧状态、过期 Worker 响应隔离和 Worker 生命周期异常、PNG 头部与像素限制、导航排序纯函数、目录/图标/懒加载组件一致性,以及原子写入失败后的临时文件清理。
## 增加工具
### 固件 Hash 固定语义
### Intel HEX 与 Block 校验头固定语义
固件 Hash 与 CRC 共用经过校验的 Intel HEX 解析器,但使用独立纯逻辑、Worker 和 Vue 页面。解析器处理扩展段/线性地址,将数据按 32 位绝对地址排序,合并连续记录,去重内容一致的重叠记录,并拒绝冲突或越过 `0xFFFFFFFF` 的数据。记录文本、记录校验和、EOF 和启动地址不参与 Hash。
固件 Hash、RSA 签名验证与 CRC 共用经过校验的 Intel HEX 解析器,但使用独立纯逻辑、Worker 和 Vue 页面。解析器处理扩展段/线性地址,将数据按 32 位绝对地址排序,合并连续记录,去重内容一致的重叠记录,并拒绝冲突或越过 `0xFFFFFFFF` 的数据。记录文本、记录校验和、EOF 和启动地址不参与 Hash 或签名验证。
摘要计算优先使用浏览器原生 Web Crypto;通过普通 HTTP 局域网地址访问而无法使用 `SubtleCrypto` 时,自动回退到项目内已有的 `node-forge` SHA-256/SHA-512 实现。两条路径都在 Web Worker 中本地处理,不会把固件数据发送到服务端。
@@ -329,7 +336,7 @@ uint32 startAddress
uint32 dataLength
```
默认使用 Big Endian,可以显式切换 Little Endian。两个字段始终为 4 字节;`dataLength` 只表示该 block 的有效数据字节数,不包含 8 字节校验头。总输入严格为 `Header1 || Data1 || Header2 || Data2 ...`,同时输出总 SHA-256/SHA-512 和每个 block 的独立摘要。不得把固定宽度 Hex 文本误作为 ASCII 字符加入 Hash,也不得隐式使用运行设备的原生端序。
默认使用 Big Endian,可以显式切换 Little Endian。两个字段始终为 4 字节;`dataLength` 只表示该 block 的有效数据字节数,不包含 8 字节校验头。总输入严格为 `Header1 || Data1 || Header2 || Data2 ...`。固件 Hash 对该输入输出总 SHA-256/SHA-512 和每个 block 的独立摘要;RSA 签名验证则把同一输入交给所选 RSA/Hash 算法验证。不得把固定宽度 Hex 文本误作为 ASCII 字符加入计算,也不得隐式使用运行设备的原生端序。
### 1. 先定义稳定标识
@@ -348,7 +355,7 @@ uint32 dataLength
在 `tests/` 添加正常输入、边界输入、无效输入和已知测试向量。涉及字节的工具必须明确 UTF-8、Hex、Base64、换行及分隔符语义,避免隐式改变数据。
文件或高开销工具还必须定义文件大小、记录数量、图像尺寸或输出 DOM 数量等资源上限。异步工具在清空、更换输入或卸载后必须忽略旧任务结果;计算量较大的文件解析与 CRC 计算放入 Web Worker。
文件或高开销工具还必须定义文件大小、记录数量、图像尺寸或输出 DOM 数量等资源上限。异步工具在清空、更换输入或卸载后必须忽略旧任务结果;计算量较大的文件解析与 CRC 计算放入 Web Worker。若新工具采用“解析文件后继续在同一 Worker 中计算”的协议,应优先复用 `FileDropField` 和 `useTransactionalFileWorker`;候选文件解析成功前不得销毁当前 Worker、文件摘要或结果。
### 3. 编写统一的工具页面
@@ -358,7 +365,7 @@ uint32 dataLength
- 文本输入输出优先使用 `TextEditor`。
- 模式切换使用 `ModeTabs`。
- 操作按钮使用 Lucide 图标和现有 `action-button` 类。
- 必须提供清空、错误提示和必要的复制/粘贴操作。
- 必须提供清空、错误提示和必要的复制/粘贴操作。文件工具的交互与现有协议匹配时复用 `FileDropField`,不要复制一套相近的上传框和替换状态。
- 不增加登录、收藏、赞助、遥测、外部网络请求或独立视觉风格。
- 在窄屏下确认控件不溢出、不重叠,文字不会遮挡。
@@ -414,9 +421,9 @@ npm audit --audit-level=low
1. `shared/tool-catalog.json` 和 `shared/default-navigation.json`
2. `src/tools/registry.ts`
3. 与目标功能最接近的 `src/tools/*.vue`
4. `src/components/ToolPage.vue`、`TextEditor.vue`、`ModeTabs.vue`
5. 相关 `src/lib/` 和 `tests/`
6. `server/navigation.mjs` 中的导航兼容逻辑
4. `src/components/ToolPage.vue`、`TextEditor.vue`、`ModeTabs.vue`;文件工具还要检查 `FileDropField.vue`
5. 相关 `src/lib/`、`src/workers/` 和 `tests/`;采用解析/计算 Worker 协议时还要检查 `src/composables/useTransactionalFileWorker.ts`
6. 涉及工具登记或导航行为时,检查 `server/navigation.mjs` 中的导航兼容逻辑
AI 不应仅修改 `dist/`;必须修改源码并重新构建。不得覆盖或删除用户的 `data/navigation.json`。发现工作区已有未说明的改动时应保留并兼容,不得擅自回退。