频道栏目
首页 > 资讯 > 加密解密 > 正文

探讨一下加密、证书的那些事儿

16-03-18        来源:[db:作者]  
收藏   我要投稿

 现在网络这么发达,许多人都在上面购物、理财、预约挂号…网络上传送的可都是自己的重要资料,比如身份证号,信用卡密码等。因特网如何才能保证这些敏感信息的安全?本文试着来探讨一下加密、证书等那些事儿。

历史隐藏信息

古代交通不便,一般都是通过送信的方式传递信息。那么如何保证信件的内容不被泄露呢?一种方法是隐藏字迹。中国古代使用矾书,也就是用明矾水来书写保密书信。水干之后没有任何痕迹,泡水时字才显示。还有一招是使用淀粉水在纸上写字,再把纸泡在碘水中显示字迹。据知乎的水波说在西方世界里,也有使用牛奶或者羊奶书写信息,待干掉以后再用高温烘烤使之重新显现字迹的说法。这些办法一旦为人所知,便会轻易被破解,而且还有点儿此地无银三百两的意思。

加密信息

除了隐藏信息以外,还有加密的方法。在宋代兵书《武经总要》里,约定了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位或以上。密钥这么大,非对称加密的速度比较慢(与对称加密有千倍的差距)也是可以理解的。所以在实际的使用当中一般用对称加密来加密数据,非对称加密来加密对称加密的密钥。

散列算法

好吧,密码破解不了,但是攻击者可以截取加密后的数据包,然后篡改。这样“传位十四皇子”就变成了“传位于四皇子”啦。散列算法堵死了这条路。它能把很长的数据变成固定长度的文本。也称为数据的指纹(fingerprint)。相同数据的指纹一定是一样的,不同数据的指纹有可能一样,但是通常不一样。正因如此,散列算法是不可逆的,也就是说不能从数据指纹倒推出数据来。但是它可以用来校验数据是否被更改。如果数据有变化,那么指纹通常都是不一样的,概率取决于散列的长度,越长越不容易相同。本来常用的散列算法有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)是个什么鬼?这个是中国铁路自己啊。知道为什么首页上总有一个“为保障您顺畅购票,请下载安装根证书”的提示了吧。

申请证书

申请证书需要给CA提供一个CSR(certificate sigining request)文件。通常做法就是通过程序把域名、联系人和公钥等信息都放在这个文件里,发送给某个CA。交费之后,CA就会对CSR文件设置有效期等操作,当然还需要用自己的私钥对证书签名,再发送给用户。最后用户把证书绑定到自己的网站上。

动手时间加解密

OpenSSL是SSL/TLS的开源实现,我们就用它来练练手吧。首先,用DES加解密文本:

 

1
2
echo Hello World! | openssl enc -e -des -a -salt    ## 需要输入两次密码,如果你输入的都是1,那么可以用下一条命令解密
echo U2FsdGVkX1/J5B1od/3gTMcX1/DJQFEW+GizDVK1rUg= | openssl enc -d -des -a -salt

 

还可以多试几次加密,就算文本、密码相同,每次加密的结果也很可能是不一样的。把上面的-des变成-des3或者是-aes-256-cbc就可以自行尝试DES3和AES加解密了。接下来尝试RSA。首先生成RSA的私钥:

 

1
2
openssl genrsa -out private.pem 2048
cat private.pem

 

PEM表示这是base64编码的密钥,也可以改成DER即二进制的密钥,加上一个-outform DER的参数就行。然后通过私钥生成公钥:

 

1
2
openssl rsa -in private.pem -pubout -out public.pem
cat public.pem

 

接下来用刚刚生成的公钥加密,私钥解密:

 

1
2
3
echo Hello World! | openssl rsautl -encrypt -pubin -inkey public.pem -out encrypt
cat encrypt
cat encrypt | openssl rsautl -decrypt -inkey private.pem

 

然后私钥加密,公钥解密。注意这个的意义其实是私钥签名,公钥认证:

 

1
2
3
echo Hello World! | openssl rsautl -sign -inkey private.pem -out encrypt
cat encrypt
cat encrypt | openssl rsautl -verify -pubin -inkey public.pem

 

 

散列

现在轮到散列算法了:

 

1
2
echo Hello World! | openssl dgst -md5
echo Hello World! | openssl dgst -sha1

 

也可以用linux自带的小工具实现:

 

1
2
3
4
5
6
echo Hello World! | md5sum
echo Hello World! | sha1sum
echo Hello World! | sha224sum
echo Hello World! | sha256sum
echo Hello World! | sha384sum
echo Hello World! | sha512sum

 

是不是越来越长了?散列越长越不容易被碰撞。

证书

申请证书,首先需要生成CSR文件。而CSR文件需要先生成私钥:

 

1
2
3
openssl genrsa -out private.pem 2048
openssl req -new -key private.pem -out domain.csr
cat domain.csr

 

生成私钥文件是可以加密的,加上一个参数比如-des3就可以了。生成CSR文件的时候需要填写各种信息,没耐心就随便写点什么甚至一路回车也行,反正又不是真的去找CA。如果你真的有需求,这里有一张表格说明了应该怎么填。填完的东西可以这么看:

 

1
openssl req -noout -text -in domain.csr

 

现在我们假装自己是个CA,有自己的密钥对,然后对刚才提交的CSR文件签名:

 

1
2
3
openssl genrsa -out private_ca.pem 2048
openssl x509 -req -days 365 -in domain.csr -signkey private_ca.pem -out my_domain.crt
cat my_domain.crt

 

大功告成!生成的my_domain.crt就是我们要的证书。由于这个是自签名证书,默认是不被我们的操作系统信任的。如果我们需要增加信任,可以参考这里。比如在Ubuntu/Debian里可以这么做:

 

1
2
sudo cp my_domain.crt /usr/local/share/ca-certificates/
sudo update-ca-certificates

 

如果要取消信任,可以这么做:

 

1
2
sudo rm /usr/local/share/ca-certificates/my_domain.crt
sudo update-ca-certificates --fresh

 

 

相关TAG标签
上一篇:攻击单片机的攻击技术浅析
下一篇:JDK将新增局部变量类型推断功能(相关介绍)
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站