Skip to content

方法Method

密码协议字段的无歧义编码

Cryptographic protocol field encoding · Length-delimited transcript encoding

规定字段类型、长度和解析边界,用可逆编码把语义元组唯一映为认证字节,并拒绝截断、尾随及多重解释。

形式陈述 ​

密码算法处理字节串,而应用处理“版本、身份、消息类型”等有意义的字段。先固定一个合法元组集合 D,定义编码 E:D→{0,1}∗ 和从字节串到合法元组的部分解析函数 P;P 只在被接受的串上有定义。本页要求两条合同:对所有 x∈D,P(E(x))=x;对所有被接受的串 b,E(P(b))=b。第一条给出往返正确性并推出 E 单射;第二条规定接受的字节表示必须规范,排除不同字节串被悄悄当作同一对象。

本单元的教学编码先写两字节大端无符号字段数 n,随后按顺序写每个字段的四字节大端长度和字段本身:

E(x1,…,xn)=u16(n)‖∏i=1n(u32(|xi|)‖xi).

这里 ‖ 和连乘形符号都表示拼接;长度以字节计,不是汉字个数。为限定资源,本例再规定 n≤65535、每字段长度不超过65535字节。每种消息固定预期字段数、类型、顺序和总大小上限;计数正确仍不意味着字段语义有效。序号字段必须恰为八字节,身份是固定ASCII教学标识,版本是一个约定字节串。

解析时先验证输入中还有完整长度字,再检查长度不超过上限与剩余字节数,才读取字段;最后要求全部输入被消费。整数加法不得溢出。真实流式解析还需要总帧长度与缓冲预算,不能仅因长度前缀是32位就准许分配4 GiB。

直觉

签名或MAC只能承诺它实际收到的字节。若两个不同的业务请求在编码阶段已经变成同一字节串,后面使用再强的哈希也无法区分它们。这不是找到了密码哈希碰撞,而是应用自己丢失了边界。

长度前缀相当于给每个盒子写上尺寸;类型和消息阶段则告诉接收者盒子里应该是什么。只有尺寸、没有固定字段含义,仍可能把“发送者”误作“接收者”。因此编码合同与协议解释合同都要明确。

例子与边界

裸拼接把 (ab,c) 与 (a,bc) 都变成 abc。教学编码分别是:

  • 0002 00000002 6162 00000001 63
  • 0002 00000001 61 00000002 6263

空格只为阅读,不是线上字节。第一个串先声明两个字段,再读取长度2与长度1;第二个依次读取1与2,所以解析结果不同。空字段也合法但不等于缺字段:E()=0000,E(ϵ)=0001 00000000。

证明往返时,读取计数得到同一个 n;归纳到第 i 个字段,由已读前缀长度已确定,下一长度字唯一给出 |xi|,其后恰好读出 xi。最后没有尾随字节,故还原整元组。由 E(x)=E(y) 两边应用 P 得 x=y,完成单射证明。

只保留最后一字节之前的前缀必须拒绝;给合法串追加 00 也必须拒绝。若前端忽略尾随字节而签名检查使用完整串,或两端对重复JSON键采用不同优先级,双方可能认证相同输入却执行不同对象。Unicode归一化、大小写和数字表示应在规格中决定;不能在验证后临时“清理”成另一种语义。

推论与应用

握手 transcript、KDF info、签名上下文与AEAD关联数据都可以复用这项编码接口,但每种消息必须有自己的域或类型标签。编码提供确定的对象边界,不提供保密、认证、随机性或安全版本协商。

会话实验中的 enc/dec 用本规格检查往返、两种 abc 元组、截断和尾随输入。有限测试用来查实现错误;上面的归纳论证才解释任意合法字段序列为什么不会混淆。生产协议通常已有成熟编码,不能为使用本例而私自替换线上格式。

设字段数为n、总payload长度为m,采用一次汇集或线性缓冲器,编码与完整复制解析需 O(n+m) 时间,输出占 2+4n+m 字节;解析器仅返回切片时仍须读取和校验各边界。检查器使用列表汇集后join,避免反复拼接不可变字节串造成一般n下的平方复制成本。

参考资料
  • Eric Rescorla,RFC 8446,§3的向量长度编码、§4.4.1的握手transcript:长度与类型参与协议字节语义;本页自定义教学格式并非TLS线格式
  • David McGrew,RFC 5116,§3.3:关联数据中多项字段必须可无歧义解析
关系图谱8 个相邻概念 · 1 类关系

拖动节点调整位置。

显示关系

显示:依赖

  1. 前置三跳
  2. 前置二跳
  3. 前置一跳
  4. 当前条目
  5. 后续一跳
  6. 后续二跳
  7. 后续三跳
文字版关系按与当前条目的最短距离分组