不使用 SSL/TLS 的 HTTP 通信,就是不加密的通信。所有信息明文传播,带来了三大风险。
SSL/TLS 协议是为了解决这三大风险而设计的,希望达到:
SSL/TLS 协议的基本思路是采用公钥加密法,也就是说,客户端先向服务器端索要公钥,然后用公钥加密信息,服务器收到密文后,用自己的私钥解密。
但是,这里有两个问题。
如何保证公钥不被篡改
解决方法:将公钥放在数字证书中。只要证书是可信的,公钥就是可信的。
公钥加密计算量太大,如何减少耗用的时间
解决方法:每一次对话(session),客户端和服务器端都生成一个对话密钥(session key),用它来加密信息。由于对话密钥是对称加密,所以运算速度非常快,而服务器公钥只用于加密对话密钥本身,这样就减少了加密运算的消耗时间。
因此,SSL/TLS 协议的基本过程是这样的:
上面过程的前两步,又称为握手阶段(handshake)。
"握手阶段"涉及四次通信,我们一个个来看。需要注意的是,"握手阶段"的所有通信都是明文的。
首先,客户端(通常是浏览器)先向服务器发出加密通信的请求,这被叫做 ClientHello 请求。
在这一步,客户端主要向服务器提供以下信息:
这里需要注意的是,客户端发送的信息之中不包括服务器的域名。也就是说,理论上服务器只能包含一个网站,否则会分不清应该向客户端提供哪一个网站的数字证书。这就是为什么通常一台服务器只能有一张数字证书的原因。
对于虚拟主机的用户来说,这当然很不方便。2006年,TLS 协议加入了一个 Server Name Indication 扩展,允许客户端向服务器提供它所请求的域名。
服务器收到客户端请求后,向客户端发出回应,这叫做 SeverHello。服务器的回应包含以下内容。
除了上面这些信息,如果服务器需要确认客户端的身份,就会再包含一项请求,要求客户端提供"客户端证书"。比如,金融机构往往只允许认证客户连入自己的网络,就会向正式客户提供 USB 密钥,里面就包含了一张客户端证书。
客户端收到服务器回应以后,首先验证服务器证书。如果证书不是可信机构颁布、或者证书中的域名与实际域名不一致、或者证书已经过期,就会向访问者显示一个警告,由其选择是否还要继续通信。
如果证书没有问题,客户端就会从证书中取出服务器的公钥。然后,向服务器发送下面三项信息。
上面第一项的随机数,是整个握手阶段出现的第三个随机数,又称"pre-master key"。有了它以后,客户端和服务器就同时有了三个随机数,接着双方就用事先商定的加密方法,各自生成本次会话所用的同一把"会话密钥"。
为什么一定要用三个随机数,来生成"会话密钥":
不管是客户端还是服务器,都需要随机数,这样生成的密钥才不会每次都一样。由于 SSL 协议中证书是静态的,因此十分有必要引入一种随机因素来保证协商出来的密钥的随机性。
对于 RSA 密钥交换算法来说,pre-master-key 本身就是一个随机数,再加上 hello 消息中的随机,三个随机数通过一个密钥导出器最终导出一个对称密钥。
pre master secret 的存在在于 SSL 协议不信任每个主机都能产生完全随机的随机数,如果随机数不随机,那么 pre master secret 就有可能被猜出来,那么仅适用 pre master secret 作为密钥就不合适了,因此必须引入新的随机因素,那么客户端和服务器加上 pre master secret 三个随机数一同生成的密钥就不容易被猜出了,一个伪随机可能完全不随机,可是是三个伪随机就十分接近随机了,每增加一个自由度,随机性增加的可不是一。
同时需要注意前两个随机数都是明文传输的,窃听者是可以轻易获取到的,只有最后一个 pre master secret 是加密传输的,只有拥有服务器私钥才能解密,一旦 pre master secret 泄露,那么本次通信就就完全可被破解了。
此外,如果前一步,服务器要求客户端证书,客户端会在这一步发送证书及相关信息。
服务器收到客户端的第三个随机数 pre-master key 之后,计算生成本次会话所用的"会话密钥"。然后,向客户端最后发送下面信息:
至此,整个握手阶段全部结束。接下来,客户端与服务器进入加密通信,就完全是使用普通的 HTTP 协议,只不过用"会话密钥"加密内容。
之后双方就拿着这个对称加密秘钥来进行正常的通信
对对称加密的通俗理解:
即通信的双方都使用同一个秘钥进行加解密
对非对称加密算法的通俗理解:
不过,以上方式存在明显的中间人问题:
假设,此时在客户端和服务器之间存在一个中间人,这个中间人只需要把原本双方通信互发的公钥,换成自己的公钥,这样中间人就可以轻松解密通信双方所发送的所有数据
为解决上述中间人问题,于是后来就出现了证书,简单来讲就是找了一个大家公认的中介,来证明我就是我,你就是你的问题,防止中间被篡改:
证书中就包括个人的基本信息和最重要的公钥
乍一眼看去,上面的方案貌似还不错,但证书在传输的过程中如果被篡改了呢,所以后来就又出现了数字签名:
======================================================================
网络前端http
阅读约 17 分钟
本文主要是对HTTPS做一个总结,主要讲解HTTPS的实质、HTTPS加密原理、HTTPS的通信过程等。
由于HTTP协议过于简单:
为了解决诸多问题,HTTPS应运而生。
HTTP加上加密处理、认证机制、以及完整性保护后的就是HTTPS。
需要知道的是,HTTPS并非是应用层的一种新的协议。只是HTTP通信接口部分用SSL或TLS协议代替而已。也就是说,所谓的HTTPS,其实就是身披SSL协议外壳的HTTP。
值得一提的是,SSL是独立于HTTP协议的,也就是说其他运行在应用层的协议均可配合SSL协议使用。现今SSL是最为广泛的网络安全技术。
HTTPS中使用了SSL和TLS这两个协议。
TLS以SSL3.0为基准,后又制定了TLS1.0、TLS1.1和TLS1.2。当前主流的版本是SSL3.0和TLS1.0。
TLS是以SSL为原型开发的协议,有时候会统称该协议为SSL。
近代的加密算法中加密算法是公开的,而密钥是保密的。通过这种方式来保持加密方法的安全性。
加密和解密要用到密钥,如果没有密钥就没有办法对密码解密。换句话来说,任何人只要持有密钥就能够对密文进行解密。
HTTPS在加密过程中使用了非对称加密技术和对称加密技术。
采用单钥密码系统的加密方式,同一个密钥可以同时做信息的加密和解密,这种加密的方法称为对称加密,也称为单密钥加密。
下面会把对称加密算法称为共享密钥加密算法。
假如现在,SSL在通信过程中,使用了对称加密算法,也就是说客户端和服务器同时共享一个密钥。
于是,以共享密钥的方式加密,必须将密钥发给对方。这个时候,假如通信过程被监听,密钥被攻击者获取了,那么这个时候也就失去了加密的意义了。
那么,有没有办法解决这个问题呢?答案是肯定的,也就是使用两把密钥。
下面先看使用两把密钥的非对称加密算法。
与对称加密算法相反,非对称加密算法需要两个密钥来进行加密和解密,这两个密钥是配对的,分别是公开密钥(公钥)和私有密钥(私钥)。
一般情况下,公钥是可以被公开的,它主要用来加密明文。而相应的,私钥不能被公开,用来解密公钥加密的密文。
值得注意的是:公钥加密后的密文只能通过对应的私钥来解密,而私钥加密的密文却可以通过对应的公钥来解密。
以上,公钥加密私钥解密用来加密,私钥加密公钥解密用来签名。相关用途后面会讲到。
下面会把非对称加密算法称为公开密钥加密算法。
于是现在,假设现在由服务器来生成一对公钥和私钥。
当客户端第一次发请求和服务器协商的时候,服务器就生成了一对公钥和私钥。
紧接着,服务器把公钥发给客户端(明文,不需要做任何加密),客户端接收后,随机生成一个密钥,使用服务器发过来的公钥进行加密。
再接着,客户端把使用公钥加密的密钥发给服务器,服务器接收到了以后,用配对的私钥进行解密,就得到了客户端随机生成的那个密钥。
这个时候,客户端和服务端所持的密钥都是相同的。此时,交换密钥环节就完成了。
于是通信开始时就可进行上面所述的共享密钥加密方式来进行加密。
可能,有小伙伴就会问,为什么要大费周章使用非对称加密的方式,然后再得到相同的密钥,进行共享密钥加密的通信呢?
由于公开密钥加密处理起来比共享密钥加密方式更为复杂,因此在通信的时候使用公开密钥加密的方式,效率很低。
于是,我们需要使用非对称加密的方式来保证密钥共享的过程中密钥的安全性,而后在通信的过程中使用对称加密算法,这是最合理的设计方式,在保证安全性的同时又保证了性能。
所以,HTTPS采用共享密钥加密和公开密钥加密两者并用的混合加密机制。在交换密钥使用环节使用公开密钥加密方式,之后建立的通信交换报文阶段则使用共享密钥加密方式。
以上,大概就是使用对称加密和非对称加密的过程。看似过程很完美,其实还存在着一个问题,就是:如何保证服务器传过来的公开密钥的正确性。换句话说,就是保证它不被拦截篡改。
假如现在正准备和某台服务器建立公开密钥加密方式下的通信,如何证明客户端收到的公开密钥就是原本预想的那台服务器发行的公开密钥呢?或许,在公开密钥传输的过程中,真正的公开密钥可能已经被攻击者替换掉了。
为了解决这个问题,可以使用由数字证书机构和其相关颁发的公开密钥证书。
下面阐述一下数字证书认证机构(简称CA)的业务流程:
首先,服务器的运营人员向数字证书机构提出公开密钥的申请。数字证书认证机构在判明提出申请者的身份之后,会对已申请的公开密钥做数字签名,然后分配这个已签名的公开密钥,并将该公开密钥放入公钥证书后绑定在一起。
我们用白话文来翻译一下上面这段话:
接下来,服务器会把这份由数字证书认证机构颁发的公钥证书发给客户端。这个时候,客户端可以使用数字证书机构的公开密钥对其进行验证。一旦验证成功,客户端便能够确定这个公开密钥是可信的。
我们再用白话文来翻译一下:
那客户端上面的CA公钥是从哪里来的呢?
其实,CA除了给申请者发布证书,它自己本身也有自己的证书。CA自身的数字证书(一般由它自己生成)在我们操作系统刚安装好的时候,这些CA自身的数字证书就已经被微软(或者其它操作系统的开发机构)安装在操作系统中了。而CA的公钥就包含在其中。这样,CA就可以通过自身的私钥对发布的数字证书进行签名,而在客户端就能够用对应的公钥来对其进行解密。
其具体过程是这样子的(图中简化了数字签名的过程):
这里其实就用到了非对称加密算法,只不过现在这个加密算法用来签名而不是加密。
使用私钥加密,公钥解密,用于公钥的持有者验证通过私钥加密的内容是否被篡改,但是不用来保证内容是否被他人获得。
而使用公钥加密,私钥解密,则是相反的,它不保证信息被他人截获篡改,但是保证信息无法被中间人获得。
HTTPS中不仅可以使用服务器证书,还可以使用客户端证书。以客户端证书进行客户端认证,它的作用与服务器证书是相同的。
由于客户端获取证书需要用户自行安装客户端证书,同时也面临着费用的问题。
因此,现状是,安全性极高的认证机构可办法客户端证书但是仅用于特殊用途的业务。比如那些可支撑客户端证书支出费用的业务。
例如,银行的网上银行就采用了客户端证书。在登录网银时不仅要求用户确认输入ID和密码,还会要求用户的客户端证书,以确认用户是否从特定的终端访问网银。
现在我们来理清一下SSL建立的过程:
Pre-master secret
的随机密码串。该报文使用从证书中解密获得的公钥进行加密(其实就是服务器的公钥)。 Pre-master secret
取出来。接着,服务器同样发送Change Cipher Spec报文。读到这里,你可能会对上面的一些细节产生很多疑惑,现在我们一个个来理清楚?
问题一
为什么最后客户端和服务端都要发送一个Finish报文?
上面已经提及,Finish报文是对至今全部报文的整体校验值(也就是HASH值)。当客户端把这个值通过得到的公钥进行加密的时候,服务器得到之后对其进行解密,然后再对全部报文进行一个HASH求值。如果这个值跟解密得到的值相等的话,那么说明客户端是可信赖的。
同样的,服务器发送这样的一个整体校验值,用来客户端验证服务器是否是真正要进行通信的那一个。
综上,这个Finish报文就是用来校验双方的身份的。
问题二
整个过程中产生的三个随机数有什么用呢?还有,后面进行HTTP通信的时候,是用哪一个密钥进行加密,还有怎么保证报文的完整性。
看下面这张图。
对于客户端:
当其生成了Pre-master secret
之后,会结合原来的A、B随机数,用DH算法计算出一个master secret
,紧接着根据这个master secret
推导出hash secret
和session secret
。
对于服务端:
当其解密获得了Pre-master secret
之后,会结合原来的A、B随机数,用DH算法计算出一个master secret
,紧接着根据这个master secret
推导出hash secret
和session secret
。
在客户端和服务端的master secret
是依据三个随机数推导出来的,它是不会在网络上传输的,只有双方知道,不会有第三者知道。同时,客户端推导出来的session secret
和hash secret
与服务端也是完全一样的。
那么现在双方如果开始使用对称算法加密来进行通讯,使用哪个作为共享的密钥呢?过程是这样子的:
双方使用对称加密算法进行加密,用hash secret
对HTTP报文做一次运算生成一个MAC
,附在HTTP报文的后面,然后用session-secret
加密所有数据(HTTP+MAC
),然后发送。
接收方则先用session-secret
解密数据,然后得到HTTP+MAC
,再用相同的算法计算出自己的MAC
,如果两个MAC
相等,证明数据没有被篡改。
MAC(Message Authentication Code)称为报文摘要,能够查知报文是否遭到篡改,从而保护报文的完整性。
问题三
为什么要使用三个随机数呢?
网友dog250是这么解释的:
"不管是客户端还是服务器,都需要随机数,这样生成的密钥才不会每次都一样。由于SSL协议中证书是静态的,因此十分有必要引入一种随机因素来保证协商出来的密钥的随机性。
对于RSA密钥交换算法来说,pre-master secret
本身就是一个随机数,再加上hello消息中的随机,三个随机数通过一个密钥导出器最终导出一个对称密钥。
pre-master secret
的存在在于SSL协议不信任每个主机都能产生完全随机的随机数,如果随机数不随机,那么pre-master secret
就有可能被猜出来,那么仅适用pre-master secret
作为密钥就不合适了,因此必须引入新的随机因素,那么客户端和服务器加上pre-master secret
三个随机数一同生成的密钥就不容易被猜出了,一个伪随机可能完全不随机,可是是三个伪随机就十分接近随机了,每增加一个自由度,随机性增加的可不是一。"
注:我们在计算机所使用的随机数都是伪随机,而不是物理上所说的真正随机。
另外,黑客可能拦截了这样的一个加密的报文,他不对报文进行修改,而是不停的向报文的接受者发送重复的报文,以扰乱通信的建立。于是,就可以加这么一个随机数。只要任何一个通信方,接收到的报文中的随机数出现重复的情况,就可以知道有中间者对通信的过程进行了扰乱,可以立即中断通信。
问题四
如果黑客拦截了服务器把证书发送给客户端,并对证书进行恶意修改,会出现什么情况?
第一种情况,假如黑客只是单纯的修改数字证书中的内容,那么由于数字签名的存在,客户端会很容易的判断出报文是否被篡改。
第二种情况,黑客不仅修改了数字证书的内容,并且把数字签名替换掉了,由于黑客不可能知道CA的私钥,于是在客户端用CA的公钥进行解密的时候,解密之后得不到正确的信息,也很容易判断出报文是否被修改。
第三种情况,黑客恶意的从相同的第三方CA申请了一个数字证书。由于这个CA是真实存在的,所以客户端是可以用CA的公钥进行解密,得到了黑客提供的数字证书中的公钥。但是,由于数字证书在申请的时候,会绑定一个域名,当客户端比如说浏览器,检测到这个数字证书中的域名和我们现在网页访问的域名不一致,便会发出警告,此时我们也能得知数字证书被替换了。发出的警告如下:
当HTTP披上SSL外壳之后,由于加入了诸多验证的机制,虽然安全性大大提高了,但是它的处理速度会变慢。慢的原因分以下两种:
可见,使用HTTPS会消耗更多的资源。如果每次通信都加密,那么平摊到一台计算机上,能够处理的请求数量也必定会减少。
同时,使用HTTPS需要向CA购买证书,于是开销也成为考虑是否使用HTTPS的原因之一。
所以,大部分的Web网站都采取了一个折中的方法。对于一些需要隐藏、私密的信息进行加密,而普通的信息不进行加密处理,以节省资源。
很多时候我们可以通过fiddler来进行抓HTTP包,但是当遇到连接采用的是HTTPS的时候,过程可能就不那么愉快了。但实际上实现拦截也十分简单。
fiddler拦截HTTPS请求最核心的地方在于真正的客户端需要安装fiddler的证书。这样子的话,fiddler能够伪造出CA证书,达到欺骗客户端,拿到需要的信息并推算出之后双方正常通信的对称加密密钥。
这学期刚好有《信息安全》这门课程,那就简明的介绍一下公钥密码密码体系RSA算法原理是什么。
它是这样子工作的:
p
和q
,相乘得到n
。p-1
和q-1
相乘,得到f(n)
。e
与f(n)
互质,然后得到公钥(e, n)
。ed = 1 mod f(n)
。 [这是一个等价关系而不是一个表达式!也就是ed
模fn(n)
的结果是1,这是求模运算的逆运算,可以用欧几里德辗转相除法求得](d, n)
。整个RSA公钥密码算法的难度其实在于分解这一个大数n
,pq=n
正向运算很容易,逆向运算很困难,随着这个数越来越大,想要逆向分解需要很多年的时间。