C++ 中的 ChaCha20 流密码

2025年5月10日 | 阅读11分钟

引言

流密码是现代密码学中的一项基本功能,可确保对应用程序中对速度和灵活性有要求的应用程序提供数据机密性。ChaCha20 流密码是该领域中最受欢迎的算法之一。此密码的创建者 Daniel J. Bernstein 于 2008 年作为 Salsa20 的修改版开发了它,并在安全性与性能方面得到了显著改进。本文将探讨 ChaCha20 流密码、其结构以及在 C++ 中的实现。

问题陈述

为了在 C++ 中应用 ChaCha20 流密码,需要什么才能确保我们拥有可行且安全的加密-解密机制?我们可以将这些问题纳入解决我们主要问题之中,即 ChaCha20 在 C++ 中的实现,也就是它的构造、工作方案以及主要组件(如初始化、块布局以及密钥元素的包含和如何在 C++ 源代码中管理它们)的集成。

背景

ChaCha20 允许加密密钥和解密密钥相同。这意味着它是一种对称流密码。它会构建一个称为密钥流的伪随机字节序列。然后,通过 XOR 将密钥流与明文结合以获得密文。由于密钥流是确定性的,因此当使用相同的密钥和 IV 时会生成相同的密钥流,从而使解密变得容易,因为对密文执行所需的 XOR 操作将产生原始明文。

ChaCha20 的核心由几个元素构成,包括以下几点。

  • 密钥:单个 256 位(32 字节)密钥
  • Nonce:96 位(12 字节)Nonce,绝不重复使用。它对于防止密钥流重用至关重要。
  • 计数器:32 位计数器,通常设置为零,这使得 ChaCha20 能够流式传输长流而不会重复密钥流块。

ChaCha20 是完全安全的,并且能够抵御旧的流密码(如 RC4)可能会屈服的特定攻击。此外,它被设计为可在现代硬件中使用,并且在 HTTPS 和 VPN 等软件应用程序中越来越受欢迎。

解决方案:C++ 中的 ChaCha20 算法

现在,我们将逐步演示如何在 C++ 中实现 ChaCha20。在此实现中,我们将重点介绍 ChaCha20 的结构,包括初始化过程、核心四分之一轮函数的应用以及密钥流的生成。

1. 四分之一轮函数

ChaCha20 核心的四分之一轮中有一个重要的轮函数,它通过加法、XOR 和位旋转进行操作。此四分之一轮应用于由 32 位整数组成的 4x4 矩阵,这些整数来自密钥、Nonce 和计数器。

ChaCha20 的四分之一轮函数形式如下:

a += b; d ^= a; d <<<= 16;

c += d; b ^= c; b <<<= 12;

a += b; d ^= a; d <<<= 8;

c += d; b ^= c; b <<<= 7;

在 C++ 中,我们可以这样写:

2. ChaCha20 块函数

块函数通过将 ChaCha20 轮应用于初始状态矩阵,为每个计数器值生成 64 字节的密钥流。

初始状态矩阵的构建如下:

  • 前 16 字节:常量“expand 32-byte k”
  • 接下来的 32 字节:密钥
  • 接下来的 4 字节:计数器
  • 最后 12 字节:Nonce

然后,该函数应用 20 轮 ChaCha(10 轮“双轮”四分之一轮),混合并转换状态。

3. 使用 ChaCha20 加密数据

实现了块函数后,加密就变成了生成密钥流并将其与明文数据进行 XOR 的问题。

程序 1

输出

 
Ciphertext: 6a 2a 3d 9f 2f 37 f9 b6 40 ac 4b b 99 
Decrypted text: Hello, World!   

说明

  1. 初始化:包含 AES 常量以及 S-box 和 Rcon 的预计算值。
  2. 关键扩展:这是从原始 256 位密钥派生密钥计划的过程,该密钥计划可用于 AES 的所有轮。
  3. 加密步骤
    • 我们实现 AddRoundKey、SubBytes、ShiftRows 和 MixColumns,它们是对 AES 状态的微小转换。
    • 加密使用 CBC 模式将每个明文块与前一个密文块进行 XOR。
  4. 解密步骤
    • 它与加密步骤的顺序相反。
    • AES 加密/解密块:转换由 AES 中轮组成的单个块。
  5. CBC 模式:使用初始化向量连接加密和解密块。

