Nginx 实现 Chrome 下的 X25519 密钥交换组
偶然看到 Chrome 访问谷歌的时候,显示的 Key exchange group 是 X25519,但是自己网站显示的是 P-384,谷歌通常喜欢走在技术的前沿,所以决定探索一下这是什么情况。
在探索的过程中,发现自己签的 Root CA 返回的也是 X25519 group,想起来自己的 CA 是纯 ECC 证书,猜测这可能是因为所有证书链都是 ECC 的时候,才会开启 X25519,随后就被证伪了,因为谷歌的根证书也是 RSA。
后来在网上搜罗一圈,几乎搜不到相关的文章,换了几个关键词之后发现了一篇讲的比较透彻的文章 折腾X25519的两三事,所以直接放结论,如果想实现 X25519 Key exchange group,只需要更改 SSL 配置:
方案 1:去掉这一行
ssl_ecdh_curve secp384r1;
方案 2:使用这一行(推荐)
ssl_ecdh_curve X25519:secp384r1;
ECC/RSA 证书和 Nginx 的配置的组合可以看下表
ECC-384 | RSA | |
---|---|---|
删掉 ssl_ecdh_curve | X25519 | P-256 |
ssl_ecdh_curve X25519; | Error | X25519 |
ssl_ecdh_curve secp384r1; | P-384 | N.A. |
之后自己的网站显示也就是 X25519 了。
以下是引用自瑞瑞哥的博客:
如果你把X25519放在前面,那么谷歌的蜘蛛将没法爬取你的网页;而如果你把它放在后面,那就等于没有X25519,所以目前开启这个就没法被爬取了。
(2016 年的时候)谷歌浏览器最喜欢X25519,而所有浏览器更喜欢P-256相比于P-384。这个目前和我验证的内容有点接近,但是不清楚Nginx配置文件里的具体用法。
Curve25519/Ed25519/X25519 是著名密码学家 Daniel J. Bernstein 在 2006 年独立设计的椭圆曲线加密/签名/密钥交换算法,和现有的任何椭圆曲线算法都完全独立。特点是:第一完全开放设计,算法各参数的选择直截了当,非常明确,没有任何可疑之处,相比之下目前广泛使用的椭圆曲线是 NIST 系列标准,方程的系数是使用来历不明的随机种子 c49d3608 86e70493 6a6678e1 139d26b7 819f7e90 生成的,非常可疑,疑似后门;第二,一个椭圆曲线加密算法就算在数学上是安全的,在实用上也并不一定安全,有很大的概率通过缓存、时间、恶意输入摧毁安全性,而 25519 系列椭圆曲线经过特别设计,尽可能的将出错的概率降到了最低,可以说是实践上最安全的加密算法。例如,任何一个 32 位随机数都是一个合法的 X25519 公钥,因此通过恶意数值攻击是不可能的,算法在设计的时候刻意避免的某些分支操作,这样在编程的时候可以不使用 if,减少了不同 if 分支代码执行时间不同的时序攻击概率,相反,NIST 系列椭圆曲线算法在实际应用中出错的可能性非常大,而且对于某些理论攻击的免疫能力不高,Bernstein 对市面上所有的加密算法使用 12 个标准进行了考察,25519 是几乎唯一满足这些标准的 https://safecurves.cr.yp.to/index.html ;第三,25519 系列曲线是目前最快的椭圆曲线加密算法,性能远远超过 NIST 系列,而且具有比 P-256 更高的安全性;第四,Daniel J. Bernstein 是世界著名的密码学家,他在大学曾经开设过一门 UNIX 系统安全的课程给学生,结果一学期下来,发现了 UNIX 程序中的 91 个安全漏洞;他早年在美国依然禁止出口加密算法时,曾因为把自己设计的加密算法发布到网上遭到了美国政府的起诉,他本人抗争六年,最后美国政府撤销所有指控,目前另一个非常火的高性能安全流密码 ChaCha20 也是出自 Bernstein 之手;第五,25519 系列曲线自 2006 年发表以来,除了学术界无人问津,2013 年爱德华·斯诺登曝光棱镜计划后,该算法突然大火,大量软件,如 OpenSSH 都迅速增加了对 25519 系列的支持,如今 25519 已经是大势所趋,可疑的 NIST 曲线迟早要退出椭圆曲线的历史舞台,目前,RFC 增加了 SSL/TLS 对 X25519 密钥交换协议的支持,而新版 OpenSSL 1.1 也加入支持,是摆脱老大哥的第一步,下一步是将 Ed25519 做为可选的 TLS 证书签名算法,彻底摆脱 NIST。
各个曲线的安全性可以看下图,出自https://safecurves.cr.yp.to/index.html
(ssl_ecdh_curve)支持的曲线会同时影响 ECDHE 和 ECDSA,但是实际上本应该各自分开的。解决方案就是要么不填,要么手动制定多个。