加解密算法之ChaCha
2022-05-22 22:24:30 阿炯

在2008年,丹尼尔·J·伯恩斯坦发布了一个密切相关的“ChaCha”密码家族,其目的是增加每一轮的扩散以实现相同或稍微提升的性能。业界多次攻击过ChaCha,实现了少一轮循环:256位ChaCha6有复杂性2^139,ChaCha7有复杂性2^248。128位ChaCha6在2^107以内,但据称攻击128位的ChaCha7失败。它派生自Salsa20,密钥长度在128或256位。

ChaCha替换了基本的Salsa20循环函数R(a,b,c,k)
b ⊕= (a ⊞ c) <<< k;

修改后的计算方法:
b ⊞= c;
a ⊕= b;
a <<<= k;

循环移位量也被更新。一个完整的quarter-round,QR (a,b,c,d)变为:
a ⊞= b; d ⊕= a; d <<<= 16;
c ⊞= d; b ⊕= c; b <<<= 12;
a ⊞= b; d ⊕= a; d <<<= 8;
c ⊞= d; b ⊕= c; b <<<= 7;

这除了使其在双操作数指令集(如x86)上更有效率,也使其在每次quarter-round中更新每个word两次。

在事实上,8轮的两次循环允许一些优化。此外,输入格式可以被重新布置,以支持高效的SSE实现优化,这对Salsa20已被发现。相比逐行、逐列下移置换,还可以沿对角线进行。这样ChaCha中的两轮循环是:
QR (0, 4, 8, 12)
QR (1, 5, 9, 13)
QR (2, 6, 10, 14)
QR (3, 7, 11, 15)
QR (0, 5, 10, 15)
QR (1, 6, 11, 12)
QR (2, 7, 8, 13)
QR (3, 4, 9, 14)

其中的数字是十六个32位state word。ChaCha20使用两轮10次迭代。


The ChaCha quarter-round function. Four parallel copies make a round.

ChaCha是BLAKE哈希算法的基础,NIST哈希算法竞争的一个入围者,并且继任者BLAKE2调整为更高的速度。它还定义了一个使用16个64位word(state的1024位)的变种,具有相应调整的循环移位常数。


谷歌选择了伯恩斯坦设计的,带Poly1305消息认证码的ChaCha20(即ChaCha20-Poly1305),作为OpenSSL中RC4的替代品,用以完成互联网的安全通信。Google最初实现了HTTPS (TLS/SSL)流量在Chrome浏览器(Android手机版)与Google网站之间的通信。不久之后在TLS中采用它,ChaCha20-Poly1305算法也以chacha20-poly1305@openssh.com成为OpenSSH中的一个新密码包。后续通过编译时选项避免它依赖于OpenSSL也成为可能。

ChaCha20也被用在OpenBSD和NetBSD操作系统中的arc4random随机数生成器,取代已经脆弱的RC4,在DragonFly BSD中内核的CSPRNG子程序中也是如此。

ChaCha20已经在RFC 7539中标准化。它在IKE和IPsec中的使用已在RFC 7634中标准化。在RFC 7905中,ChaCha20-Poly1305已经被加入TLS扩展标准。

若CPU或软件不支持AES指令集,ChaCha20可提供比AES更好的性能。WireGuard协议使用了带Poly1305消息鉴别码的ChaCha20。

ChaCha20为ChaCha系列流密码的主要代表,作为salsa密码的改良版,具有更强的抵抗密码分析攻击的特性,“20”表示该算法有20轮的加密计算。由于是流密码,故以字节为单位进行加密,安全性的关键体现在密钥流生成的过程,即所依赖的伪随机数生成器(PRNG)的强度,加密过程即是将密钥流与明文逐字节异或得到密文,反之,解密是将密文再与密钥流做一次异或运算得到明文。


Salsa20

