I'M BACK & AEAD

RETURN

Posted by kara on May 12, 2022

回归

奇奇怪怪的标题

看了看上一篇文章更新时间已经是2019年六月,现在已经是2022年五月了。好家伙,咱三年没更…

说起原因的话本来最开始创建这个站点是为了记录一些知识,方便以后用到的时候回来查,但后来慢慢的觉得光是记录的话onenote之类的反而更方便,于是就懒得更新了。但其实折腾这个站点本身也是十分有趣的,包括右下角这只抓包抓出来的kokoro。包括咱现在也有很多需要记录的需求,于是又回来了。

这篇文章不知道写什么好,随便记录一下AEAD的浅显学习吧。

AEAD:新的传输标准

在TLS1.3标准(RFC8446,2018)中,移除了所有独立的对称加密模式和消息认证模式。比如,在TLS1.3标准中,已经不可以使用类似RC4的流式密码,或是工作在各种传统模式下的DES,AES分组密码,取而代之的是一种被称为AEAD(RFC5116, 2008)的新的对称加密结构。TLS1.3作为国际互联网工程任务组(IETF)所制定的标准化传输层安全协议(TLS)的最新版本,是该任务组旗下最重要的安全协议之一,用于保护web等应用层应用,提供加密并确保每个HTTPS网站和API的真实性。TLS1.3中所简化的密码套件协议中对密文加密模式做出了如此重大的修订或许也标志着在互联网端对端加密传输中将传统对称密码与消息认证码单独使用已成为过去式,AEAD将作为更安全的对称加密模式为未来的互联网提供支持。

什么是AEAD?

AEAD即带有关联数据的认证加密(Authenticated Encryption with Associated Data,AEAD)。用于 TLS 连接的常见 AEAD 是 ChaCha20-Poly1305和AES-GCM。在TLS1.3问世之前,一些用于隐蔽和混淆网络流量的基础网络工具中就已经引入了AEAD加密模式,例如未被引入TLS1.3标准的目前最受 libsodium 项目推荐的 AEAD算法XChaCha20-IETF-Poly1305。

AEAD算法 支持两种操作:“密封”和“打开”,即传统意义上的加密与解密。“密封”操作接收以下内容作为输入:

  1. 要被加密的消息,即明文。
  2. 一个密钥
  3. 一个独特的初始向量,也就是IV。它在使用相同密钥的“密封”操作调用之间必须是唯一的,否则密码的保密性将被完全破坏。
  4. 可选的其他一些非秘密的附加数据。这些数据不会被加密,但会被认证。这是 AEAD 中的 AD。

“密封”操作使用密钥和IV,使用底层密码将明文加密成等长的密文。对于 ChaCha20-Poly1305,底层密码是 ChaCha20,而对于 AES-GCM,底层密码是 Counter 模式下的 AES (AES-CTR)。

明文被加密后,“密封”操作使用密钥(以及可选的$IV$)生成二级密钥。二级密钥用于生成 AD的一段引入密钥的哈希值、密文和各自的对应长度。 ChaCha20-Poly1305 中使用的散列算法是 Poly1305,而 AES-GCM 中使用的散列是 GHASH。

最后一步是获取哈希值并对明文进行加密,生成最终的 MAC(消息认证码)并将其附加到密文中。

“打开”操作与“密封”相反。它采用相同的密钥和 IV 并生成所输入的密文和 AD 的 MAC,类似于“密封”所做的操作。然后读取密文后附加的 MAC,并比较两者。 MAC 值的任何差异都意味着密文或 AD 被篡改,这样的密文应该被视为不安全而被丢弃。反之,如果两者匹配,则操作解密密文,返回原始明文。

AEAD实例分析

下文以ChaCha20-Poly1305算法实例详细解释AEAD算法流程:

avatar

如图所示,ChaCha20-Poly1305加密流程的输入和输出为以下数据:

  1. 输入:
    1. K 32bytes的密钥
    2. Nounce 12bytes的一次性数据
    3. M 明文
    4. AD 追加的认证数据。使用通信双方已从通信内容中得到的信息。例如,在TLS1.3中使用加密传输的数据长度。
  2. 输出:
    1. C 密文
    2. T 16bytes的认证标签

ChaCha20-Poly1305的底层是用ChaCha20流密码对明文进行加密的,但是其计数器(Counter)是从1开始进行加密的。当计数器为 0 时,使用左侧密钥流的 32 个byte作为 Poly1305 的一次性密钥。

