它要解决什么
传统接入机制解决"你是谁",自治平台还要解决"你带着什么规则、能写哪里"。只校验身份的实现,会放行携带过期规则的合法节点。
身份可仿冒
匿名或自签节点混入集群,后续脏数据无法归因到具体节点。
权限无处下发
身份合法不等于可写。权限需由服务端在握手时裁决并绑定到会话。
规则集不同步
节点载着三天前的元规则接入,仍按旧规则写共享资产——最隐蔽的一类破坏。
协议不替代 TLS:传输层的机密性由 TLS 提供,AHP 叠加的是节点身份语义、权限视图、认知版本这三件 TLS 不回答的事。
三层信任,失效半径不同
把"谁来签、签什么、用多久"拆成三层,目的是让一次泄露不波及全域。
根信任锚
私钥离线,仅签发节点凭证;生产环境置于 TEE/TPM 只读边界内,签名运算不出安全区。
节点凭证 NodeCred
DID + 角色 + 权限位 + 有效期 + 根签名。有效期必须在签名覆盖范围内,否则改期即越权。
会话临时密钥
每次握手新生成 X25519 密钥对,会话销毁即丢弃;长期私钥不参与协商。
四阶段流程
四个往返内完成身份、权限、认知、密钥四件事。失败分支只回标准错误码,不回原因。
签名域与密钥派生
签名不覆盖线路编码,只覆盖一段确定性字节串——同一报文可换 protobuf / JSON / 总线消息体上线而不破坏验签。
// scope:被签名的确定性字节串,长度恒定 AHP/1.0 | CMD | DID | b64(nonce) | ts | b64(epk) | SHA256(canonical(payload)) | sid // 会话密钥:双向 Nonce 都进盐,跨会话不可能复用同一 SK SH = X25519(sk_eph_own, pk_eph_peer) SK = HKDF-SHA256(SH, salt = nonce_c ‖ nonce_s, info = "AHP1-SESSION-KEY", L = 32) // 会话标识由密钥推导,两侧可独立复算,审计不依赖单点记录 SID = "SID-" + SHA256(SK ‖ nonce_s)[:16]
sid 进入签名域的直接收益:把已授权报文搬到另一个会话(跨会话重放)时签名失配,攻击者无法用旧会话的授权帧操作新会话。
认知版本协商
把规则集按层聚合成 baseline_id,节点在 HELLO 中声明它接受的基线,网关逐层比对,得出三态。漂移不拒绝,而是降级。
基线一致
按角色发放会话与完整 perm_mask。
基线漂移
会话仍建立,但收敛为 0x0002 只读位;写路径不可达,裁决必须落审计。
硬校验失败
凭证、签名、版本不通过,不建会话,外部只回码。
为什么不直接拒绝:吊销会促使下游绕过受控入口去裸写共享资产,风险反而放大。保留读能力,节点取到新基线后重签,形成收敛路径。基线口径的三个坑写在白皮书 §6:按内容元字段归层、覆盖所有存放地、文件数与条目数分开统计。
错误码
外部只回码与枚举名;细分原因(过期 / 伪签 / 借壳)只进内部日志,避免用错误差异做凭证探测。
| 码 | 名称 | 触发 |
|---|---|---|
| 0x81 | HELLO_REJECT | 凭证非法/过期、DID 不一致、黑名单、时钟偏移、报文签名失败 |
| 0x82 | ACK_FAIL | 节点侧校验网关凭证或应答签名失败 |
| 0x83 | READY_INVALID | 协商失败、GCM 认证失败、Nonce 回显不符 |
| 0x84 | PERM_DENY | 角色 tier 不足(含降级后的写操作) |
| 0x85 | VERSION_MISMATCH | 协议版本不兼容,含降级尝试 |
| 0x86 | REPLAY | Nonce 重复,或应答回显不匹配 |
| 0x87 | SESSION_FULL | 网关会话容量达上限 |
| 0x88 | BREAKER | 会话被熔断隔离 |
| 0x89 | SESSION_UNKNOWN | SID 不存在、已销毁或已过期 |
STRIDE 威胁矩阵
六类威胁、24 条渗透用例。残余风险最高的一条不在密码学里,而在审计存储可被删改。
三条已识别的攻击链:合法身份 + 过期认知(断链点:降级只读)、Nonce 表投毒(断链点:先验签后记 Nonce)、中间人诱导改参数(断链点:全字段签名 + 回显绑定)。
实测验证
参考实现纯标准库 + cryptography,本地执行 python3 selftest.py。判据为「返回码 + 台账事件 + 密钥状态」三者一致,不只看返回码。
| 用例 | 场景 | 期望 | 实测 | 结果 |
|---|---|---|---|---|
| C01 | 标准四阶段握手 | 会话建立 | sid=SID-f465a… | PASS |
| C02 | 心跳保活 → BYE 销毁 | PONG + 密钥销毁 | pong=True sessions=0 | PASS |
| C03 | 原样报文重放 | 0x86 | 0x86 | PASS |
| C04 | 载荷篡改(签名不符) | 0x81 | 0x81 | PASS |
| C05 | 凭证过期 | 0x81 | 0x81 | PASS |
| C06 | 节点黑名单 | 0x81 | 0x81 | PASS |
| C07 | 协议版本降级 | 0x85 | 0x85 | PASS |
| C08 | 时间戳超窗 −120s | 0x81 | 0x81 | PASS |
| C09 | 非会话密钥加密 READY | 0x83 | 0x83 | PASS |
| C10 | 心跳密文篡改 | 0x83 + 熔断 | 0x83 sessions=0 | PASS |
| C11 | 认知基线过期 | 建会话仅读位 | perm=0x2 downgraded=True | PASS |
实现过程中暴露的两个真实缺陷一并留档:AES-GCM nonce 拼接错误(库函数只返回密文+标签,取前 12 字节当 nonce 必然解密失败)、cmd 字段类型漂移(信封用整型码、签名域用枚举名,往返缺转换导致验签域拼接错误)——后者正是"签名域必须显式规范化"的现实理由。
交付与锁档
| 交付物 | 内容 |
|---|---|
| AHP-01_白皮书.md | 13 章规范 + 附录:信任模型、报文、签名域、生命周期、部署清单、与 TLS/mTLS/OIDC 对比 |
| proto/ahp01.proto | proto3 报文定义:Envelope / NodeCredential / Hello / HelloAck / Ready / ReadyAck / Reject |
| reference/*.py | 网关 + 节点 + 公共层 + 自验脚本,11 条用例可复跑 |
| 威胁矩阵.md | STRIDE 六类 × 资产/攻击面,24 条渗透用例 + 覆盖矩阵 + 判定规范 |
| 本页 | 规范速览,供评审与对外沟通;无外部依赖,可直接双击打开 |
锁档口径:全部交付物计算 SHA-256,汇总为清单并推导 Merkle 根;清单与根值随交付一并留档,供后续比对是否被静默改写。