You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

113 lines
10 KiB
Markdown

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 15 | 现代密码:你用的加密算法过时了吗?
你好我是范学雷。今天我想和你聊聊JDK里的密码学算法相关的问题。
Java语言安全的基础主要有两块内容。一块是Java语言的安全设计比如字节码的校验内存保护机制等等另外一块是Java平台的保护机制比如签名的类库资源的认证授权等等。而Java平台的保护机制是建立在密码学的基础之上的。
这一次的讨论,我们从故事开始,来看看现在我们应该采用的密码学的技术,以及应该抛弃的密码学技术。
## 阅读案例
1976年是现代密码学的奠基之年。这一年DiffieHellman密钥交换协议公开发表。这是由 Ralph Merkle 构思并以 Whitfield Diffie 和 Martin Hellman 命名的第一个公钥协议。这是最早为公众所知的,提出公钥和私钥思想的著作。从这一年开始,在非安全通道上建立安全通信的想法,有了理论上的依据;现代互联网的安全,也终于有了稳固的基石。
DiffieHellman密钥交换协议的论文为密码学家展示了一个全新的大陆。有了这个方向的指引接下来很快就有了更多的脚步踏出了新的道路。1977年受DiffieHellman密钥交换协议的启发Ron Rivest、Adi Shamir和Leonard Adleman公开发表了基于公开密钥的电子签名算法也就是RSA算法。从此以后要在非安全通道上识别身份、建立信任的想法也有了理论上的依据。
至此,加上传统的加密技术,解决信息安全基本问题的三大技术就已经集结完成了。随着互联网的发展,这些技术大放异彩,成为了互联网基础设施最终的环节之一。
后面的事情也就顺理成章了。1982年Ron Rivest、Adi Shamir 和 Leonard Adleman 成立了RSA公司公司主要提供基于RSA算法的产品和服务。1991年RSA公司推出了RSA大会以及RSA算法的分解挑战。 2006年RSA公司被EMC收购收购价达到21亿美元。2007年RSA算法分解挑战终止。而RSA大会则发展成了信息安全领域最富盛名的的大会。
为什么RSA分解挑战终止了呢 按照官方的声明,因为:“现在业界对常见对称密钥和公钥算法的密码分析强度有了更深入的了解,这些挑战不再活跃。”
那分解挑战的成果是什么样子的呢? 我想你也一定感兴趣。
1991年3月18日RSA公司推出RSA算法的分解挑战。不到两个星期也就是1991年的4月1日330位的RSA密钥被破解。随后更高强度的RSA算法被破解。其中768位的RSA密钥在2009年被破解这是一个RSA命运的分水岭。从此以后小于或者等于1024位的RSA密钥都被认为是不安全的密钥。现在的RSA算法应该是用至少2048位的密钥。
对RSA算法的破解研究并不仅仅局限于因式分解这样的纯计算游戏。比如说早在1998年就有密码学家发现了对RSA算法进行旁路攻击的办法。现在如果是用测时攻击timing attacks对于1024位的密钥破解传统的RSA实现也就是分分钟钟的事情。
虽然我们可以通过复杂的RSA实现来化解这样的攻击。但是复杂的实现意味着性能的损失以及维护的困难。到这里我们已经可以依稀地听到RSA算法要告别历史舞台的声音了。
其实,任何一个密码学的算法,都有它的生命周期。从看似完美的问世,到实际破落的境地,也就是数十年的时间。
## 看向未来
但是,我们的隐私数据却需要上百年,甚至是永远的保护。有生命周期的算法,似乎满足不了这样的要求。密码学要始终看向未来。如果站在十年后看现在,我们怎么能保证万无一失呢?
十多年后,量子计算机大概率就能够问世了。而量子计算机的计算能力是非常恐怖的。现在我们常见的非对称密码算法所能提供的计算强度,在量子计算时代,也许就像是小孩子的玩具一样脆弱。所以,密码学家和各种组织都在紧锣密鼓地遴选“后量子时代”的非对称密码算法。
显然我们不能等到“后量子时代”的非对称密码算法问世以后再来保护我们的隐私数据。现在我们就需要这样的保护。而这其中最重要的方案就是使用前向保密Forward Secrecy的安全协议。前向保密也就意味着即使未来我们反复使用的密钥被破解我们的数据依然能够得到保护。如果你想了解更多的关于前向保密的细节请参考我在另外一个专栏里的讨论[《量子时代,你准备好了吗?》](https://time.geekbang.org/column/article/329292)。
在Java的设计和实现里前向保密是JDK缺省的选择。这是JDK 8之后JDK做的一个重要的安全策略调整。这个调整涉及到的大都是JDK实现的小细节比如缺省JDK升级到TLS 1.3这样的变动。
JDK的安全是Java语言的头等大事。所以JDK的安全改进一般情况下都会向后移植直到我们没有能力移植为止。前向保密的策略也已经向后移植进入到JDK 8了。
## 关注变化
既然密码学的算法有生命周期,我们就需要了解这个生命周期,及时地停止使用危险的、过期的算法。那么,哪些密码算法如今已经过期或者存在安全隐患?我们又能从哪里找到这方面最新的信息呢?
JDK 8之后Java安全策略的另外一个重要的调整就是公开发布[JDK的密码路线图](https://java.com/en/jre-jdk-cryptoroadmap.html)。在这个路线图里JDK会声明哪些密钥算法是危险的哪些是过期的以及JDK根据密码学的进展作出的变动。
如果你的产品或者代码涉及到了密码相关的内容,你就要密切关注这个路线图的更新,及时地调整产品里涉及到密码算法了。
另外,密钥算法的废弃,总是会带来这样或者那样的兼容性问题。当安全性和兼容性相遇的时候,我们应该毫不犹豫地选择选择安全性,及时解决掉兼容性问题。安全性问题,时间上千万不要拖。软件系统的漏洞,一般情况下,攻击者知道的比你还要早。我们拖拉的每一秒钟,都是留给攻击者的时间窗口。
## 应该抛弃的算法
下面我罗列了一些曾经流行的JDK支持的但是我们不应该使用的密码学算法或者协议。继续使用这些算法会给你的系统带来难以预料的灾难。而且使用的系统也很容易成为黑客攻击的目标。
* MD2
* MD5
* SHA-1
* DES
* 3DES
* RC4
* SSL 3.0
* TLS 1.0
* TLS 1.1
* 密钥小于1024位的RSA算法
* 密钥小于1024位的DSA算法
* 密钥小于1024位的Diffie-Hellman算法
* 密钥小于256位的EC算法
## 应该退役的算法
下面我罗列了一些曾经流行的JDK支持的我们可以使用但是应该尽快替换掉的算法。这些算法目前来看还是安全的但是已经处于危险的边缘了。如果你的系统计划运行五年以上这些算法的安全性值得担忧。
* 密钥大于1024位小于2048位的RSA算法。
* 密钥大于1024位小于2048位的DSA算法。
* 密钥大于1024位小于2048位的Diffie-Hellman算法。
* RSA签名算法
* 基于RSA的密钥交换算法
* 128位的AES算法
## 推荐使用的算法
下面我罗列了一些现在流行的JDK支持的我们推荐使用的密码学算法。这些算法目前看还没有发现值得重视的安全问题是可以信任的算法。如果一个系统计划运行五年以上你应该使用这些算法。
* 256位的AES算法
* SHA-256、SHA-512单向散列函数
* RSASSA-PSS签名算法
* X25519/X448密钥交换算法
* EdDSA签名算法
我们前面提到过,安全改进一般都会向后移植,但是也有我们没有能力移植的例子。上面提到的推荐使用的算法中, JDK 8不支持X25519/X488密钥交换算法也不支持EdDSA签名算法。一个最重要的原因就是这些算法需要使用新的公开接口。
一般情况下小版本的JDK升级不能变更公开接口。这就让JDK 8有了安全上的短板。目前看这个短板还不足以构成安全威胁。但是停留在JDK 8意味着我们放弃了更好的密码算法包括安全性的提高和性能的提升。
我上面列举的算法大部分开发者应该接触不到。因为它们是Java语言和Java平台的一部分是计算机基础设施的一部分。我们天天使用它们但是没有多少人意识到它们的存在。如果你需要使用密码比如签名Java包或者使用数字证书请留意这些数字内容使用的密码算法尽量使用推荐的算法千万不要使用已经抛弃的算法。
## 总结
好,到这里,我来做个小结。通过今天的讨论,我们知道,任何一个密码学的算法,都有它的生命周期。所以,我们要能够管理它们的生命周期。反映到代码里,就是要使用前向保密的安全协议以及当前推荐的算法;及时替换掉过期的算法。
对于JDK的开发者来说我们要关注[JDK的密码路线图](https://java.com/en/jre-jdk-cryptoroadmap.html)了解JDK根据密码学的进展作出的变动及时解决自己代码里的兼容性问题。
如果面试中聊到了密码学算法的问题,你可以聊聊前向保密,以及我们推荐的密码学算法。
## 思考题
今天的思考题是一个拓展阅读。在上面推荐的算法里除了AES算法之外其他的三个算法如果不是关注密码学进展的话你可能都没有听说过。密码学进展很快十多年前的主流算法在今天几乎都要进入退休的年龄了。我们也要随时更新对密码学基本现状的认识。
如果有时间你可以去搜索一下RSASSA-PSS签名算法X25519密钥交换算法以及EdDSA签名算法的相关介绍。不需要了解技术细节知道大致是怎么回事就行。
欢迎你在留言区留言、讨论,分享你的阅读体验以及你的拓展阅读内容。我们下节课见!