提供给散列算法Poly1305 的认证数据由以下六项组成。其中,“len()”表示byte数。

  1. AD追加的认证数据
  2. pad(AD)将AD的长度填充至16的倍数的填充值
  3. C 密文
  4. pad(C)将C的长度填充至16的倍数的填充值
  5. len(AD) AD的长度
  6. len(C) C的长度
  7. 以上为ChaCha20-Poly1305的加密和认证标签的创建流程,下文将针对解密和认证流程进行展开:

avatar

如图所示,ChaCha20-Poly1305解密流程的输入和输出为以下数据:

  1. 输入:
    1. K 32bytes的密钥
    2. Nounce 12bytes的一次性数据
    3. C 密文
    4. 认证标签 T
    5. AD 追加的认证数据。使用通信双方已从通信内容中得到的信息。
  2. 输出:
    1. 验证通过时:明文M
    2. 验证失败时:错误信息

输入的密文与 ChaCha20 密钥流进行异或运算生成明文。另外,输入的密文经过Poly1305算法认证,验证没有被篡改(如padding oracle攻击)。这就是ChaCha20-Poly1305作为AEAD的功能体现。

对于ChaCha20-Poly1305所使用的一次性数据Nounce,其作用等同于初始向量IV,但两者并不完全相同。IV与Nonce之间的区别主要体现在不同的加密方案的侧重点上。有些方案所需要的只是密文不重复,这种情况我们通常叫作Nonce;还有一些方案需要密文是随机的,甚至完全不可预测的,这种情况我们通常叫作IV。Nounce和IV的应用体现了密码学的基本原则之一:不能把多条消息用同一种编码方式进行加密。否则,两条相同的明文会有相同的密文,这是个危险的漏洞。

选择AEAD的原因

回溯过去的对称加密方案,在更早期的传统协议中,最大的缺陷就是没有对数据包完整性进行校验,再加上流加密的特点,导致了攻击者可以通过穷举的方式修改密文进行基于服务器行为的主动探测。

在通常的密码学应用中,保密性用加密实现,消息认证用 MAC实现。这两种算法的配合方式,引发了很多安全漏洞,过去曾经有 3 种方法:

  1. 加密和消息认证 Encrypt-and-MAC(E&M)
  2. 消息认证然后加密 MAC-then-Encrypt(MtE)
  3. 加密然后消息认证 Encrypt-then-MAC(EtM)

Encrypt-and-MAC (E&M)基于明文生成MAC,并且明文在没有MAC的情况下被加密。明文的MAC和密文一起发送。用于例如SSH。E&M方法本身并未被证明是“强不可伪造”的。

MAC-then-Encrypt (MtE) 基于明文生成MAC,然后将明文和MAC一起加密生成密文。密文(包含加密的MAC)被发送。MtE方法本身并未被证明是“强不可伪造”的。[1]尽管有理论上的安全性,但在实际应用中应使用MAC-then-pad-then-encrypt,即明文先填充到加密函数对应的块大小。填充错误通常会导致接收方发现可检测到的错误,从而导致密文填塞攻击(Padding oracle attack),如Lucky Thirteen attack。

Encrypt-then-MAC (EtM)首先对明文进行加密,然后根据得到的密文生成MAC。密文和它的MAC一起发送。这是唯一形式化证明可以达到认证加密安全性最高定义的方法,但这只有在使用的MAC“强不可伪造”时才能实现。[2]

如上文所述,E&M 和 MtE 均被证明存在安全问题。[3][4] 2008 年起, 逐渐提出了「用一个算法在内部同时实现加密和认证」的算法,称为 AEAD。在 AEAD 这种概念里,cipher + MAC 的模式被一个 AEAD 算法替换。使用了 AEAD 算法的新协议本质上就是更完善的对称加密和消息认证,通过更完善的数据包完整性验证机制杜绝了上面所述的可被篡改密文的可能性。

AEAD 的特殊之处在于它们将两种算法(加密和 MAC)组合成一个原语,并具有可证明的安全保证。在AEAD之前,可以接受一些独立被认为是安全的加密算法和一些MAC,并将它们组合成一个不安全的组合。例如,某些组合通过重用相同的密钥进行加密和 MAC(AES-CBC 和 CBC-MAC)而容易被攻破,而其他组合则是通过在明文上执行 MAC 而不是在密文上。如早期版本的TLS 所使用AES-CBC和HMAC的组合。

对称加密算法的选择

对于加密方案、算法来说,一般而言安全性与性能呈负相关,越是安全的加密方案,对性能要求则更高。在实际应用中,主流的加密协议的安全性均能达到现阶段的安全性标准,更多所做的是一个取舍问题,即如何平衡安全性和性能开销问题。

