fix(device): 设备注册绑定接口添加 PoP 验签,照片下载改为设备端本地解密
This commit is contained in:
23
README.md
23
README.md
@@ -66,8 +66,10 @@
|
||||
设备端 后端 用户端
|
||||
│ │ │
|
||||
│── 生成 TEE 密钥对 ──────────│ │
|
||||
│── POST /api/device/register │ │
|
||||
│ {sn, publicKey} ──►│ │
|
||||
│── GET /api/device/challenge│ │
|
||||
│◄── {challenge} ────────────│ │
|
||||
│── POST /api/device/register│ │
|
||||
│ {sn,pubKey,challenge,sig}──►│── PoP 验签(challenge,sig) │
|
||||
│ │── 存储 device(sn, pubKey) │
|
||||
│◄── {deviceId} ─────────────│ │
|
||||
│ │ │
|
||||
@@ -100,8 +102,10 @@
|
||||
设备端(新) 后端 用户端
|
||||
│ │ │
|
||||
│── 新 TEE 密钥对 │ │
|
||||
│── POST /api/device/register │ │
|
||||
│ {sn, newPubKey} ──►│(旧设备自动停用) │
|
||||
│── GET /api/device/challenge │ │
|
||||
│◄── {challenge} ─────────────│ │
|
||||
│── POST /api/device/register │ │
|
||||
│ {sn,newPubKey,challenge,sig}►│(PoP 验签 + 旧设备自动停用) │
|
||||
│◄── {newDeviceId} ───────────│ │
|
||||
│ │ │
|
||||
│ │◄── POST /api/device/sms/send │
|
||||
@@ -336,14 +340,15 @@ TEE 密钥是「**门禁卡**」,UK / DEK 才是「**保险柜钥匙**」。
|
||||
|
||||
### 数据持久化说明(JPA + MySQL)
|
||||
|
||||
设备状态、用户、照片索引已落库,**服务重启 / App 重启均不丢失注册与绑定状态**:
|
||||
设备状态、用户、照片归属已落库,**服务重启 / App 重启均不丢失注册与绑定状态**:
|
||||
|
||||
| 表名 | 对应实体 | 存储内容 |
|
||||
|---|---|---|
|
||||
| `device` | `Device` | 设备注册/绑定状态(SN 唯一、公钥、userId、active) |
|
||||
| `app_user` | `User` | 用户 + UK + 登录密码 |
|
||||
| `encrypted_photo` | `EncryptedPhoto` | 照片元数据(密文仍落盘 `uploads/`) |
|
||||
| `user_photo` | `UserPhoto` | 用户 ↔ 照片索引 |
|
||||
| `encrypted_photo` | `EncryptedPhoto` | 照片元数据 + 归属用户(密文仍落盘 `uploads/`) |
|
||||
|
||||
> 注:早期版本存在 `user_photo` 关联表(`UserPhoto` 实体),已废弃。照片归属统一由 `encrypted_photo.user_id` 承担,查询复用 `findByUserIdOrderByUploadTimeAsc`。
|
||||
|
||||
- 数据库脚本:`springboot-server/sql/schema.sql`(含建库建表 DDL)。
|
||||
- 依赖 `spring.jpa.hibernate.ddl-auto=update` 会在启动时自动建表,也可手动执行 `schema.sql`。
|
||||
@@ -370,11 +375,11 @@ TEE 密钥是「**门禁卡**」,UK / DEK 才是「**保险柜钥匙**」。
|
||||
| Method | Path | 说明 |
|
||||
|---|---|---|
|
||||
| GET | `/api/device/status?sn=xxx` | 查询设备注册/绑定状态(App 启动复用,免重复注册绑定) |
|
||||
| POST | `/api/device/register` | 设备注册(SN + 公钥,幂等:同 SN 同公钥返回原 deviceId) |
|
||||
| POST | `/api/device/register` | 设备注册(SN + 公钥 + PoP 验签 `{challenge, signature}`,幂等:同 SN 同公钥返回原 deviceId) |
|
||||
| POST | `/api/photo/upload` | 上传加密照片(设备签名验签) |
|
||||
| POST | `/api/photo/recover` | 恢复后获取照片 DEK |
|
||||
|
||||
> **注册/绑定幂等说明**:`/api/device/register` 对「同一 SN + 相同公钥」幂等——App 重启后重复注册不会生成新 deviceId,也不会误停用自己;仅当公钥变化(恢复出厂)时才停旧换新。App 启动时建议先调 `GET /api/device/status?sn=xxx`,若 `registered=true` 且 `bound=true`,直接复用返回的 `deviceId`/`userId`,跳过注册与绑定。
|
||||
> **注册/绑定幂等说明**:`/api/device/register` 对「同一 SN + 相同公钥」幂等——App 重启后重复注册不会生成新 deviceId,也不会误停用自己;仅当公钥变化(恢复出厂)时才停旧换新。注册必须携带 PoP(先 `GET /api/device/challenge`,再用 TEE 私钥对 challenge 签名),服务端验签通过才允许注册,防止攻击者用自己公钥冒名注册受害者 SN(P0-1 修复)。App 启动时建议先调 `GET /api/device/status?sn=xxx`,若 `registered=true` 且 `bound=true`,直接复用返回的 `deviceId`/`userId`,跳过注册与绑定。
|
||||
|
||||
### 用户端(需要登录 Token)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user