密码应用漏洞最多的环节
我参与审查了许多现实世界中的密码应用程序,如OpenSSL、谷歌的加密备份系统、Cloudflare的TLS 1.3实现、“Let’s Encrypt”证书颁发授权协议、Zcash“加密货币”协议、NuCypher的门限代理重加密方案,以及其他几十个不能公开的现实世界密码应用程序。
在工作初期,我参与审查了一家知名公司自己定制的安全通信协议。审查结果表明,这个协议可以为除了临时密钥之外的几乎所有信息生成签名。这种做法导致替换临时密钥会很困难,这完全破坏了协议的整体设计原则,绝大多数有安全传输协议开发经验的新手容易犯这样的错误,但即便有足够的安全传输协议开发经验,开发人员仍有可能忽略一些细节。记得在审查即将结束时,我解释了这个漏洞,那时一屋子的工程师几乎沉默了30秒。
这样的情形在我的职业生涯中多次出现。有一段时间,在审查另一个客户的“加密货币”协议时,我发现其使用的签名协议存在二义性,这让我可以从已有交易伪造新的交易。通过检查一个客户的TLS协议实现,我发现了一些攻击RSA实现的巧妙方法。这一发现进一步转化为一份由RSA发明者之一参与撰写的白皮书,它报告了十几个开源项目存在的常见漏洞和弱点。在写本书的时候,我查看了Matrix聊天协议实现。我发现该协议中的身份验证协议存在问题,进而导致协议内置的端到端加密算法易被攻破。不幸的是,在使用密码技术时,有太多的细节可能会被疏忽。此时,我意识到必须写一些与实用密码有关的东西。这也是书中有很多这种轶事的缘由。
我会审查用各种编程语言编写的密码程序库和应用程序,在这个过程中,我发现了许多安全漏洞(例如,在 Go 语言的标准库中发现了CVE-2016-3959漏洞)。我还研究了密码程序库欺骗开发者滥用这些漏洞的方法(请阅读我的论文“How to Backdoor Diffie-Hellman”),并为开发者应该使用哪些密码库给出具体建议。开发人员总是不知道该使用哪些密码库,这是一件非常棘手的事情。
我提出了Disco协议,并用不到1000行代码将它编写成一个功能齐全的密码库,而且这个密码库使用了多种编程语言。Disco协议仅依赖两个密码原语:SHA-3置换和Curve25519曲线。是的,开发人员只需1000行代码就能实现这两个密码原语,进而可以实现认证密钥交换、数字签名、非对称加密、消息认证码、哈希函数、密钥派生函数等密码原语。编写Disco协议的过程为我提供了一个独特的视角,它让我明白一个好的密码库应该包含哪些基本密码原语。
本书包含许多实用见解。具体来讲,每章都包含密码算法的应用示例且它们涉及多种编程语言,同时这些密码算法都来自广泛应用的密码库。