AEAD算法将加密部分和消息认证部分组合成了一个原语,相当于提供了一个黑盒子,对外只提供了易于使用的编程接口,程序员无需考虑如何选择加密算法和消息认证算法以及用何种方式将他们组合起来。与此同时,AEAD在性能上会造成10\%左右的额外开销,对于本身计算效率远超现阶段普遍传输速度的对称加密而言,这些性能开销在大多数情况下都可以忽略不计。对于绝大多数的互联网应用和端对端传输场景,都推荐使用AEAD算法代替传统的对称加密模式,正如TLS1.3所强调的。

一些情况下对传输层安全性并不需要太高的要求,比如在可信的内网(LAN 或 IPLC 线路)使用,则不必过多担心安全问题,RC4-MD5 加密协议将是非常节省性能的选择。除此之外,在路由器或是其他低算力物联网设备的应用场景下,很多设备的 CPU 的运算速度都在 500MHz 以下,并且不支持 AES 硬解,所以,在这类设备上的加密方式一般都选 ChaCha20 或 RC4-MD5等算法。

尚待解决的问题

尽管从提出到现在已经过了10年以上的时间,AEAD算法仍在广泛应用的最前沿。直到最近,唯一使用的标准 AEAD 是 AES-GCM。TLS1.3将 ChaCha20-Poly1305加入了AEAD标准算法行列当中,越来越多的客户端将会向服务器请求 使用这个算法。问题在于如果有人攻破了 GCM 模式,我们便只能选择 ChaCha20-Poly1305;相对应的,如果有人发现了Poly1305的漏洞,则只能使用AES-GCM,这对没有AES优化的硬件或是MIPS指令集的硬件来说非常不友好。TLS1.3标准非常强硬的将前版本遗留的庞大的密码套件库一并删除,只留下了使用AEAD的拓展协议,如果在将来某个时候发现这些参数不安全时,就很难更新协议。

ChaCha20 或 Poly1305 都不是新的发明。两者都是丹尼尔·J·伯恩斯坦 (DJB) 的想法。ChaCha20 基于 DJB 开发的一种名为 Salsa 的早期密码,该密码可追溯到 2005 年。[5][6] ChaCha20本身是2008年发布的,对Salsa中的回合数稍加修改,数字20表示总共重复了20轮。[7] 与 AES-CTR 类似,ChaCha20 是一种流密码。它根据递增的计数器生成一个伪随机比特流,然后将流与明文“异或”以对其进行加密(或与密文“异或”以进行解密)。因为不需要提前知道明文来生成比特流,所以这种方法使得两者都非常高效且可并行化。 ChaCha20 是一个 256 位密码。

Poly1305 于 2005 年发布[8]。Poly1305 是一个 MAC,可以与任何加密或未加密的消息一起使用,以生成带密钥的认证标签。此类标签的目的是保证给定消息的完整性。最初Poly1305使用AES作为底层密码(Poly1305-AES);现在它更多的与ChaCha20共同使用。同样,与 GHASH 类似,它是多项式哈希。与 GHASH 不同的是,它的密钥 会随着每条新消息而变化,因为它取决于随机的初始向量 IV。当 DJB 开发这个 MAC 时,他使它特别适合在当时的 CPU 上存在的浮点运算器上高效执行。今天,使用 64 位整数指令执行的效率要高得多,现在的设计可能略有不同。

从那以后的几年里,两者都受到了密码学社区的严格审查,今天被认为是完全安全的,尽管有人担心当一个人负责行业中的如此多的标准时可能会丧失多元性(DJB 也负责 Curve25519密钥交换协议,TLS1.3中主要的握手协议之一)。

对于现阶段的密码方案,很多设计缺陷都是使用形式化分析时发现的。学者们尝试证明TLS的完全安全特性,反而却发现了一些反例,变成了真正的漏洞。这些缺陷遍布了纯理论的漏洞(SLOTH 和 CurveSwap),到资源丰富的攻击者可实施的可行漏洞(WeakDH, LogJam, FREAK, SWEET32),再到可实现的重大危险漏洞(POODLE, ROBOT)。

最后尝试为本博客添加MathJax的tex数学公式支持。哪天看到下面公式渲染成功了就说明咱的渲染成功了。

Marry has a little matrix $ ( \begin{smallmatrix} a&b\ c&d \end{smallmatrix} ) $.

Marry has a little matrix \( ( \begin{smallmatrix} a&b\ c&d \end{smallmatrix} ) $.

\[E=mc^2\]