具体来说,我询问密文是否可以包含诸如 之类的字节序列170303
,这是一种可能的 TLS 记录标头。
通常,解析 TCP 字节流的应用程序通过解析标头并从标头开始后的第 4 个和第 5 个字节中提取八位位组的长度来分隔 TLS 记录。然后,我假设它向前跳过并尝试在由先前解析的标头计算出的偏移量处读取下一条记录。
我的问题是,TLS 1.3 的 AES 256 GCM 实施是否对密码输出施加了任何限制?RFC 没有提及这一点。是否存在以 header 开头170303xxxx
,但也包含170303
密文一部分的 TLS 记录?
除了一些特殊(且非常罕见)的“格式保留”模式外,所有现代加密算法(包括 AES-GCM)都可以处理明文中的任何字节序列,并将任何字节序列生成为密文。(事实上,算法大多可以处理任何位序列,但实现在面向字节的计算机上,大多数只处理字节,特别是因为它们通常是用 C 编写的,而 C 对子字节数据的支持取决于实现。AES-GCM 是一个例外;它由 AES-CTR 和 GMAC 组成,两者都可以处理任何位,但 NIST 指定 GCM 仅处理 8 位字节。可能是因为他们过去在加密实现方面遇到过问题,据称这些加密实现经过了一致性测试,但在边缘情况下仍然失败,而且现在几乎没有人需要甚至想要非字节加密。)
当数据约束适用时——例如通过非 MIME 电子邮件发送密文,或将其存储在某些不支持二进制(又名“blob”数据)的数据库中——通常以满足这些约束的形式对密文进行编码,例如hex、base64、URL安全的base64、base32、base58、base95等。但是SSL/TLS(所有版本)并不要求这样做;在记录级别,它允许正文中的任何字节序列,是的,因此每个记录仅由记录头中指定的长度分隔,而不是由其内容分隔。(某些记录,例如握手子协议中的记录,对其内容确实有限制,但如果加密,这些记录适用于加密之前或解密之后的明文,而不是密文。)
任何可以加密任意二进制数据的分组密码都必须能够在其输出中产生所有字节序列,或者对于至少某些输入,其输出必须大于其输入。但 AES-GCM 产生相同大小的输出并接受二进制输入。
如果有任何限制,它的每字节输出的熵将比完全随机输入的熵要少。即可能的输出值少于 2^n 个,其中 n 是以位为单位的输出长度。这意味着它无法以该长度对 2^n 个可能的输入流中的每一个进行唯一编码。
(这个原则一般来说都是正确的,不仅适用于密码,这也是为什么你不能无损压缩任意随机数据的原因。通常称为鸽巢原则。https: //en.wikipedia.org/wiki/Pigeonhole_principle)