证书的那些事儿
现在网络这么发达,许多人都在上面购物、理财、预约挂号…网络上传送的可都是自己的重要资料,比如身份证号,信用卡密码等。因特网如何才能保证这些敏感信息的安全?本文试着来探讨一下加密、证书等那些事儿。
历史
隐藏信息
古代交通不便,一般都是通过送信的方式传递信息。那么如何保证信件的内容不被泄露呢?一种方法是隐藏字迹。中国古代使用矾书,也就是用明矾水来书写保密书信。水干之后没有任何痕迹,泡水时字才显示。还有一招是使用淀粉水在纸上写字,再把纸泡在碘水中显示字迹。据知乎的水波说在西方世界里,也有使用牛奶或者羊奶书写信息,待干掉以后再用高温烘烤使之重新显现字迹的说法。这些办法一旦为人所知,便会轻易被破解,而且还有点儿此地无银三百两的意思。
加密信息
除了隐藏信息以外,还有加密的方法。在宋代兵书《武经总要》里,约定了40个常用的军事短语,送信内容为一首40个字的五言律诗,每个字代表一个军事短语。然后在相应的字上做标记,对方就明白了,这个叫字验。这个就有点儿密码表的意思了。从知乎某匿名用户的回答上找了一张图:
在西方世界里,古希腊军队将长条羊皮纸缠绕在约定长度和粗细的木棍上书写,木棍称为Scytale。把羊皮纸解下来后就变成没有意义的字母了。古罗马的凯撒大帝用的是字母移位的办法。比如有封信写着:IFMMP,多半我们是不知道啥意思的。要是对方事先说明了把每个字母都右移一位的方法,也就是A变成B,B变成C…Z变成A,那我们就能很轻松地把IFMMP变成HELLO,明白对方的意思。
现代
对称加密
对上文说的凯撒大帝移位法而言,“右移”就是算法(algorithm),一位的“1”就是密钥(key)。计算机普及后,最早的有影响力的算法是DES(Data Encryption Standard),它的秘钥是64位,但只有56位会用来计算。所以,只要最多尝试256(大约是七万亿)次的暴力破解,就能解密。随着计算机硬件的发展,这个数量级在1998年只要56小时就能破解,到了1999年变成了24小时以内。这样就不够安全了。于是四年之后,AES(Advanced Encryption Standard)取代了DES成为了新的标准。它可以使用128、192或256位密钥。最低的128位也能承受大约三千万亿亿次的暴力破解,至少目前看起来还算是比较安全的。在DES向AES的过渡期间,使用了3DES算法。所谓3DES,可以理解成重要的事情做三遍,用不同密钥的DES加密三次,几乎也就等同于56×3=168位的密钥,这样也算是比较安全了。
非对称加密
对称密钥有一个问题,就是密钥通过什么渠道来传输。加密算法再好,密钥被偷走了,也无济于事。在这样的背景下,非对称加密问世了。它的密钥包含着一个公钥和一个私钥。私钥顾名思义是只有你自己的电脑才知道的,公钥是公开的。用私钥加密的数据只有用公钥才能解开,同样的,用公钥加密的数据只有用私钥才能解开。假如两台电脑甲和乙相互通信,双方先把自己的公钥告诉对方。当甲给乙发消息时,用乙的公钥来加密,由于只有乙有相对应的私钥,所以只有乙能解密,甲要是忘记了消息内容连自己都解不了,更遑论第三方了。反之亦然。非对称加密最常用的算法是RSA(发明者Rivest、Shmir和Adleman的姓氏首字母)。它的私钥和公钥是通过至少百位的大质数来生成的。由于在数学上很难计算大整数的因数,所以目前来说是比较安全的。万一哪天数学或量子计算机上有了突破,这种算法也就不再可靠了。1999年,512位的RSA被成功分解。2009年,768位的RSA也被成功分解。现在通用的1024位密钥可能也不那么可靠了,从安全的角度来说应该升级到2048位或以上。密钥这么大,非对称加密的速度比较慢(与对称加密有千倍的差距)也是可以理解的。所以在实际的使用当中一般用对称加密来加密数据,非对称加密来加密对称加密的密钥。
散列算法
好吧,密码破解不了,但是攻击者可以截取加密后的数据包,然后篡改。这样“传位十四皇子”就变成了“传位于四皇子”啦。散列算法堵死了这条路。它能把很长的数据变成固定长度的文本。也称为数据的摘要(digest)或指纹(fingerprint)。相同数据的摘要一定是一样的,不同数据的摘要有可能一样,但是通常不一样。正因如此,散列算法是不可逆的,也就是说不能从数据摘要倒推出数据来。但是它可以用来校验数据是否被更改。如果数据有变化,那么摘要通常都是不一样的,概率取决于散列的长度,越长越不容易相同。配合上文所说的非对称加密,如果我用自己的私钥加密了某个摘要,那它就只有用我的公钥才能解密。这就说明了这个摘要一定是我发出的,因为别人不可能有我的私钥。进而推导出摘要所代表的消息也是由我发出的。这个加了密的摘要称为数字签名(Digital signature)。它保证数据的完整性,确定数据的发出者,是具有法律效力的。
原来常用的散列算法有MD5和SHA1,2004年后,山东大学的王小云教授通过碰撞法分别攻破了这两种算法。也就是说,在已知摘要的情况下,可以很快计算出另一个拥有相同摘要的文本,这样就实现了文本篡改。行话叫散列碰撞(Hash Collision)。所以NSA推出了SHA2和SHA3成为了新的标准。虽然MD5和SHA1被破解,也不用特别在意。因为虽然能找到相同摘要的数据,但是篡改者并不能随心所欲地把数据修改成自己想要的样子。
协议
SSL/TLS
有了加密算法,是不是传输就安全了呢?确实如果严格去用的话,是安全了,但是也麻烦了很多。每次都要跟对方沟通用什么算法,传送密钥,传送摘要…累不累?所以需要有一套协议,大家都遵守这样的协议,就能少掉很多我们不需要太关注的、技术上的事情。这个协议叫做SSL(Secure Sockets Layer)。它所做的事情,主要就是上面说的交换公钥,用对方的公钥加密数据,用自己的私钥解密,还支持MD5用于验证数据的完整性。SSL是网景公司发明的,由于应用广泛,成为了事实上的标准。IETF(Internet Engineering Task Force)在1999年把SSL 3.0标准化,称为TLS(Transport Layer Security)。除了标准化以外,相对SSL来说TLS也更加安全一些。
HTTP/HTTPS
因特网发明后,大部分的网站都是用的HTTP协议。这个协议关心的是如何方便地获取到自己需要的资源,并不关心安全性。如果你的网络被监视(比如你的wifi提供者,运营商等等),对方是可以明文看到你的所有信息的,行话叫嗅探(sniffer)。在HTTP上应用SSL/TLS的协议叫做HTTPS(HTTP over SSL/TLS)。有了它,我们就还可以像以前的HTTP那样方便地在网上冲浪,而不用太担心安全问题,但不是完全不需要担心,一会儿我们会说到。
顺便说一句,SSL/TLS并不是只能用于HTTP,还可以用于FTP(File Transfer Protocol)、SMTP(Simple Mail Transfer Protocol)等一系列应用层协议。
CA及证书
数字证书
前面说到了HTTPS,为什么有了这么安全的技术我们还是不能高枕无忧呢?这是因为:虽然它能保证我们的信息不被第三方破解,但是它绕不开一个很现实的绕口问题:你怎么知道他就是他声称的那个他?举个栗子:你以为正在访问的网站是某个银行,但是却不知道其实你被钓鱼(phishing)了。对方正等着你输入你的银行卡号和密码,好用它们去真正的银行网站给自己转账。这一切发生得这么自然,你的信息只有钓鱼网站能解密看到,钓鱼网站的信息也只有你能解密看到…就算是你注意到了对方的域名,也有可能因为0和O、1和l傻傻分不清楚或者域名劫持(domain hijacking)而上当。数字证书就是用来阻止这事儿发生的。虽然我不认识你,但是如果我认识一个很知名的家伙,他肯为你做担保,那我也可以相信你。这个知名的家伙就叫CA(Certificate Authority)。它为通信的双方起了一个中间人的作用。CA的担保就叫数字证书(Digital Certificate或Public Key Certificate)。这个证书是什么格式,有什么内容呢?这是由PKI(Public Key Infrastructure)标准决定的。常用的标准有X.509和PKCS #12。它们定义了证书里应该含有签发机构名、证书用户名、有效期、算法、公钥等信息。
信任链
回到刚才的问题:你怎么知道他就是他声称的那个他?我无条件地信任CA,网站又有了CA的数字证书,我就能信任他就是证书里声称的那个他。如果我因为对CA的信任而有了损失,则证书可以用来追究CA的法律责任。如果我们信任A,A信任B,B信任C,那么我们也会信任B和C,这个叫做证书信任链(Chain of trust)。中间的B称为中级证书(Intermediate certificate),位于信任链顶端的A称为根证书(Root certificate)。如果根证书出了问题,那么它所信任的其它证书也就不再可信了。这个后果可是非常严重,可能会影响整个因特网的信任体系。所以,需要尽可能地少动用根证书以减少根证书的私钥被盗用的风险。如果网站想要被认证,直接用中级证书认证就好了。万一中级证书出问题,吊销掉中级证书也只会影响一部分客户,比整个根证书被吊销掉强。但事情也不绝对。对CA来说,公信力就是一切。说个案例:中国互联网络信息中心(China Internet Network Information Center,CNNIC)是中国的顶级域名.cn
和中文域名的注册管理机构。MCS集团用CNNIC签发的中级证书,发行了多个冒充成Google的假证书。于是在2015年4月份,chrome、firefox都宣布不再信任CNNIC的证书。如果你用chrome来打开https://www.cnnic.net.cn/,应该会看到:
而不是:
一般来说操作系统和浏览器都会内置一些信任的CA,比较著名的有公信力的CA有Verisign,GeoTrust等。我们打开google的时候,也能点击小锁看到它的证书:
再点击证书信息就能看到它的证书链。最上面的是GeoTrust的根证书,它包含的内容都在里面写着了,感兴趣的话就自己看看吧:
中间的是谷歌自己的中级证书:
最后是站点自己的证书,这个有效期一般比较短:
证书是可以自签名的,也就是说,你自己作为CA来发行这个证书。当然,这个证书也只有你自己会信任,广大的网友同志们的眼睛是雪亮的,不会无缘无故地信任你的。那如果我是大企业,是不是就值得信任了?谷歌、微软等通常都是可以信任的。12306,你信任它吗?每个人都会有自己的答案吧。打开12306看看它的根证书,SRCA(SinoRail Certification Authority)是个什么鬼?这个是中国铁路自己啊。知道为什么首页上总有一个“为保障您顺畅购票,请下载安装根证书”的提示了吧。
申请证书
首先,如果你觉得自己的网站没有什么信息不能公开的,那就没必要费那钱和时间去购买证书。
证书有很多种类型,价格也很不一样,大约一年数千到数万元人民币吧。简单列出几种:
- 通配符证书(Wildcard SSL Certificates):自己的域名和下一级子域名可以使用。比如
google.com
和maps.google.com
就是域名和二级子域名的关系 - 多域名证书(Subject Alternative Name SSL Certificates):不仅限于子域名,不同域名也能使用
- 增强型证书(Extended Validation SSL Certificate):总之就是验证流程更麻烦,结果就是可以在地址栏显示公司的名称,增加可信度。就像这样:
申请证书需要给CA提供一个CSR(certificate sigining request)文件。通常做法就是通过程序把域名、联系人和公钥等信息都放在这个文件里,发送给某个CA。交费之后,如果CA方面没有问题,就会对CSR文件设置有效期等操作,当然还需要用自己的私钥对证书签名,再发送给用户。最后用户把证书绑定到自己的网站上。
动手时间
加解密
OpenSSL是SSL/TLS的开源实现,我们就用它来练练手吧。首先,用DES加解密文本:
其中的-a
代表base64编码。还可以多试几次加密,就算文本、密码相同,每次加密的结果也很可能是不一样的。把上面的-des
变成-des3
或者是-aes-256-cbc
就可以自行尝试DES3和AES加解密了。接下来尝试RSA。首先生成RSA的私钥:
PEM表示这是base64编码的密钥,也可以改成DER即二进制的密钥,加上一个-outform DER
的参数就行。然后通过私钥生成公钥:
接下来用刚刚生成的公钥加密,私钥解密:
然后私钥加密,公钥解密。注意这个的意义其实是私钥签名,公钥认证:
散列
现在轮到散列算法了:
也可以用linux自带的小工具实现:
是不是越来越长了?散列越长越不容易被碰撞。
证书
申请证书,首先需要生成CSR文件。而CSR文件需要先生成私钥:
生成私钥文件是可以加密的,加上一个参数比如-des3
就可以了。生成CSR文件的时候需要填写各种信息,没耐心就随便写点什么甚至一路回车也行,反正又不是真的去找CA。如果你真的有需求,这里有一张表格说明了应该怎么填。填完的东西可以这么看:
现在我们假装自己是个CA,有自己的密钥对,然后对刚才提交的CSR文件签名:
大功告成!生成的my_domain.crt就是我们要的证书。由于这个是自签名证书,默认是不被我们的操作系统信任的。如果我们需要增加信任,可以参考这里。比如在Ubuntu/Debian里可以这么做:
如果要取消信任,可以这么做:
参考资料
How Encryption Works
有关SSL证书的一些事儿
SSL/TLS原理详解
OpenSSL 与 SSL 数字证书概念贴
数字证书及 CA 的扫盲介绍
扫盲 HTTPS 和 SSL/TLS 协议
数字签名是什么?
CNNIC证书值得信任吗?