它是一种始于2005年的流加密算法,由丹尼尔·J·伯恩斯坦提交到eSTREAM。它创建在基于add-rotate-xor(ARX)操作的伪随机函数之上——32位模加、异或(XOR)和循环移位操作。Salsa20映射一个256位密钥、一个64位nonce以及一个64位流位置到一个512位的输出(也存在一个128位密钥的版本)。这使Salsa20具有了不同寻常的优势,用户可以在恒定时间内寻求输出流中的任何位置,于2007年正式发布。它可以在现代x86处理器中提供约每4–14次循环周期一字节的速度,并具有合理的硬件性能。它没有注册专利,并且Bernstein还撰写了几篇对常见架构优化的公有领域实现。

上文相关的密码算法ChaCha,具有类似的特点,但有不同的循环移位函数。


Salsa的quarter-round函数,每四组形成一轮。

在其内部,该算法采用模加⊕(逻辑异或),32位模加232 ⊞,和在一个内部十六个32位word的state上进行恒定距离循环移位操作(<<<)。只使用add-rotate-xor操作避免了软件实现中计时攻击的可能性。基本的Salsa20循环函数 R(a,b,c,k)是:
b ⊕= (a ⊞ c) <<< k;

初始状态是根据密钥的8个word、流位置的2个word、nonce的两个word(基本上是额外的流位置)和4个固定word制成。20轮循环混合制成16个word的流密码输出。

一个quarter-round会使用四个word的输入并制成四个word的输出。内部的16-word状态被布置为一个4x4矩阵;偶数循环应用quarter-round操作到四行的每项,奇数循环应用quarter-round操作到四列的每项。连续两轮循环(一次行循环和一次列循环)被称为double-round。

更精确的规范已在下方呈现为伪代码,尽管这种行/列模式更难看出⊞是模加232,<<<是左旋操作,及⊕是异或。x ⊕= y是x = x ⊕ y的缩写。

x[ 4] ⊕= (x[ 0] ⊞ x[12])<<<7;    x[ 9] ⊕= (x[ 5] ⊞ x[ 1])<<<7;
x[14] ⊕= (x[10] ⊞ x[ 6])<<<7;    x[ 3] ⊕= (x[15] ⊞ x[11])<<<7;
x[ 8] ⊕= (x[ 4] ⊞ x[ 0])<<<9;    x[13] ⊕= (x[ 9] ⊞ x[ 5])<<<9;
x[ 2] ⊕= (x[14] ⊞ x[10])<<<9;    x[ 7] ⊕= (x[ 3] ⊞ x[15])<<<9;
x[12] ⊕= (x[ 8] ⊞ x[ 4])<<<13;   x[ 1] ⊕= (x[13] ⊞ x[ 9])<<<13;
x[ 6] ⊕= (x[ 2] ⊞ x[14])<<<13;   x[11] ⊕= (x[ 7] ⊞ x[ 3])<<<13;
x[ 0] ⊕= (x[12] ⊞ x[ 8])<<<18;   x[ 5] ⊕= (x[ 1] ⊞ x[13])<<<18;
x[10] ⊕= (x[ 6] ⊞ x[ 2])<<<18;   x[15] ⊕= (x[11] ⊞ x[ 7])<<<18;

x[ 1] ⊕= (x[ 0] ⊞ x[ 3])<<<7;    x[ 6] ⊕= (x[ 5] ⊞ x[ 4])<<<7;
x[11] ⊕= (x[10] ⊞ x[ 9])<<<7;    x[12] ⊕= (x[15] ⊞ x[14])<<<7;
x[ 2] ⊕= (x[ 1] ⊞ x[ 0])<<<9;    x[ 7] ⊕= (x[ 6] ⊞ x[ 5])<<<9;
x[ 8] ⊕= (x[11] ⊞ x[10])<<<9;    x[13] ⊕= (x[12] ⊞ x[15])<<<9;
x[ 3] ⊕= (x[ 2] ⊞ x[ 1])<<<13;   x[ 4] ⊕= (x[ 7] ⊞ x[ 6])<<<13;
x[ 9] ⊕= (x[ 8] ⊞ x[11])<<<13;   x[14] ⊕= (x[13] ⊞ x[12])<<<13;
x[ 0] ⊕= (x[ 3] ⊞ x[ 2])<<<18;   x[ 5] ⊕= (x[ 4] ⊞ x[ 7])<<<18;
x[10] ⊕= (x[ 9] ⊞ x[ 8])<<<18;   x[15] ⊕= (x[14] ⊞ x[13])<<<18;

