现代互联网上,绝大多数网站都已经支持 HTTPS,其使用的 SSL/TLS 加密协议会将用户的请求数据与网站的响应进行加密,以防止信息被路径上的恶意用户窃取或篡改。而 SSL/TLS 协议中的一个重要组成部分是 RSA、ECDSA 等非对称加密算法,这些算法的密钥分为公钥、私钥两份,公钥可以公开,而私钥则要妥善保管。
在访问 HTTPS 网站时,会经过以下的流程:
- 网站会将它的公钥(以证书形式)发送给浏览器。
- 浏览器会校验公钥的有效性,防止中间人篡改公钥,从而拦截或监听通信。
- 浏览器(或操作系统)内置了一组可信任的证书颁发机构(CA)的公钥,通过密码学方法可以确认这份公钥是其中某个颁发机构生成的。
- 证书颁发机构则会通过一系列方法(多级证书链,物理隔绝的密钥保存设备)来保护他们自己的私钥安全,防止有人窃取他们的私钥来随意生成被信任的证书信息。
- 浏览器会与证书颁发机构的服务器联系,查询「证书吊销列表」(Certificate Revocation List)。这个列表保存了所有的「虽然的确是证书颁发机构颁发,但是因为系统错误/私钥泄漏等原因不能再被信任」的证书。
- 浏览器(或操作系统)内置了一组可信任的证书颁发机构(CA)的公钥,通过密码学方法可以确认这份公钥是其中某个颁发机构生成的。
- 浏览器在确定公钥可信后,本地随机产生一个随机密钥,用来加密这一次的连接。
- 浏览器将随机密钥用网站的公钥加密,然后发送给网站服务器。
- 加密后的内容只能用网站的私钥解密,不能用公钥解密,因此监听者是无法获取随机密钥内容的。
- 网站服务器用本地保存的私钥解密内容,获得浏览器产生的随机密钥。
- 浏览器和网站服务器开始用解密后的随机密钥进行对称加密,也就是双方使用同一份密码进行加密/解密的加密算法,例如 AES。
- 这里不再使用非对称加密是因为非对称加密对算力的消耗较大,而对称加密性能较高。
非对称加密算法保证了浏览器和网站交换对称加密密钥的安全,从而保证数据不被窃取或篡改。
但是随着量子计算机的诞生,事情发生了一点变化。在量子计算机上运行的秀尔算法可以非常高效地破解 RSA、ECDSA 等基于质因数分解难度的传统非对称加密算法,只要有一台足够强大的量子计算机,也就是量子比特数目达标的计算机。
而随着量子计算的逐渐火热,量子计算机正在迅速地发展。目前公开的最强大的量子计算机是 IBM 的 53 量子比特计算机(见量子霸权页面),仍然不够使用秀尔算法破解 RSA、ECDSA 等,但高速的科技发展随时可能将此变成现实。
因此,密码学家们着手开发无法被量子计算机有效破解的非对称加密算法,并推广它们的使用,以准备好迎接 RSA 被破解的那一天。
从 2016 年末开始,Open Quantum Safe 项目就开始将现有的、能抵抗量子计算机的加密算法整合到 liboqs 开发库里,并将它集成到 OpenSSL、BoringSSL 等广泛使用的加密库,以简化新加密算法的部署。
同时,官方还提供了 nginx、Chromium 等软件的编译、集成流程文档。因此,只需要参照文档进行简单的修改,我们就可以准备好迎接实用量子计算机的到来。
注意:这里所有的后量子加密算法都相对较新,并且正在进行 NIST 的标准化审核流程,可能仍有未被发现的漏洞。虽然 Open Quantum Safe 项目有一些方法降低风险,但在这些算法的标准化流程完成之前,不建议将它们用于生产环境等重要用途。
nginx / OpenSSL
由于 nginx 使用 OpenSSL 或 BoringSSL 作为自己的加密库,我们不需要对 nginx 做任何修改,只需要把 OpenSSL 替换成 Open Quantum Safe 项目的版本就可以。
Open Quantum Safe 提供了一份修改后的 Dockerfile,可以用作参考。
我参考以上内容也修改了自己编译 nginx 用的 Dockerfile,以使用 Open Quantum Safe 的 OpenSSL,在这里可以看到。
相比编译普通的 nginx,主要的改动有两处:
-
需要使用 Open Quantum Safe 的 OpenSSL,并额外下载、编译 liboqs,将其安装到 OpenSSL 的源码目录,以便调用。我的 Dockerfile 中与之相关的是 44-52 行:
# 前略 && git clone -b OQS-OpenSSL_1_1_1-stable https://github.com/open-quantum-safe/openssl.git \ # 省略了一些我个人使用的 OpenSSL 修改,对后量子加密不是必要的 && git clone -b master https://github.com/open-quantum-safe/liboqs.git \ && mkdir /tmp/liboqs/build && cd /tmp/liboqs/build \ && cmake -DOQS_BUILD_ONLY_LIB=1 -DBUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_PREFIX=/tmp/openssl/oqs .. \ && make -j4 && make install && cd /tmp \ # 后略
其中所有文件都被下载到了
/tmp
目录下。关键点是用 cmake 编译 liboqs 项目,并将其安装到 OpenSSL 源码目录的 oqs 子目录下。 -
需要额外添加一些编译参数,以将 liboqs 包含在编译出来的 nginx 中,在 Dockerfile 的 102-104 行:
# 前略 && ./configure \ # 略过一些 nginx 的编译参数 --with-openssl=/tmp/openssl \ --with-cc-opt="-I/tmp/openssl/oqs/include" \ --with-ld-opt="-L/tmp/openssl/oqs/lib" \ && sed -i 's/libcrypto.a/libcrypto.a -loqs/g' objs/Makefile \ # 后略
然后正常编译 nginx 即可。
编译、安装 nginx 完成后,还需要修改参数使用这些后量子时代的非对称加密算法,包括密钥交换算法和身份验证算法两类:
-
密钥交换算法:即浏览器和网站传输对称加密密钥时使用的非对称加密算法。
只需简单修改
nginx.conf
中的ssl_ecdh_curve
参数,使用这些非对称加密算法的椭圆曲线,就可以使用这些密钥交换算法:ssl_ecdh_curve 'p256_frodo640aes:p256_bike1l1cpa:p256_kyber90s512:p256_ntru_hps2048509:p256_lightsaber:p256_sidhp434:p256_sikep434:prime256v1:secp384r1:secp521r1';
修改完成后
nginx -s reload
即可。这里只开启了支持的密钥交换算法的一部分,原因有二:
- nginx 对这一参数的长度有限制,过长会报错;
- 选择的这些参数也都被 Open Quantum Safe 的 BoringSSL 支持,这在后续开启 Chromium 支持时至关重要。
同时,这些密钥交换算法都以
p256_
开头,意味着后量子加密算法和传统加密算法同时使用。这是为了防止一种情况:新的加密算法存在数学漏洞,使得它们使用传统计算机(冯诺依曼计算机)就可以快速破解。同时使用两种交换算法,既保证了无法被量子计算机破解(如果新加密算法正常工作),也保证了一旦新加密算法被破解,密钥交换数据仍然拥有与传统算法同等级别的保护,不会被传统计算机立即破解。 -
身份验证算法:即证书颁发机构(CA)给网站颁发证书形式公私钥的算法。使用这些算法需要找支持后量子算法的 CA(现在还不存在)重新签发证书,或者自己签发证书(不被浏览器信任),都不实用,因此我选择现在不使用。
在这里配置完后,你可以使用 Open Quantum Safe 的一个 curl Docker 镜像来测试一下你的网站:
# 将最后一个参数替换成你要用的加密算法,格式和 ssl_ecdh_curve 相同
docker run -it openquantumsafe/curl:0.4.0 curl https://lantian.pub --curves p256_frodo640aes
Chromium / BoringSSL
虽然有了命令行的 curl 验证,但是一个全功能的浏览器的支持能够让后量子加密实用化,给用户更佳的保护。Open Quantum Safe 同样提供了修改后的 BoringSSL,只需要将它编译到 Chromium 里,就可以在目前世界上最流行的浏览器中体验后量子加密算法了。
Open Quantum Safe 同样提供了 Chromium 的编译教程,在这里可以找到。与编译原版 Chromium 相比,主要不同的步骤有四处:
-
git clone https://github.com/open-quantum-safe/boringssl
,用修改过的 BoringSSL 替换 Chromium 源代码中third_party/boringssl/src
路径下的原版 BoringSSL; -
下载 liboqs,编译安装到 BoringSSL 的
oqs
目录下:git clone --branch master https://github.com/open-quantum-safe/liboqs.git cd liboqs && mkdir build && cd build cmake .. -G"Ninja" -DCMAKE_INSTALL_PREFIX=<CHROMIUM_ROOT>/third_party/boringssl/src/oqs -DOQS_USE_OPENSSL=OFF ninja && ninja install
-
给 Chromium 打上这个调用 liboqs 的补丁。
-
在
third_party/boringssl
文件夹下运行python2 src/util/generate_build_files.py gn
以更新依赖,加入 liboqs 相关内容。
之后按照正常步骤编译 Chromium 即可。
我也修改了一份 Chromium 的 PKGBUILD 文件,Arch Linux 用户可以直接使用。最新版的 PKGBUILD 可以在此处找到,我写文章时的版本可以在此处找到(241cfaa)。
注意编译 Chromium 是个非常漫长的过程,我的 i7-7700HQ 花了 8 个小时。如果你的 CPU 更弱,请做好等上一整天的准备。
编译、安装完成后,启动 Chromium 访问开启了后量子加密的网站,然后打开开发者工具的 Security(安全)面板:
上面已经显示使用了 p256_frodo640aes
算法,也就意味着你的网页浏览已经有了后量子时代的保护。
我的网站已经支持了后量子加密,可以作为测试。或者你也可以访问 Open Quantum Safe 官方测试站,上面提供了目前支持的所有密钥交换、身份验证算法组合,可以进行更全面的测试。
额外要注意的是,Open Quantum Safe 的 BoringSSL 只支持一小部分的密钥交换算法:
P256_BIKE1L1CPA, P256_FRODO640AES, P256_KYBER90S512, P256_NTRU_HPS2048509, P256_LIGHTSABER, P256_SIDHP434, P256_SIKEP434
这一列表只在官方测试站上提到。因此我先前选择了这些算法配置在 nginx 中。