写在最前面
最近一段时间,国内各大网站纷纷用上了https连接,在访问这些网站的时候,很多浏览器会给予“特别关照”,给它们的链接旁边加上一个绿色的小锁,那么,什么是https,它与网络安全又有什么关系呢?今天我们就来谈谈https与tls(传输层安全)。
我不是计算机专业的学生,没有系统学过计算机网络相关的知识,写这篇文章是因为之前给自己挖过一个坑不得不填上,文章内容大部分来自于网络,我大概只是做了下整合,所以如果有什么错误还请大家指出,谢谢。
http之罪,为什么不安全?
http协议在制定之初,其目的仅仅是为了方便地完成html网页内容的交换,没有过多考虑安全性问题,http连接不进行身份认证,同时内容是明文传输,因此采用http协议传输的内容对于任何人来说都是公开的;这带来了很严重的安全问题:如果有人创建一个开放热点,并对连接该热点的用户http数据进行抓包,便可以轻松获取用户的用户名、密码或者其他敏感信息;这里有一个通过Wireshark抓包获取用户名、密码的例子:Wireshark如何抓明文用户名和密码;其它情况下还可以做到的,诸如分析你浏览的页面内容、替换页面内容等等,在此不再一一举例;
什么是https/TLS?
HTTPS(全称:Hyper Text Transfer Protocol over Secure Socket Layer),是以安全为目标的HTTP通道,简单讲是HTTP的安全版,它建立在SSL(Secure Sockets Layer 安全套接层)之上,其目的是保障网络数据传输的安全。TLS(Transport Layer Security 传输层安全)是SSL的继任者,从对应关系上看应该可以算是SSL的子集。可以说,目前的https都是基于TLS而得以实现的,因此下面我们就来着重讲一讲TLS的实现及其安全性。
TLS
一个形象的解释(感谢知乎的天才老哥们)
生活中大家应该都用过一种锁,你可以用对应的钥匙打开它,打开之后如果拔出钥匙,你将合不上锁(我知道现在很多锁拔出钥匙后也能合上了,但请大家稍微配合一下_(:з)∠)_):
下面我们用锁来讲一个故事,帮助大家更好地理解TLS的工作方式。
A和B是分隔两地的商业伙伴,两地之间除了信件往来没有其他的通讯方式,并且两地之间的信件通行状况非常糟糕,经常有人伪装成邮递员私拆信件甚至更改信件内容,曾经也有人用普通锁锁上坚固的盒子来快递,但是并没有安全的方法能把钥匙安全地送给对方而不被中间人复制;A与B想要互通信件,但是又不想让交流的内容被别人知道;恰好两人都了解有一个很聪明的人发明了一种锁,这种锁不同于以往,它需要用两把钥匙分别完成开锁和合锁的过程,一把钥匙只能开不能合,另一把只能合不能开(非对称加密),于是两人在信件内容没有被篡改的情况下约定了一种交流方式:
- A现在手持一把特殊锁{Special_Lock}和两把对应的钥匙{Public_Key}(公钥)与{Private_Key}(私钥),其中{Public_Key}只能用来合锁,{Private_Key}只能用来开锁;首先A用私钥打开{Special_Lock},并把打开的{Special_Lock}与{Public_Key}通过快递寄给B;
- B收到寄来的{Special_Lock}和{Public_Key}之后,把一把普通的锁{Lock_B}(对称加密)和钥匙{Key_B1}装到一个足够坚固不会被破坏的盒子里,用寄来的{Special_Lock}锁上(锁的时候需要用到{Public_Key}),并寄还给A,同时B手上还有这把普通锁的备用钥匙{Key_B2},它与{Key_B1}一模一样;
- A收到B寄来的使用{Special_Lock}锁着的包裹后,悄悄地拿出藏起来的{Private_Key},把特殊锁打开,拿到了属于B的{Lock_B}和能够锁上、打开这把锁的{Key_B1},于是A很开心地写了封“Hello world!”,找了个坚固的盒子放了进去,并且用{Lock_B}和对应的钥匙{Key_B1}锁上了盒子,保留了{Key_B1}并把盒子寄还给了B
- B收到快递后,使用备用钥匙{Key_B2}打开了锁{Lock_B},得到了信件;
完成以上动作之后:A拥有了B提供的锁与钥匙,此后两人便可以用这个锁来进行安全的通信({Lock_B}的钥匙只有两人拥有),也就是说,两人通过非对称加密的方式协商了一个{Lock_B}以及对应的钥匙{Key_B1}、{Key_B2},此后一直通过对称加密{Lock_B}进行通讯;
现在还有一点疑问,诚然,有了第一步的特殊锁之后,送信人员不可能打开这把锁了(因为TA没有私钥{Private_Key}),但这还有一个问题,如果送信人员M悄悄扣留了A的特殊锁及其公钥,然后送给B一个自己的特殊锁及其公钥{FAKE_Special_Lock}和{FAKE_Public_Key},在B给A回信送{Lock_B}以及{Key_B1}的时候,M就可以用{FAKE_Private_Key}打开那个盒子,取出锁和钥匙,复制一份钥匙,并用之前扣留的{Special_Lock}和{Public_Key}封装起来还给A;经过这个操作,M在两者都不知情的情况下获得了接下来A、B通信所需要使用的加密密码{Key_B1};
对此TLS提出了一个解决办法:
- 找一个德高望重的人(CA),用他独一无二的签名给最初的A的那把{Special_Lock}做一个认证:这把锁是A所有——由“X”CA认证;这名德高望重的人X恪守规矩——绝对不会给不是A的锁作这个认证;因为这位大人的签名没人能模仿,因此B收到特殊锁之后只要看一眼签名是不是发给A的就知道锁有没有被掉包过了,当然前提是,A、B都信任这位德高望重的大人。
可是某一天A需要和一位与B住在同一城市的商业伙伴C联系,A与C想要效仿之前的操作建立一个安全的联系方式,但是C并不信任X这个人,因此B只好又找了个德高望重的人Y,A、B、C都信任这个Y先生;Y先生很忙,没法直接认证A的特殊锁,因此Y仅仅签名认证了X,并委托X在锁上加上了“X经过Y的‘CA认证,可以认证锁的从属’”的字样;下次C拿到{Special_Lock}之后,看到这行字,就选择信任X对特殊锁的认证,并成功和A建立了加密通信;
A的商业伙伴越来越多,人们的信任关系错综复杂,即使找来更有威望的Z给Y先生认证,也终究不是办法,最后人们选出了一个最有威望的人“ROOT”,并且大家约定,只要是“ROOT”认证过的人或者是锁,大家都无条件地信任;这位“ROOT”就是根CA,TA所写的“ROOT认证xxx”的内容,称为根证书。
至此信件的安全问题已经被完美解决了,然而在实际操作中还有一些细节,比如非对称加密很复杂,消耗的计算时间较长,因此不用在正常的通信中,仅作为链接发起时,协商对称加密的密钥时使用,正常通信是使用对称加密进行的。
非对称加密
- 因为本人实在水平有限,因此这部整段搬运了知乎用户刘叔的文章非对称加密算法与TLS中的内容,侵删……
RSA是最古老,最成熟,也是应用最广泛的非对称加密算法,其发明时间早在1978年。RSA三个字母就是三个发明人的名字的首字母。
RSA利用的核心思想就是大素数分解的问题。这个问题虽然理解起来简单,但是破解起来非常难,以至于RSA至今为止仍旧是应用最广泛的非对称加密算法。虽然描述起来是两个大素数分解因式,但是实际的实现相对复杂很多。不是任何的两个大素数都可以用,而必须要满足一系列的条件。本书不是一本密码学的书,不进行深入探讨。
数学上,RSA算法的原理非常简单(密文为X,明文为A):
加密:$$X=A^E \bmod N$$
解密:$$A=X^D \bmod N$$
也就是说加密和解密的运算形式是完全一样的,公式里面$E$或者$D$叫做离散对数。RSA算法的数学基础就建立在已知其他值,$D$不可解的前提下。这里面$E$和$N$共同组成公钥,$D$和$N$共同组成私钥。所以整个加密算法剩下的唯一问题就是如何确定$E,D,N$三个字母了。
确定的方法是取两个大素数$p$和$q$。$p$和$q$相乘就是$N$:$N=pq$。在计算$E$和$D$之前要计算一个中间值,这个值叫做$L$:$L=lcm(p-1, q-1)$。lcm的意思是最小公倍数,也就是说$L$的值等于$p-1$和$q-1$的最小公倍数。下面就可以得到$E$了:$gcd(E,L)=1$。gcd表示最大公约数,也就是说$E$的值为与$L$互质的数。这个数在数学上的求法并不是多么的高端,而是简单的随机生成大数,然后与$L$求最大公约数,看看结果是不是1。也就是说是一个暴力尝试的方法。得到了$E$和$N$,我们就得到了公钥了。$D$的值是根据$E$计算得到的:$ED \bmod L=1$。解这个式子就可以得到$D$,也就是得到了私钥。整个RSA过程就结束了。RSA的加密与解密非常的简介易懂,这也是其迅速普及的原因。广泛使用的原因。整个RSA的安全性依赖于$N=q*p$,$N$对外部是已知的,已知$N$的情况下,如果能分解得到$q$、$p$,那么RSA就没有安全性可言。所以也可以说整个RSA的安全性就依赖于大素数分解因式了,当然也可以说依赖于求离散对数问题,他们是一个问题的两个方面,主要的破解方式是大素数分解因式。主要依赖于离散对数安全性的非对称加密算法是EIGamal算法。
另一个常用的加密算法是ECC算法,采用椭圆曲线来构造密钥:
Server Key Exchange里面的最重要的参数就是ECDHE算法需要构造的密码学参数。可以看到一个是椭圆曲线的名字:secp256r1。这个椭圆曲线不但在HTTPS中,还在比特币中有广泛的应用,所有的椭圆曲线实际上都是方程:$y^2=x^3+ax+b$ 。这里面两个参数,这个椭圆曲线是一大类的曲线,对于secp256r1来说,a=0, b=7。所以对于secp256r1来说,这条曲线是$y^2=x^3+7$。$a$,$b$参数的取值并不是随便取的,必须要满足一定的条件,并且一条密码学曲线都是固定取值的。不同的$a$,$b$会得到非常不一样形状的图形,不同的图形有不同的用途,我们这里讨论的secp256r1曲线的图形如下:
这条曲线的形状如图。在密码学上,所有的椭圆曲线都是使用的有限域版本$GF(p)$,所以$p$也是一个椭圆曲线的一个值。对于secp256k1来说,他的$p=2^{256}-2^{32}-2^9-2^8-2^7-2^6-2^4-1$,椭圆曲线的方程是$y^2=x^3+7 \bmod p$。
椭圆曲线之所以被选择出来是因为他有众多非常有意思的特性,例如在椭圆曲线上拉一条直线,经过三个点,那三个点的和是0(那就看曲线怎么定义和这个操作了,这里是数论里的阿贝尔群)。本质上,使用椭圆曲线是使用了椭圆曲线的性质来得到一个数学运算系统,最终在参与密码学计算的是数论系统,与椭圆曲线就没有太大关系了,但是仍然可以用曲线来理解,因为数论运算是基于椭圆曲线构造的。
当这个椭圆曲线算法用于非对称加密的密钥交换的时候,我们知道两个人都能看到对方的公钥,并且都知道自己的私钥。椭圆曲线算法在使用的时候能够看到与RSA的一个最大的不同,就是RSA需要一个私钥,椭圆曲线并不需要。对于椭圆曲线做密钥交换,每一次通信的私钥和公钥都是临时生成的,这也是椭圆曲线比RSA安全性高的原因。因为RSA一旦私钥泄漏,历史的加密数据都能破解,而椭圆曲线不能。每一次通信都用完全不同的私钥公钥对进行信道协商。所以对于椭圆曲线来说,在每一次通信的时候都会首先生成这个私钥和公钥,生成私钥的方法就是在椭圆曲线上取一个点,根据上面说过的三点和等于0的特性,让两个点重合,重合之后,这条曲线就是椭圆的切线,与椭圆相交于两个点。非切点的那个点就是私钥,切点取反再多切线得到一个新的切点,如果多次取反做切点就得到了公钥点。$Q=NG$,$G$是私钥点,$N$是做切线的次数,$Q$是公钥。已知$Q$,算不出$G$,就是椭圆曲线生成公钥私钥的原理了。这里面对于椭圆曲线来说,$N$是一个公开的常数,双方都知道并且相同,也就是说,这个数学难题是已知了一个点,求$N$次反向的求切线运算得到的那个点。这个点是计算难度上得不出来的。也就是说已知一点曲线上的切点,得到切线的难度比已知一个随意点,对曲线做切线的计算度复杂很多,多到多次计算就是计算不可能问题。
当椭圆曲线生成的公钥和私钥用于交换的时候,因为双方已经互换了公钥,这个计算过程就变成了双方同时用自己的私钥乘以对方的公钥。椭圆曲线的神奇特性保证了得到的结果是一样的,也就是说是得到了同一个点。这个点就是协商得到的对称加密的密钥。
总结
已经写昏了……总结先摸了,哪天想起来了再写吧……