Salsa20在其输入上实行20轮混合,然后添加最终数组到原数数组来获得64字节输出块。但使用8轮和12轮的缩减循环的变体Salsa20/8和Salsa20/12也已分别被引入。这些变体被引入以补充原有的Salsa20,但不是取代它,甚至在eSTREAM的基准测量中比Salsa20表现更好[quantify],尽管它相应有着较低的安全余量。

eSTREAM选用

Salsa20已被选择作为eSTREAM项目“Profile 1”(软件)的第三阶段设计,其在第二阶段结束时得到了Profile 1中算法中的最高投票得分。Salsa20先前被选择为Profile 1(软件)的第二阶段设计重点,并作为eSTREAM项目Profile 2(硬件)的第二阶段,但最终没有晋级到“Profile 2”的第三阶段,因为eSTREAM觉得这对于极其资源受限的硬件环境可能不是一个好的候选。

密码分析

截至2015年,没有已知的对Salsa20/12或完整Salsa20/20的攻击被发布;已知的最佳攻击是打破12轮或20轮循环中的8轮。

在2005年,Paul Crowley报告了一个对Salsa20/5的攻击,预计时间复杂度2^165,并赢得Bernstein的1000美金“最有趣Salsa20密码分析”奖励。此次攻击及所有后续的攻击都是基于截断差分分析。在2006年,Fischer、Meier、Berbain、Biasse和Robshaw报告了一个对Salsa20/6的攻击,预计时间复杂度2^177,以及一个对Salsa20/7的相关密钥攻击,预计时间复杂度2^217。

在2007年,Tsunoo 等人公布了一个Salsa20的密码分析,在2^255次操作中,使用2^11.37对密钥流,打破8/20轮来恢复256位的私钥。但这种攻击似乎没有比蛮力攻击更好。

在2008年,Aumasson、Fischer、Khazaei、Meier和Rechberger报告了一个追对Salsa20/7的密码分析攻击,时间复杂度2^153,并且他们报告了首个对Salsa20/8用预计时间复杂度2^251的攻击。此攻击使用了对中性密钥位进行截断差分概率检测的新概念。此攻击可以打破使用128位密钥的Salsa20/7。2008年的密码分析中,在2^251次操作中利用2^31对密钥流,尝试恢复256位的密钥,破解了20轮中的8轮。

在2012年,Aumasson 等人的攻击将Salsa20/7(128位密钥,时间复杂度2^109)改进为Salsa20/8(256位密钥,时间复杂度2^250)。

在2013年,Mouha和Preneel发布了一则证明,叙述使用15轮循环的Salsa20在128位的安全差分分析。具体来说,它没有比2^−130更高概率的差分特征,因此差分分析会比用尽128位密钥更困难。


简言之,Salsa20 是一种流加密算法,由 Daniel J. Bernstein 提交到 eSTREAM。它创建在基于 add-rotate-xor(ARX) 操作的伪随机函数之上——32位模加、异或(XOR)和循环移位操作。Salsa20 映射一个 256位密钥、一个64位nonce以及一个64位流位置到一个512位的输出(也存在一个128位密钥的版本)。这使得Salsa20具有了不同寻常的优势,用户可以在恒定时间内寻求输出流中的任何位置。它可以在现代x86处理器中提供约每4–14次循环周期一字节的速度,并具有合理的硬件性能。它没有注册专利,并且Bernstein还撰写了几篇对常见架构优化的公有领域实现。

ChaCha20

