Define license verification task (T-502)

This commit is contained in:
ila
2026-07-20 01:12:04 +08:00
parent 8d81276fd9
commit c51ff30c54
6 changed files with 76 additions and 9 deletions
+9 -4
View File
@@ -319,10 +319,15 @@ Windows 平台用 Toolhelp32 快照枚举,并以 `QueryFullProcessImageName`
}
```
- `machine_hash` v1 固定为平台层对两个必需的瞬时来源计算的 64 字符小写 SHA-256:去首尾空白并小写化的 36 位 ASCII `MachineGuid`、以及 Windows 目录所在卷的 8 位小写十六进制序列号,以 `"softbox.machine-hash.v1\\x00" || guid || "\\x00" || volume_serial` 为输入。任一来源读取/规范化失败即拒绝,不存在单来源、MAC、加权或环境变量回退;许可证、存储、事件、UI 和日志均**不保存**原始 GUID、卷序列号或 MAC。
- 客户端用内置 Ed25519 公钥离线验签;许可证保存于 `licenses/`,与程序文件、用户配置分离;更新不得覆盖。
- 撤销名单同样签名并缓存,网络失败保留宽限期。
- 盒子负责导入/展示/管理;**子软件必须用 sdk 的 licensing 逻辑独立再验证**(签名 + machine_hash + product_id),决定正式版/试用版/授权错误。
### 3.1 License v1 wire contract
License v1 只允许示例中的九个顶层字段,全部必需,禁止未知或重复字段。`license_id` 匹配 `^lic-[a-z0-9][a-z0-9-]{0,59}$`;`products` 至少有一个、无重复、每项匹配软件包 `app.json` `product_id` 的 `^[a-z0-9-]+$`;`machine_hash` 必须是 64 位小写 hex;`issued_at` 必须精确为 `YYYY-MM-DDTHH:MM:SSZ`;`update_policy` 与 `rebind_policy` 均匹配 `^[a-z0-9][a-z0-9._:-]{0,127}$`。`schema_version` 只能为 `1`。
签发端先删除顶层 `signature`,再以 Catalog v1 相同的受限 canonical JSON 生成 signing bytes:输入必须是有效 UTF-8、无未配对 JSON surrogate、无重复 object key,且数字只能为非 `-0` 的十进制整数;递归按 object key 字典序输出、没有非必要空白。`signature` 是对该字节串的 Ed25519 签名,编码必须是**精确 canonical 的标准 padded Base64**(64 个签名字节)。`testdata/license/` 的静态 corpus 是跨实现的规范向量;不得签原始 JSON 文本或仅部分字段。
验证器先拒绝不安全 JSON/签名,再严格验证字段与签名,最后将许可证中的 hash 与调用方从 T-501 得到的 64 位小写 expected hash 精确比较。未配置或非法 public key、任何格式/验签失败、hash 不匹配、未知产品均 fail closed;错误、事件和 UI 不得包含 license JSON、signature、license ID 或任何原始机器来源。`machine_hash` v1 固定由短暂读取的规范化 `MachineGuid` 与 Windows 目录所在卷序列号生成:`SHA-256("softbox.machine-hash.v1\\x00" || guid || "\\x00" || volume_serial)`;许可证、存储、事件、UI 和日志均**不保存**原始 GUID、卷序列号或 MAC。
T-502 的 core verifier 接收调用方注入的 public key 和 expected hash;当前仓库没有生产 trust root,不能以测试 key、环境变量或 allow-all 代替。`perpetual`、update/rebind policy 在本任务只作为已签名元数据,不实施过期、trial、撤销名单、宽限期或 rebind 决策。许可证文件保存于 `licenses/` 且更新不得覆盖,但文件导入/存储、授权页面和启动用例接线留给 T-503;届时盒子和子软件都必须独立再验证签名、machine_hash 与 product ID。
## 4. application 事件合约(core → UI)