docs: 更新 UX 本地身份配置流程与对接说明

This commit is contained in:
2026-03-06 10:02:56 +08:00
parent b50d2eaf10
commit 060ddd8e12
6 changed files with 108 additions and 117 deletions

View File

@@ -1,71 +1,75 @@
# UX 授权端接口说明 # UX 授权端接口说明
本文档描述当前 UX 服务端实现的授权对接接口与职责边界 本文档描述 UX 服务当前定位:**仅提供底层密码学能力,不维护业务状态**
## 1. 职责边界 ## 1. 职责边界
- UX **只与工具箱交互**HTTP RPC不直接与手机 App 交互。 - UX 只提供加密、解密、签名、ZIP 打包能力
- 手机 App 仅承担扫码和与管理平台联网通信。 - UX 不持有设备/任务等业务主数据,不读取业务数据库
- 报告签名流程由工具箱上传原始 ZIP 到 UXUX 返回已签名 ZIP。 - 调用方(工具箱)负责提供业务上下文与密钥材料
## 2. 设备注册 ## 2. 核心接口
`device.register` ### 2.0 `config.get` / `config.setLicence`
- 输入:`licence``platformPublicKey` - `config.get`:读取本地配置(`licence``fingerprint`
- UX 在本机采集设备特征并计算 `fingerprint` - `config.setLicence`:写入本地 `licence`
- UX 将 `licence + fingerprint + 公钥 + PGP 密钥对` 持久化到数据库 - 说明:`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 }` - 输入:`encryptedData`
- 返回 Base64 密文(工具箱用于生成二维码 - 输出:`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)` ### 2.4 `crypto.signAndPackReport`
- 算法AES-256-GCM
- 输入:任务二维码中的 Base64 密文
- 输出:任务 JSON
### 3.3 摘要二维码加密 - 输入:
- `rawZip`multipart 文件)
- `pgpPrivateKey`
- `signingContext`
- `summaryJson`
- `outputFileName`(可选)
- 输出:签名后 ZIP 文件(二进制,`application/zip`
`crypto.encryptSummary` `summary.json` 由 UX 生成,结构为:
- 密钥派生HKDF-SHA256 ```json
- `ikm = licence + fingerprint` {
- `salt = taskId` "deviceSignature": "Base64...",
- `info = "inspection_report_encryption"` "signingContext": "...",
- 算法AES-256-GCM "payload": { "...": "调用方 summaryJson" },
- 输出:`{ taskId, encrypted }` JSON工具箱用于生成二维码 "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` ## 3. ZIP 安全约束
- 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`
## 4. 安全约束(签名打包 - 拒绝危险路径(防 Zip Slip
- 原始 ZIP ≤ `50 MiB`
- 单个文件 ≤ `20 MiB`
- 总解压后大小 ≤ `60 MiB`
- ZIP 条目数量 ≤ `64`
- 拒绝危险 ZIP 路径(防 Zip Slip ## 4. OpenAPI
- 限制原始 ZIP 和单文件大小
- 强制存在以下文件: - 文档:`/api/docs`
- `assets.json` - 规范:`/api/spec.json`
- `vulnerabilities.json`
- `weakPasswords.json`
- `漏洞评估报告*.html`

View File

@@ -6,8 +6,8 @@
> ### UX 集成模式补充(当前项目实现) > ### UX 集成模式补充(当前项目实现)
> >
> 在当前集成模式中,工具箱扫描二维码后将密文提交给 UX 的 `crypto.decryptTask` > 在当前集成模式中,工具箱扫描二维码后将密文提交给 UX 的 `crypto.decryptTask`
> UX 使用设备绑定的 `licence + fingerprint` 执行 AES-256-GCM 解密并返回任务明文 > UX 从本地配置读取 licence/fingerprint 执行底层解密并返回明文字符串
## 一、业务流程 ## 一、业务流程

View File

@@ -10,9 +10,10 @@
> >
> 在当前集成模式中,工具箱可将原始报告 ZIP 直接上传到 UX 的 `crypto.signAndPackReport` > 在当前集成模式中,工具箱可将原始报告 ZIP 直接上传到 UX 的 `crypto.signAndPackReport`
> >
> 1. UX 校验 ZIP 并提取必需文件 > 1. 工具箱先通过 `config.setLicence` 完成本地 licence 配置
> 2. UX 生成 `deviceSignature`、`summary.json`、`META-INF/manifest.json`、`META-INF/signature.asc` > 2. 工具箱传入 `pgpPrivateKey`、`signingContext`、`summaryJson` 与 `rawZip`
> 3. UX 重新打包并返回签名后的 ZIP二进制文件响应工具箱再用于离线介质回传平台。 > 3. UX 从本地配置读取 licence/fingerprint执行签名与打包能力生成 `summary.json`、`META-INF/manifest.json`、`META-INF/signature.asc`
> 4. UX 返回签名后的 ZIP二进制文件响应工具箱再用于离线介质回传平台。
## 一、ZIP 文件结构要求 ## 一、ZIP 文件结构要求

View File

@@ -6,8 +6,8 @@
> ### UX 集成模式补充(当前项目实现) > ### UX 集成模式补充(当前项目实现)
> >
> 在当前集成模式中,工具箱将摘要明文传给 UX 的 `crypto.encryptSummary` > 在当前集成模式中,工具箱将明文文本传给 UX 的 `crypto.encryptSummary`并提供 `salt`。
> UX 执行 HKDF + AES-256-GCM 加密并返回二维码内容 JSON`taskId + encrypted` > UX 从本地配置读取 licence/fingerprint执行 HKDF + AES-256-GCM 并返回 Base64 密文
## 一、业务流程 ## 一、业务流程

View File

@@ -6,11 +6,11 @@
> ### UX 集成模式补充(当前项目实现) > ### UX 集成模式补充(当前项目实现)
> >
> 在当前集成模式中,工具箱不直接执行 RSA 加密,而是调用 UX 接口: > 调用前提:工具箱先调用 `config.setLicence` 写入本地 licencefingerprint 由 UX 本机计算并持久化)。
> >
> 1. 工具箱调用 `device.register` 传入 `licence` 与平台公钥,`fingerprint` 由 UX 本机计算并入库。 > 在当前集成模式中,工具箱调用 UX 的 `crypto.encryptDeviceInfo`,直接传入
> 2. 工具箱再调用 `crypto.encryptDeviceInfo` 获取加密后的 Base64 密文。 > `platformPublicKey` 获取加密后的 Base64 密文。
> 3. 工具箱将该密文生成二维码供 App 扫码提交平台 > UX 不保存业务设备实体仅保存本机身份材料licence/fingerprint
## 一、业务流程 ## 一、业务流程

View File

@@ -1,98 +1,84 @@
# 第三方 OpenAPI 对接指南 # 第三方 OpenAPI 对接指南
本文档用于第三方系统快速接入 UX 授权服务。 本文档用于第三方系统对接 UX 底层能力服务。
## 1. 文档入口 ## 1. 文档入口
- OpenAPI 文档Scalar`/api/docs` - OpenAPI 文档Scalar`/api/docs`
- OpenAPI 规范JSON`/api/spec.json` - OpenAPI 规范JSON`/api/spec.json`
例如本地开发环境: 本地开发环境示例
- `http://localhost:3000/api/docs` - `http://localhost:3000/api/docs`
- `http://localhost:3000/api/spec.json` - `http://localhost:3000/api/spec.json`
## 2. 接口分组 ## 2. 服务边界
OpenAPI 中已按 `tags` 分组: UX 仅提供底层加密/解密/签名能力,不维护业务实体(设备、任务、组织等)。
- `Device`:设备注册与查询 - 调用方负责提供业务上下文与必要签名材料(如 `platformPublicKey``pgpPrivateKey`
- `Crypto`:授权加解密与二维码数据处理 - 调用方负责业务字段定义与存储
- `Report`:报告签名打包
- `Task`:任务保存与状态管理
## 3. 核心接口一览 ## 3. 核心接口
### Device - `POST /api/config/get`
- operationId: `configGet`
- 作用:读取 UX 本地 `licence``fingerprint`
- `POST /api/device/register` - `POST /api/config/set-licence`
- 操作名:`deviceRegister` - operationId: `configSetLicence`
- 说明注册设备UX 计算并存储 fingerprint - 作用:设置 UX 本地 `licence``fingerprint` 由 UX 本机计算并持久化)
- `POST /api/device/get`
- 操作名:`deviceGet`
- 说明:按 `id``licence` 查询设备
### Crypto
- `POST /api/crypto/encrypt-device-info` - `POST /api/crypto/encrypt-device-info`
- 操作名:`encryptDeviceInfo` - operationId: `encryptDeviceInfo`
- 说明:生成设备授权二维码密文 - 作用使用本地身份licence/fingerprint与输入 `platformPublicKey` 生成授权密文
- `POST /api/crypto/decrypt-task` - `POST /api/crypto/decrypt-task`
- 操作名:`decryptTask` - operationId: `decryptTask`
- 说明:解密任务二维码数据 - 作用:基于 `SHA256(licence+fingerprint)` 解密 AES-GCM 密文
- `POST /api/crypto/encrypt-summary` - `POST /api/crypto/encrypt-summary`
- 操作名:`encryptSummary` - operationId: `encryptSummary`
- 说明:加密摘要并返回二维码内容 - 作用:基于 HKDF + AES-GCM 加密任意明文
- `POST /api/crypto/sign-and-pack-report` - `POST /api/crypto/sign-and-pack-report`
- 操作名:`signAndPackReport` - operationId: `signAndPackReport`
- 说明:上传原始 ZIP返回签名后 ZIP - 作用:上传原始 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` 说明:响应 ZIP 中 `summary.json` 会包含 `timestamp`(服务端生成,毫秒时间戳)
- 文件类型:`application/zip``application/x-zip-compressed`
- 其他业务字段(如 `deviceId``taskId`)与文件一起提交
- 接口响应为签名后 ZIP 文件(`application/zip`
示例curl 示例curl
```bash ```bash
curl -X POST "http://localhost:3000/api/crypto/sign-and-pack-report" \ curl -X POST "http://localhost:3000/api/crypto/sign-and-pack-report" \
-F "deviceId=dev_xxx" \ -F "pgpPrivateKey=-----BEGIN PGP PRIVATE KEY BLOCK-----..." \
-F "taskId=TASK-20260115-4875" \ -F "signingContext=TASK-20260115-4875|702286470691215417" \
-F "enterpriseId=1173040813421105152" \ -F "summaryJson={\"summary\":\"检查摘要\"}" \
-F "inspectionId=702286470691215417" \ -F "outputFileName=signed-report.zip" \
-F "summary=检查摘要信息" \
-F "rawZip=@./report-raw.zip;type=application/zip" \ -F "rawZip=@./report-raw.zip;type=application/zip" \
--output signed-report.zip --output signed-report.zip
``` ```
## 6. 推荐接入方式 ## 5. 字段说明来源
第三方如需代码生成,建议直接消费 `/api/spec.json` 所有接口名称、字段类型、必填项、描述均以 `/api/docs` `/api/spec.json` 为准。
- JavaOpenAPI Generator
- C#NSwag / OpenAPI Generator
- TypeScriptopenapi-typescript / Orval