谷歌选择了带有 Bernstein 的 Poly1305 消息认证码的 ChaCha20 作为一个 OpenSSL 中 RC4 的替代品,用以完成互联网的安全通信。最初实现了 https(TLS/SSL)流量在 Chrome 浏览器(Android手机版)与 Google 网站之间的通信。它在 IKE 和 IPsec 中的使用已在 RFC 7634 中标准化,在 RFC7905 中,Chacha20-Poly1305 已经被加入 TLS 扩展标准。


ChaCha20-Poly1305

ChaCha20是一种流式对称加密算法。Poly1305是一种带密码的消息摘要算法。ChaCha20-Poly1305是一种流式对称加密算法。

ChaCha20 和 ChaCha20-Poly1305 的区别

这两种算法原理上是一致的,区别如下:
ChaCha20 是流式加密,密文长度和原文长度是相同的。ChaCha20-Poly1305 在 ChaCha20 的基础上增加了Poly1305 算法运算结果。

ChaCha20 有四个输入:
明文 Plaintext
秘钥 Key
秘钥 Nonce
轮 Initial Counter,整数

ChaCha20-Poly1305 有三个输入,不需要“轮”,其他输入和ChaCha20 一样。


Poly1305消息认证码

消息认证码(带密钥的Hash函数):密码学中,通信实体双方使用的一种验证机制,保证消息数据完整性的一种工具。构造方法由M.Bellare提出,安全性依赖于Hash函数,故也称带密钥的Hash函数。消息认证码是基于密钥和消息摘要所获得的一个值,可用于数据源发认证和完整性校验。

Poly1305是Daniel.J.Bernstein创建的消息认证码,可用于检测消息的完整性和验证消息的真实性,现常在网络安全协议(SSL/TLS)中与salsa20或ChaCha20流密码结合使用。Poly1305消息认证码的输入为32字节(256bit)的密钥和任意长度的消息比特流,经过一系列计算生成16字节(128bit)的摘要。


ChaCha20-Poly1305 优势

Google 推出新的加密套件并在所有移动端的 Chrome 浏览器上优先使用原因:
避开了现有发现的所有安全漏洞和攻击;
针对移动端设备大量使用的ARM芯片做了优化,能够充分利用 ARM 向量指令,在移动设备上加解密速度更快、更省电;
更加节省带宽,Poly1305 的输出是 16 字节,而 HMAC-SHA1 是 20 字节,可以节省 16% 的 overhead 消耗。

如果是用在路由器上,因为很多路由器 CPU 速度都在500MHz以下,性能并不强,使用 aes-256-cfb 多出来的那点性能开销在路由器上可能会构成一个影响性能的大问题,因此之前使用在路由器上的加密方式一般都选 rc4-md5。因为在路由器等性能不强的设备上使用aes加密方式会影响性能,使用rc4-md5又加密强度不够,所以创造了 Salsa20 这个加密算法,它比前辈rc加密算法速度更快而加密强度更高,后来谷歌又在这个算法的基础上开发了 chacha20 这个更快加密更强的算法。基本上,它现在算是性能不强的设备使用最佳的算法了。


ChaCha20-Poly1305是Google所采用的一种新式加密算法,性能强大,在CPU为精简指令集的ARM平台上尤为显著(ARM v8前效果较明显),在同等配置的手机中表现是AES的4倍(ARM v8之后加入了AES指令,所以在这些平台上的设备,AES方式反而比chacha20-Poly1305方式更快,性能更好),可减少加密解密所产生的数据量进而可以改善用户体验,减少等待时间,节省电池寿命等。谷歌选择了ChaCha20和伯恩斯坦的Poly1305消息认证码取代过去一直在互联网安全领域使用的基于OpenSSL的RC4密码,最初是为了保证能够在Android手机上的Chrome浏览器和谷歌网站间的HTTPS(TLS/SSL)通讯。在谷歌采用TLS(安全传输层协议)不久后,ChaCha20和Poly1305均用在OpenSSH中的ChaCha20-Poly1305新算法中,这使得OpenSSH可能避免因编译时对OpenSSL产生依赖。