当前位置:首页 > 百科

rc4 加密问题漏洞

2015年,加密安全研究员Mathias Bynens在GitHub上发了一条issue,问题指出某个广泛使用的漏洞JavaScript库中的RC4实现存在密钥流偏移问题。这个库被下载了数百万次,加密用于前端与后端的问题加密通信。问题暴露后,漏洞开发者们才意识到,加密一个看似“能用”的问题RC4实现,可能比不用加密还危险。漏洞

RC4本身并不复杂。加密Ron Rivest在1987年设计它时,问题目标就是漏洞简单快速。一个256字节的加密状态数组S,两个指针i和j,问题加上一个密钥调度算法(KSA)和一个伪随机生成算法(PRGA),漏洞整个加密过程不到二十行代码就能写完。这种简洁性让它在WEP、WPA早期版本、SSL/TLS的某些套件里被大量采用。但简洁不等于安全。

第一个致命伤在密钥调度阶段。KSA用密钥打乱S数组,但打乱的程度取决于密钥本身。如果密钥太短,或者密钥存在大量重复字节,S数组的初始排列会保留明显的规律性。2013年,有研究者发现,当密钥长度接近256字节时,KSA产生的S数组几乎接近恒等排列——也就是说,加密后的输出和明文之间的关联性变得可预测。这不是理论推演,是在实际抓包中验证过的。

更麻烦的是RC4的密钥流前几个字节。由于PRGA的初始状态受KSA影响,输出的前256个字节存在统计偏差。具体来说,第二个输出字节等于0的概率大约是1/128,而不是理想的1/256。这个偏差看起来很小,但在WEP那种每帧换一个IV(初始向量)的场景下,攻击者可以收集大量使用不同IV的密文,利用这个偏差逐步恢复密钥。2001年,Fluhrer、Mantin和Shamir发表的论文直接把这个攻击变成了现实工具,WEP在几分钟内就能被破解。

WEP的失败没有让RC4退出历史舞台。TLS在很长一段时间里仍然支持RC4套件,理由是“比没有加密好”。这个理由在2013年崩塌了。那一年,有研究者提出了针对TLS中RC4的“Bar Mitzvah”攻击,利用RC4密钥流前几个字节的偏差和TLS记录层的行为,可以从加密的HTTP cookie中恢复出明文。攻击需要大约2^30次加密操作,在当时的硬件上几天就能完成。浏览器厂商开始行动,Chrome和Firefox在2015年彻底移除了RC4支持。

问题出在实现层面同样严重。开头提到的那个JavaScript库,它的KSA循环写成了for (i = 0; i < 256; i++),但密钥索引用的是key[i % key.length]。当密钥长度是256的因数时,比如16或32,这个取模操作会让密钥的每个字节在KSA中被使用的次数完全相同,进一步削弱了S数组的随机性。正确的做法是用一个独立的计数器来遍历密钥,而不是直接用循环变量取模。这个细节在Rivest的原始描述里是清楚的,但很多实现者忽略了。

RC4还有一个被低估的问题:它的输出没有完整性保护。这意味着攻击者可以翻转密文中的某个比特,解密后的明文对应比特也会翻转。在WEP中,这被用来注入任意数据包;在TLS中,这被用来实施“Lucky 13”之类的攻击。加密算法本身不提供认证,必须配合MAC使用,但RC4的流密码特性让MAC-then-encrypt和encrypt-then-MAC的选择变得格外敏感。

现在RC4基本被AES-GCM和ChaCha20-Poly1305取代了。ChaCha20的设计者Daniel J. Bernstein在2008年发表论文时,明确把“避免RC4的密钥流偏差”作为设计目标之一。从RC4到ChaCha20,流密码的进化不是速度的竞赛,而是对统计偏差和实现陷阱的持续修正。如果你手里还有依赖RC4的系统,别犹豫,换掉它。这不是过度谨慎——RC4的偏差是数学事实,不是配置问题。

分享到: