From 060ddd8e121665e4e20090ecb1cdbfea4d369a28 Mon Sep 17 00:00:00 2001 From: imbytecat Date: Fri, 6 Mar 2026 10:02:56 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E6=9B=B4=E6=96=B0=20UX=20=E6=9C=AC?= =?UTF-8?q?=E5=9C=B0=E8=BA=AB=E4=BB=BD=E9=85=8D=E7=BD=AE=E6=B5=81=E7=A8=8B?= =?UTF-8?q?=E4=B8=8E=E5=AF=B9=E6=8E=A5=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/UX-授权端接口说明.md | 100 ++++++++--------- .../工具箱端-任务二维码解密指南.md | 4 +- .../工具箱端-报告加密与签名生成指南.md | 7 +- .../工具箱端-摘要信息二维码生成指南.md | 4 +- .../工具箱端-设备授权二维码生成指南.md | 8 +- docs/第三方-OpenAPI-对接指南.md | 102 ++++++++---------- 6 files changed, 108 insertions(+), 117 deletions(-) diff --git a/docs/UX-授权端接口说明.md b/docs/UX-授权端接口说明.md index 30746e0..c700d2e 100644 --- a/docs/UX-授权端接口说明.md +++ b/docs/UX-授权端接口说明.md @@ -1,71 +1,75 @@ # UX 授权端接口说明 -本文档描述当前 UX 服务端实现的授权对接接口与职责边界。 +本文档描述 UX 服务当前定位:**仅提供底层密码学能力,不维护业务状态**。 ## 1. 职责边界 -- UX **只与工具箱交互**(HTTP RPC),不直接与手机 App 交互。 -- 手机 App 仅承担扫码和与管理平台联网通信。 -- 报告签名流程由工具箱上传原始 ZIP 到 UX,UX 返回已签名 ZIP。 +- UX 只提供加密、解密、签名、ZIP 打包能力 +- UX 不持有设备/任务等业务主数据,不读取业务数据库 +- 调用方(工具箱)负责提供业务上下文与密钥材料 -## 2. 设备注册 +## 2. 核心接口 -`device.register` +### 2.0 `config.get` / `config.setLicence` -- 输入:`licence`、`platformPublicKey` -- UX 在本机采集设备特征并计算 `fingerprint` -- UX 将 `licence + fingerprint + 公钥 + PGP 密钥对` 持久化到数据库 +- `config.get`:读取本地配置(`licence`、`fingerprint`) +- `config.setLicence`:写入本地 `licence` +- 说明:`fingerprint` 由 UX 本机计算并持久化,不由调用方传入 -## 3. 核心加密接口 +### 2.1 `crypto.encryptDeviceInfo` -### 3.1 设备授权二维码密文 +- 输入:`platformPublicKey` +- 输出:`encrypted`(Base64) +- 说明:读取本地 `licence`/`fingerprint` 组装 JSON 后执行 RSA-OAEP 加密 -`crypto.encryptDeviceInfo` +### 2.2 `crypto.decryptTask` -- 使用平台公钥 RSA-OAEP 加密:`{ licence, fingerprint }` -- 返回 Base64 密文(工具箱用于生成二维码) +- 输入:`encryptedData` +- 输出:`decrypted`(明文字符串) +- 说明:使用本地 `licence`/`fingerprint` 推导 `SHA256(licence + fingerprint)` 作为 AES-GCM 密钥 -### 3.2 任务二维码解密 +### 2.3 `crypto.encryptSummary` -`crypto.decryptTask` +- 输入:`salt`、`plaintext` +- 输出:`encrypted`(Base64) +- 说明:使用本地 `licence`/`fingerprint` 做 HKDF-SHA256 + AES-256-GCM 加密 -- 密钥:`SHA256(licence + fingerprint)` -- 算法:AES-256-GCM -- 输入:任务二维码中的 Base64 密文 -- 输出:任务 JSON +### 2.4 `crypto.signAndPackReport` -### 3.3 摘要二维码加密 +- 输入: + - `rawZip`(multipart 文件) + - `pgpPrivateKey` + - `signingContext` + - `summaryJson` + - `outputFileName`(可选) +- 输出:签名后 ZIP 文件(二进制,`application/zip`) -`crypto.encryptSummary` +`summary.json` 由 UX 生成,结构为: -- 密钥派生:HKDF-SHA256 - - `ikm = licence + fingerprint` - - `salt = taskId` - - `info = "inspection_report_encryption"` -- 算法:AES-256-GCM -- 输出:`{ taskId, encrypted }` JSON(工具箱用于生成二维码) +```json +{ + "deviceSignature": "Base64...", + "signingContext": "...", + "payload": { "...": "调用方 summaryJson" }, + "timestamp": 1734571234567 +} +``` -### 3.4 原始 ZIP 签名打包(最终报告) +签名输出 ZIP 固定包含: -`crypto.signAndPackReport` +- `summary.json` +- `META-INF/manifest.json` +- `META-INF/signature.asc` -- 输入:`rawZip`(`multipart/form-data` 文件字段) + `taskId` + `inspectionId` + `enterpriseId` + `summary` -- UX 在服务端完成: - 1. 校验并解包原始 ZIP - 2. 计算文件 SHA-256 - 3. HKDF + HMAC 生成 `deviceSignature` - 4. 生成 `summary.json` - 5. 生成 `META-INF/manifest.json` - 6. OpenPGP 分离签名生成 `META-INF/signature.asc` - 7. 重新打包为 signed ZIP -- 输出:签名后 ZIP 文件(二进制响应,`application/zip`) +## 3. ZIP 安全约束 -## 4. 安全约束(签名打包) +- 拒绝危险路径(防 Zip Slip) +- 原始 ZIP ≤ `50 MiB` +- 单个文件 ≤ `20 MiB` +- 总解压后大小 ≤ `60 MiB` +- ZIP 条目数量 ≤ `64` -- 拒绝危险 ZIP 路径(防 Zip Slip) -- 限制原始 ZIP 和单文件大小 -- 强制存在以下文件: - - `assets.json` - - `vulnerabilities.json` - - `weakPasswords.json` - - `漏洞评估报告*.html` +## 4. OpenAPI + +- 文档:`/api/docs` +- 规范:`/api/spec.json` diff --git a/docs/工具箱端-授权对接指南/工具箱端-任务二维码解密指南.md b/docs/工具箱端-授权对接指南/工具箱端-任务二维码解密指南.md index 496c1ff..88d01e6 100644 --- a/docs/工具箱端-授权对接指南/工具箱端-任务二维码解密指南.md +++ b/docs/工具箱端-授权对接指南/工具箱端-任务二维码解密指南.md @@ -6,8 +6,8 @@ > ### UX 集成模式补充(当前项目实现) > -> 在当前集成模式中,工具箱扫描二维码后将密文提交给 UX 的 `crypto.decryptTask`, -> 由 UX 使用设备绑定的 `licence + fingerprint` 执行 AES-256-GCM 解密并返回任务明文。 +> 在当前集成模式中,工具箱扫描二维码后将密文提交给 UX 的 `crypto.decryptTask`。 +> UX 从本地配置读取 licence/fingerprint 执行底层解密并返回明文字符串。 ## 一、业务流程 diff --git a/docs/工具箱端-授权对接指南/工具箱端-报告加密与签名生成指南.md b/docs/工具箱端-授权对接指南/工具箱端-报告加密与签名生成指南.md index 83fd7af..d7dd2ff 100644 --- a/docs/工具箱端-授权对接指南/工具箱端-报告加密与签名生成指南.md +++ b/docs/工具箱端-授权对接指南/工具箱端-报告加密与签名生成指南.md @@ -10,9 +10,10 @@ > > 在当前集成模式中,工具箱可将原始报告 ZIP 直接上传到 UX 的 `crypto.signAndPackReport`: > -> 1. UX 校验 ZIP 并提取必需文件; -> 2. UX 生成 `deviceSignature`、`summary.json`、`META-INF/manifest.json`、`META-INF/signature.asc`; -> 3. UX 重新打包并返回签名后的 ZIP(二进制文件响应),工具箱再用于离线介质回传平台。 +> 1. 工具箱先通过 `config.setLicence` 完成本地 licence 配置; +> 2. 工具箱传入 `pgpPrivateKey`、`signingContext`、`summaryJson` 与 `rawZip`; +> 3. UX 从本地配置读取 licence/fingerprint,执行签名与打包能力,生成 `summary.json`、`META-INF/manifest.json`、`META-INF/signature.asc`; +> 4. UX 返回签名后的 ZIP(二进制文件响应),工具箱再用于离线介质回传平台。 ## 一、ZIP 文件结构要求 diff --git a/docs/工具箱端-授权对接指南/工具箱端-摘要信息二维码生成指南.md b/docs/工具箱端-授权对接指南/工具箱端-摘要信息二维码生成指南.md index 2a46dc3..7ed686e 100644 --- a/docs/工具箱端-授权对接指南/工具箱端-摘要信息二维码生成指南.md +++ b/docs/工具箱端-授权对接指南/工具箱端-摘要信息二维码生成指南.md @@ -6,8 +6,8 @@ > ### UX 集成模式补充(当前项目实现) > -> 在当前集成模式中,工具箱将摘要明文传给 UX 的 `crypto.encryptSummary`, -> 由 UX 执行 HKDF + AES-256-GCM 加密并返回二维码内容 JSON(`taskId + encrypted`)。 +> 在当前集成模式中,工具箱将明文文本传给 UX 的 `crypto.encryptSummary`,并提供 `salt`。 +> UX 从本地配置读取 licence/fingerprint,执行 HKDF + AES-256-GCM 并返回 Base64 密文。 ## 一、业务流程 diff --git a/docs/工具箱端-授权对接指南/工具箱端-设备授权二维码生成指南.md b/docs/工具箱端-授权对接指南/工具箱端-设备授权二维码生成指南.md index 40f2d51..5e08b87 100644 --- a/docs/工具箱端-授权对接指南/工具箱端-设备授权二维码生成指南.md +++ b/docs/工具箱端-授权对接指南/工具箱端-设备授权二维码生成指南.md @@ -6,11 +6,11 @@ > ### UX 集成模式补充(当前项目实现) > -> 在当前集成模式中,工具箱不直接执行 RSA 加密,而是调用 UX 接口: +> 调用前提:工具箱先调用 `config.setLicence` 写入本地 licence(fingerprint 由 UX 本机计算并持久化)。 > -> 1. 工具箱先调用 `device.register` 传入 `licence` 与平台公钥,`fingerprint` 由 UX 本机计算并入库。 -> 2. 工具箱再调用 `crypto.encryptDeviceInfo` 获取加密后的 Base64 密文。 -> 3. 工具箱将该密文生成二维码供 App 扫码提交平台。 +> 在当前集成模式中,工具箱调用 UX 的 `crypto.encryptDeviceInfo`,直接传入 +> `platformPublicKey` 获取加密后的 Base64 密文。 +> UX 不保存业务设备实体,仅保存本机身份材料(licence/fingerprint)。 ## 一、业务流程 diff --git a/docs/第三方-OpenAPI-对接指南.md b/docs/第三方-OpenAPI-对接指南.md index 841ce31..10d43af 100644 --- a/docs/第三方-OpenAPI-对接指南.md +++ b/docs/第三方-OpenAPI-对接指南.md @@ -1,98 +1,84 @@ # 第三方 OpenAPI 对接指南 -本文档用于第三方系统快速接入 UX 授权服务。 +本文档用于第三方系统对接 UX 底层能力服务。 ## 1. 文档入口 - OpenAPI 文档(Scalar):`/api/docs` - OpenAPI 规范(JSON):`/api/spec.json` -例如本地开发环境: +本地开发环境示例: - `http://localhost:3000/api/docs` - `http://localhost:3000/api/spec.json` -## 2. 接口分组 +## 2. 服务边界 -OpenAPI 中已按 `tags` 分组: +UX 仅提供底层加密/解密/签名能力,不维护业务实体(设备、任务、组织等)。 -- `Device`:设备注册与查询 -- `Crypto`:授权加解密与二维码数据处理 -- `Report`:报告签名打包 -- `Task`:任务保存与状态管理 +- 调用方负责提供业务上下文与必要签名材料(如 `platformPublicKey`、`pgpPrivateKey`) +- 调用方负责业务字段定义与存储 -## 3. 核心接口一览 +## 3. 核心接口 -### Device +- `POST /api/config/get` + - operationId: `configGet` + - 作用:读取 UX 本地 `licence` 与 `fingerprint` -- `POST /api/device/register` - - 操作名:`deviceRegister` - - 说明:注册设备,UX 计算并存储 fingerprint -- `POST /api/device/get` - - 操作名:`deviceGet` - - 说明:按 `id` 或 `licence` 查询设备 - -### Crypto +- `POST /api/config/set-licence` + - operationId: `configSetLicence` + - 作用:设置 UX 本地 `licence`(`fingerprint` 由 UX 本机计算并持久化) - `POST /api/crypto/encrypt-device-info` - - 操作名:`encryptDeviceInfo` - - 说明:生成设备授权二维码密文 + - operationId: `encryptDeviceInfo` + - 作用:使用本地身份(licence/fingerprint)与输入 `platformPublicKey` 生成授权密文 + - `POST /api/crypto/decrypt-task` - - 操作名:`decryptTask` - - 说明:解密任务二维码数据 + - operationId: `decryptTask` + - 作用:基于 `SHA256(licence+fingerprint)` 解密 AES-GCM 密文 + - `POST /api/crypto/encrypt-summary` - - 操作名:`encryptSummary` - - 说明:加密摘要并返回二维码内容 + - operationId: `encryptSummary` + - 作用:基于 HKDF + AES-GCM 加密任意明文 + - `POST /api/crypto/sign-and-pack-report` - - 操作名:`signAndPackReport` - - 说明:上传原始 ZIP,返回签名后 ZIP + - operationId: `signAndPackReport` + - 作用:上传原始 ZIP,生成 `summary.json` + `META-INF/manifest.json` + `META-INF/signature.asc`,返回签名后 ZIP 文件(二进制) -### Task +## 4. 文件上传接口(signAndPackReport) -- `POST /api/task/save` - - 操作名:`taskSave` -- `POST /api/task/list` - - 操作名:`taskList` -- `POST /api/task/update-status` - - 操作名:`taskUpdateStatus` +调用顺序建议: -## 4. 字段说明来源 +1. 先调用 `POST /api/config/set-licence` 写入本地 `licence` +2. 调用 `POST /api/config/get` 确认 `fingerprint` 已存在 +3. 再调用各 `crypto/*` 能力接口 -每个接口的字段定义、必填/可选、类型、以及业务描述,均在 OpenAPI 中由 oRPC 合约的 Zod schema 自动生成。 +请求使用 `multipart/form-data`: -你可以在 `/api/docs` 页面直接查看: +- `rawZip`:原始 ZIP 文件(`application/zip` / `application/x-zip-compressed`) +- `pgpPrivateKey`:签名材料 +- `signingContext`:签名上下文字符串 +- `summaryJson`:`summary.json` 的 JSON 文本 +- `outputFileName`:可选,输出文件名 -1. 接口名称(operationId) -2. 接口摘要(summary) -3. 详细说明(description) -4. 请求字段(含描述) -5. 响应字段(含描述) +响应: -## 5. 文件上传接口注意事项 +- `application/zip` 二进制文件(签名后 ZIP) -`signAndPackReport` 使用 `multipart/form-data`,文件字段名为 `rawZip`。 - -- 文件类型:`application/zip` 或 `application/x-zip-compressed` -- 其他业务字段(如 `deviceId`、`taskId`)与文件一起提交 -- 接口响应为签名后 ZIP 文件(`application/zip`) +说明:响应 ZIP 中 `summary.json` 会包含 `timestamp`(服务端生成,毫秒时间戳)。 示例(curl): ```bash curl -X POST "http://localhost:3000/api/crypto/sign-and-pack-report" \ - -F "deviceId=dev_xxx" \ - -F "taskId=TASK-20260115-4875" \ - -F "enterpriseId=1173040813421105152" \ - -F "inspectionId=702286470691215417" \ - -F "summary=检查摘要信息" \ + -F "pgpPrivateKey=-----BEGIN PGP PRIVATE KEY BLOCK-----..." \ + -F "signingContext=TASK-20260115-4875|702286470691215417" \ + -F "summaryJson={\"summary\":\"检查摘要\"}" \ + -F "outputFileName=signed-report.zip" \ -F "rawZip=@./report-raw.zip;type=application/zip" \ --output signed-report.zip ``` -## 6. 推荐接入方式 +## 5. 字段说明来源 -第三方如需代码生成,建议直接消费 `/api/spec.json`: - -- Java:OpenAPI Generator -- C#:NSwag / OpenAPI Generator -- TypeScript:openapi-typescript / Orval +所有接口名称、字段类型、必填项、描述均以 `/api/docs` 与 `/api/spec.json` 为准。