程序 2

输出

 
Ciphertext: 6a 2a 3d 9f 2f 37 f9 b6 40 ac 4b 0b 99 
Tag: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   

说明

  1. 四分之一轮和块函数:quarterRound() 和 chacha20Block() 函数执行 ChaCha20 的 20 轮排列,生成 64 字节的密钥流。
  2. 加密函数:chacha20Encrypt() 函数将明文作为数据输入,并通过与 ChaCha20 密钥流进行 XOR 来对其进行加密。
  3. HChaCha20 函数:hchacha20() 函数允许选择性地派生子密钥以备将来使用。
  4. Poly1305 认证标签:poly1305Auth() 函数将使用 Poly1305 对密文进行身份验证,但在本例中仅使用占位符数组。
  5. ChaCha20-Poly1305 加密:chacha20Poly1305Encrypt() 函数可以首先使用 ChaCha20 进行加密,并使用 Poly1305 生成认证标签。

ChaCha20 与其他算法的比较

1. ChaCha20 与 AES

然而,尽管 ChaCha20 和 AES 是当今最流行的两种密码,但它们在构建、设计和预期用途方面存在巨大差异。

关键区别

  • 速度:在不包含 AES 硬件加速(AES-NI)的平台上,ChaCha20 的性能更高,例如手机和低功耗 IoT 设备。
  • 防计时攻击:由于其架构,ChaCha20 可抵抗计时攻击,而 AES 则可能被攻击,如果未采取足够的措施。
  • 易于实现:与 AES 相比,ChaCha20 更易于安全实现,因为没有填充和操作模式。

用例

  • ChaCha20 主要用于移动、便携式和轻量级应用程序、VPN(如 WireGuard)以及防计时攻击的协议。
  • AES 是几乎所有解决方案的标准解决方案,主要是因为它具有硬件支持,而不是因为它就是最好的,尤其是在涉及银行和企业系统的情况下。

2. ChaCha20 与 Salsa20

如前所述,ChaCha20 是 Salsa20 的修改和改进版本,由同一位密码学家 Daniel J. Bernstein 开发。

关键区别

  • Nonce 大小:ChaCha20 提供 96 位长的 Nonce,这有望比 Salsa20 的 64 位 Nonce 减少 Nonce 重用的问题。
  • 扩散性:理论上,ChaCha20 比 Salsa20 能够实现更好的扩散性(输入位在输出中的分布),使其更安全。

用例

  • ChaCha20:总的来说,ChaCha20 在各种应用中比 Salsa20 更受欢迎,因为它更安全。
  • Salsa20:如今,Salsa20 已被 ChaCha20 取代。但是,在速度是主要考虑因素且 Nonce 的唯一性可以得到控制的某些系统中,它们仍然存在。

3. ChaCha20 与其他流密码(例如 RC4)

ChaCha20 还与 RC4 等其他类型的旧式密码一起使用。

关键区别

  • 安全性:RC4 已因各种因素(如其密钥流中的偏差)而被弃用,使其不适用于当前使用。ChaCha20 没有此类缺陷。
  • 性能:两者都很快,但 ChaCha20 在现代硬件和低功耗设备上更快、更安全。

结论

总而言之,本文中呈现的这个功能性 C++ 实现的ChaCha20 的结构,集成了定义 ChaCha20 加密的根本过程,包括但不限于初始化、四分之一轮和块函数。这种理解还可以使开发人员了解 ChaCha20 的优势、速度以及它为何适合在密码学中进行实际工作的原因。ChaCha20 在许多现代应用程序和协议中的相关性为其使用留下了空间,现在,通过 C++ 中的这个实现,它可以轻松地用作密码商品。