第 7 章 安全与加密

7.1 安全模型

DTP 实现 必须 提供端到端加密。安全模型 必须 满足以下不变量:

  1. 仅目标 iFay 实例 必须 能够解密接收到的 Payload。
  2. FayGer 运行时环境 不得 在任何情况下访问明文数据。
  3. 中间网络节点 不得 读取 Payload 明文。
  4. DTP 实现 不得 自行管理加密密钥。

7.2 加密范围

加密范围 必须 严格限定于 LogicalFrame 的 Payload。

7.2.1 必须加密的内容

以下数据 必须 加密:

  • LogicalFrame 的 payload 字段(即 Fragment 的 data 字段以及(若以 Frame 方式承载的)RequestFrame、ResponseFrame、ControlFrame 的内容)。

7.2.2 不得加密的内容

以下数据 不得 加密,必须 以明文传输:

  • LogicalFrame 的 header(包括 protocolVersionframeTypefragmentIdagreementIdoriginTimestampdagDependenciesencryptionMetadatasequenceNumber)。

加密元数据本身 不得 加密,以使接收方能在解密前确定解密参数。

7.3 密钥管理

7.3.1 密钥来源

DTP 实现 必须 使用 CAP 预协商的密钥。具体要求:

  1. CAP 必须 在连接建立阶段完成身份验证与密钥交换。
  2. DTP 实现 必须 使用 CAP 提供的 sessionKey 进行 Payload 加密/解密。
  3. DTP 实现 不得 自行生成、协商或交换加密密钥。

7.3.2 CAPContext 接口

DTP 实现 必须 通过以下接口接收 CAP 提供的上下文:

interface CAPContext {
  identity: string;
  sessionKey: Uint8Array;
  verified: boolean;
}
字段规范性要求
identity必须 为对端身份标识
sessionKey必须 为 CAP 协商出的会话密钥的字节序列
verified必须 反映 CAP 验证状态

7.3.3 CAP 前置条件

DTP 实现 必须 在开始数据传输前验证 CAPContext:

  1. verified === false必须 拒绝发送任何数据帧并返回 KEY_NOT_READY 错误(2002)。
  2. sessionKey 为空或长度无效,必须 返回 KEY_NOT_READY 错误。
  3. 协商帧(Request_Frame、Response_Frame)的传输 同样 受此前置条件约束。

7.4 加密元数据

每个 LogicalFrame 的帧头 必须 携带 EncryptionMetadata:

interface EncryptionMetadata {
  algorithm: string;
  keyVersion: number;
}

7.4.1 算法标识符

algorithm 字段 必须 为加密算法的标识字符串。 使用以下标准化命名之一:

标识符算法状态
"AES-256-GCM"AES-256 in Galois/Counter Mode推荐
"ChaCha20-Poly1305"ChaCha20 with Poly1305推荐
"AES-128-GCM"AES-128 in Galois/Counter Mode 使用

实现 必须 至少支持 AES-256-GCMChaCha20-Poly1305 中的一种。推荐 同时支持两种以增强互操作性。

实现 不得 使用:

  • ECB 模式(不安全)
  • 无认证的加密模式(CBC、CTR 不带 MAC)
  • 已知存在弱点的算法(DES、3DES、RC4)

7.4.2 密钥版本号

keyVersion 必须 为非负整数,用于支持密钥轮换:

  1. 当 CAP 触发密钥轮换时,新密钥的 keyVersion 必须 严格大于上一个版本。
  2. 接收方 必须 使用 keyVersion 选择对应的解密密钥。
  3. 实现 维护至少一个旧密钥版本以支持飞行中(in-flight)的 Fragment。

7.5 加密往返一致性

实现 必须 满足以下加密往返一致性属性:

  1. 使用正确密钥(与发送方使用的密钥匹配)加密后再解密,必须 产生与原始 Payload 字节级相同的输出。
  2. 使用错误密钥解密 必须 失败,必须 返回 DECRYPTION_FAILED 错误(2001)。
  3. 解密失败时,实现 不得 返回部分解密结果或损坏的数据。

7.6 终端侧解密

当终端作为接收方时(数据注入场景):

  1. DTP_Slave 必须 使用终端在 CAP 连接建立阶段提交的密钥进行解密。
  2. 该密钥 必须 与终端在 CAP 中提交的私钥/会话密钥对应。
  3. 终端 不得 接受任何其他密钥的解密结果。

7.7 解密失败处理

实现 必须 按以下规则处理解密失败:

  1. 单次解密失败:丢弃帧,发送 DECRYPTION_FAILED 错误通知(2001)。
  2. 连续解密失败超过阈值(实现定义,推荐 为 3 次): a. 触发 CAP 重新密钥交换。 b. 通知上层应用安全异常。
  3. 实现 不得 在多次解密失败后无限重试同一帧。

7.8 安全威胁防护

实现 必须 通过协议设计防护以下威胁:

威胁防护机制
中间人窃听Payload 端到端加密
FayGer 窥探Payload 加密,FayGer 仅可见密文
密钥泄露密钥版本号机制支持密钥轮换
身份伪造委托给 CAP 验证
重放攻击序列号单调递增 + 会话绑定
帧篡改使用认证加密(AEAD)算法

7.9 重放保护

实现 必须 通过以下机制防护重放攻击:

  1. 序列号单调递增:接收方 必须 拒绝序列号小于或等于已确认最高序列号的帧(除非处于续传场景)。
  2. 会话绑定:序列号空间 必须 与具体会话绑定。新会话 必须 重置序列号。
  3. AEAD 认证:加密算法 必须 提供消息认证(GCM、Poly1305 等)。

7.10 元数据隐私

实现 注意:帧头中的明文元数据 可能 泄露以下信息:

  • 通信对端身份(通过 agreementId 关联)
  • 通信时间模式(通过 originTimestampsequenceNumber
  • 数据传输频率(通过帧之间的时间差)

实现 通过以下方式增强元数据隐私:

  1. 启用流量填充(实现定义)。
  2. 使用混淆传输层(如基于 TLS 1.3 的 ECH)。

但本规范 不要求 实现提供元数据隐私保护。