数据保密之HTTPS加密通信过程


1  HTTPS加密通信过程的演示

我们来看一个例子,现在假设服务器客户要在网络上通信,并且他们打算使用RSA来对通信进行加密以保证谈话内容的安全。由于是使用RSA这种公钥密码体制,服务器需要对外发布公钥(算法不需要公布,RSA的算法大家都知道),自己留着私钥。客户通过某些途径拿到了服务器发布的公钥,客户并不知道私钥。通信过程图如下所示:


数据保密之HTTPS加密通信过程
 

下面具体看一下双方进行保密通信的详细说明:

1.1    第一回合: 确认服务器的身份

客户”->“服务器:你好

服务器”->“客户:你好,我是服务器

客户”->“服务器:????

因为消息是在网络上传输的,有人可以冒充自己是服务器来向客户发送信息。例如上面的消息可以被黑客截获如下:

客户”->“服务器:你好

服务器”->“客户:你好,我是服务器

客户”->“黑客:你好        // 黑客在客户服务器之间的某个路由器上截获客户发给服务器的信息,然后自己冒充服务器

黑客”->“客户:你好,我是服务器

因此客户在接到消息后,并不能肯定这个消息就是由服务器发出的,某些黑客也可以冒充服务器发出这个消息。如何确定信息是由服务器发过来的呢?有一个解决方法,因为只有服务器有私钥,所以只要能够确认对方有私钥,那么对方就是服务器。因此通信过程可以改进为如下:

1.2    第二回合:

客户”->“服务器:你好

服务器”->“客户:你好,我是服务器

客户”->“服务器:向我证明你就是服务器

服务器”->“客户:你好,我是服务器 {你好,我是服务器}[私钥|RSA]

注意:这里约定一下,{} 表示RSA加密后的内容,[ | ]表示用什么密钥和算法进行加密,后面的示例中都用这种表示方式,例如上面的 {你好,我是服务器}[私钥|RSA]  就表示用私钥你好,我是服务器进行加密后的结果。

为了向客户证明自己是服务器服务器把一个字符串用自己的私钥加密,把明文和加密后的密文一起发给客户。对于这里的例子来说,就是把字符串 你好,我是服务器和这个字符串用私钥加密后的内容 {你好,我是服务器}[私钥|RSA] 发给客户。

客户收到信息后,她用自己持有的公钥解密密文,和明文进行对比,如果一致,说明信息的确是由服务器发过来的。也就是说客户 {你好,我是服务器}[私钥|RSA]这个内容用公钥进行解密,然后和你好,我是服务器对比。因为由服务器私钥加密后的内容,又且只能由公钥进行解密,私钥只有服务器持有,所以如果解密出来的内容是能够对得上的,那说明信息一定是从服务器发过来的。

假设黑客想冒充服务器

黑客”->“客户:你好,我是服务器

客户”->“黑客:向我证明你就是服务器

黑客”->“客户:你好,我是服务器 {你好,我是服务器}[???|RSA]    //这里黑客无法冒充,因为他不知道私钥,无法用私钥加密某个字符串后发送给客户去验证。

客户”->“黑客:????

由于黑客没有服务器私钥,因此它发送过去的内容,客户是无法通过服务器的公钥解密的,因此可以认定对方是个冒牌货!

到这里为止,客户就可以确认服务器的身份了,可以放心和服务器进行通信,但是这里有一个问题,通信的内容在网络上还是无法保密。为什么无法保密呢?通信过程不是可以用公钥私钥加密吗?其实用RSA私钥公钥是不行的,我们来具体分析下过程,看下面的演示:

1.3    第三回合:

客户”->“服务器:你好

服务器”->“客户:你好,我是服务器

客户”->“服务器:向我证明你就是服务器

服务器”->“客户:你好,我是服务器 {你好,我是服务器}[私钥|RSA]

客户”->“服务器{我的帐号是aaa,密码是123,把我的余额的信息发给我看看}[公钥|RSA]

服务器”->“客户{你的余额是100}[私钥|RSA]

注意上面的的信息 {你的余额是100}[私钥]这个是服务器私钥加密后的内容,但是我们之前说了,公钥是发布出去的,因此所有的人都知道公钥,所以除了客户,其它的人也可以用公钥{你的余额是100}[私钥]进行解密。所以如果服务器私钥加密发给客户,这个信息是无法保密的,因为只要有公钥就可以解密这内容。然而服务器也不能用公钥对发送的内容进行加密,因为客户没有私钥,发送个客户也解密不了。

这样问题就又来了,那又如何解决呢?在实际的应用过程,一般是通过引入对称加密来解决这个问题,看下面的演示:

1.4    第四回合: 确保信息不被获取

客户”->“服务器:你好

服务器”->“客户:你好,我是服务器

客户”->“服务器:向我证明你就是服务器

服务器”->“客户:你好,我是服务器 {你好,我是服务器}[私钥|RSA]

客户”->“服务器{我们后面的通信过程,用对称加密来进行,这里是对称加密算法密钥}[公钥|RSA]    //蓝色字体的部分是对称加密的算法和密钥的具体内容,客户把它们发送给服务器。

服务器”->“客户{OK,收到!}[密钥|对称加密算法]

客户”->“服务器{我的帐号是aaa,密码是123,把我的余额的信息发给我看看}[密钥|对称加密算法]

服务器”->“客户{你的余额是100}[密钥|对称加密算法]

在上面的通信过程中,客户在确认了服务器的身份后,客户自己选择一个对称加密算法和一个密钥,把这个对称加密算法密钥一起用公钥加密后发送给服务器。注意,由于对称加密算法密钥是用公钥加密的,就算这个加密后的内容被黑客截获了,由于没有私钥黑客也无从知道对称加密算法密钥的内容。

由于是用公钥加密的,只有私钥能够解密,这样就可以保证只有服务器可以知道对称加密算法密钥,而其它人不可能知道(这个对称加密算法密钥客户自己选择的,所以客户自己当然知道如何解密加密)。这样服务器客户就可以用对称加密算法密钥来加密通信的内容了。

总结一下,RSA加密算法在这个通信过程中所起到的作用主要有两个:

  • 因为私钥只有服务器拥有,因此客户可以通过判断对方是否有私钥来判断对方是否是服务器
  • 客户端通过RSA的掩护,安全的和服务器商量好一个对称加密算法密钥来保证后面通信过程内容的安全。

如果这里您理解了为什么不用RSA去加密通信过程,而是要再确定一个对称加密算法来保证通信过程的安全,那么就说明前面的内容您已经理解了。

到这里,客户就可以确认服务器的身份,并且双方的通信内容可以进行加密,其他人就算截获了通信内容,也无法解密。的确,好像通信的过程是比较安全了。

但是这里还留有一个问题,在最开始我们就说过,服务器要对外发布公钥,那服务器如何把公钥发送给客户呢?我们第一反应可能会想到以下的两个方法:

a)公钥放到互联网的某个地方的一个下载地址,事先给客户去下载。

b)每次和客户开始通信时,服务器公钥发给客户

但是这个两个方法都有一定的问题,

对于a)方法,客户无法确定这个下载地址是不是服务器发布的,你凭什么就相信这个地址下载的东西就是服务器发布的而不是别人伪造的呢,万一下载到一个假的怎么办?另外要所有的客户都在通信前事先去下载公钥也很不现实。

对于b)方法,也有问题,因为任何人都可以自己生成一对公钥私钥,他只要向客户发送他自己的私钥就可以冒充服务器了。示意如下:

客户”->“黑客:你好           //黑客截获客户发给服务器的消息

黑客”->“客户:你好,我是服务器,这个是我的公钥    //黑客自己生成一对公钥私钥,把公钥发给客户,自己保留私钥

客户”->“黑客:向我证明你就是服务器

黑客”->“客户:你好,我是服务器 {你好,我是服务器}[黑客自己的私钥|RSA]      //客户收到黑客私钥加密的信息后,是可以用黑客发给自己的公钥解密的,从而会误认为黑客服务器

因此黑客只需要自己生成一对公钥私钥,然后把公钥发送给客户,自己保留私钥,这样由于客户可以用黑客的公钥解密黑客的私钥加密的内容,客户就会相信黑客服务器,从而导致了安全问题。这里问题的根源就在于,大家都可以生成公钥私钥对,无法确认公钥对到底是谁的如果能够确定公钥到底是谁的,就不会有这个问题了。例如,如果收到黑客冒充服务器发过来的公钥,经过某种检查,如果能够发现这个公钥不是服务器的就好了。

为了解决这个问题,数字证书出现了,它可以解决我们上面的问题。先大概看下什么是数字证书,一个证书包含下面的具体内容:

  • 证书的发布机构
  • 证书的有效期
  • 公钥
  • 证书所有者(Subject
  • 签名所使用的算法
  • 指纹以及指纹算法

证书的内容的详细解释会在后面详细解释,这里先只需要搞清楚一点,数字证书可以保证数字证书里的公钥确实是这个证书的所有者(Subject)的,或者证书可以用来确认对方的身份。也就是说,我们拿到一个数字证书,我们可以判断出这个数字证书到底是谁的。现在把前面的通信过程使用数字证书修改为如下:

1.5    第五回合:

客户”->“服务器:你好

服务器”->“客户:你好,我是服务器,这里是我的数字证书        //这里用证书代替了公钥

客户”->“服务器:向我证明你就是服务器

服务器”->“客户:你好,我是服务器 {你好,我是服务器}[私钥|RSA]

注意,上面第二次通信,服务器把自己的证书发给了客户,而不是发送公钥客户可以根据证书校验这个证书到底是不是服务器的,也就是能校验这个证书的所有者是不是服务器,从而确认这个证书中的公钥的确是服务器的。后面的过程和以前是一样,客户服务器证明自己的身份,服务器私钥加密一段内容连同明文一起发给客户客户把加密内容用数字证书中的公钥解密后和明文对比,如果一致,那么对方就确实是服务器,然后双方协商一个对称加密来保证通信过程的安全。到这里,整个过程就完整了,我们回顾一下:

1.6    完整过程:

step1客户向服务端发送一个通信请求

客户”->“服务器:你好

  step2服务器向客户发送自己的数字证书。证书中有一个公钥用来加密信息,私钥服务器持有

服务器”->“客户:你好,我是服务器,这里是我的数字证书 

step3客户收到服务器的证书后,它会去验证这个数字证书到底是不是服务器的,数字证书有没有什么问题,数字证书如果检查没有问题,就说明数字证书中的公钥确实是服务器的。检查数字证书后,客户会发送一个随机的字符串服务器私钥去加密,服务器把加密的结果返回给客户客户公钥解密这个返回结果,如果解密结果与之前生成的随机字符串一致,那说明对方确实是私钥的持有者,或者说对方确实是服务器

客户”->“服务器:向我证明你就是服务器,这是一个随机字符串     //前面的例子中为了方便解释,用的是你好等内容,实际情况下一般是随机生成的一个字符串。

服务器”->“客户{一个随机字符串}[私钥|RSA]

step4验证服务器的身份后,客户生成一个对称加密算法密钥,用于后面的通信的加密和解密。这个对称加密算法密钥客户会用公钥加密后发送给服务器,别人截获了也没用,因为只有服务器手中有可以解密的私钥。这样,后面服务器客户就都可以用对称加密算法来加密和解密通信内容了。

服务器”->“客户{OK,已经收到你发来的对称加密算法和密钥!有什么可以帮到你的?}[密钥|对称加密算法]

客户”->“服务器{我的帐号是aaa,密码是123,把我的余额的信息发给我看看}[密钥|对称加密算法]

服务器”->“客户{你好,你的余额是100}[密钥|对称加密算法]

1.7其它问题:

上面的过程已经十分接近HTTPS的真实通信过程了,完全可以按照这个过程去理解HTTPS的工作原理。

2       问题及解答

2.1    【问题1

上面的通信过程中说到,在检查完证书后,客户发送一个随机的字符串给服务器去用私钥加密,以便判断对方是否真的持有私钥。但是有一个问题,黑客也可以发送一个字符串给服务器去加密并且得到加密后的内容,这样对于服务器来说是不安全的,因为黑客可以发送一些简单的有规律的字符串给服务器加密,从而寻找加密的规律,有可能威胁到私钥的安全。所以说,服务器随随便便用私钥去加密一个来路不明的字符串并把结果发送给对方是不安全的。

〖解决方法〗

每次收到客户发来的要加密的的字符串时,服务器并不是真正的加密这个字符串本身,而是把这个字符串进行一个hash计算,加密这个字符串的hash(不加密原来的字符串)后发送给客户客户收到后解密这个hash值并自己计算字符串的hash值然后进行对比是否一致。也就是说,服务器不直接加密收到的字符串,而是加密这个字符串的一个hash值,这样就避免了加密那些有规律的字符串,从而降低被破解的机率。客户自己发送的字符串,因此它自己可以计算字符串的hash值,然后再把服务器发送过来的加密的hash值和自己计算的进行对比,同样也能确定对方是否是服务器

2.2    【问题2

在双方的通信过程中,黑客可以截获发送的加密了的内容,虽然他无法解密这个内容,但是他可以捣乱,例如把信息原封不动的发送多次,扰乱通信过程。

〖解决方法〗

可以给通信的内容加上一个序号或者一个随机的值,如果客户或者服务器接收到的信息中有之前出现过的序号或者随机值,那么说明有人在通信过程中重发信息内容进行捣乱,双方会立刻停止通信。有人可能会问,如果有人一直这么捣乱怎么办?那不是无法通信了?答案是的确是这样的,例如有人控制了你连接互联网的路由器,他的确可以针对你。但是一些重要的应用,例如军队或者政府的内部网络,它们都不使用我们平时使用的公网,因此一般人不会破坏到他们的通信。 

2.3    【问题3

在双方的通信过程中,黑客除了简单的重复发送截获的消息之外,还可以修改截获后的密文修改后再发送,因为修改的是密文,虽然不能完全控制消息解密后的内容,但是仍然会破坏解密后的密文。因此发送过程如果黑客对密文进行了修改,客户服务器是无法判断密文是否被修改的。虽然不一定能达到目的,但是黑客可以一直这样碰碰运气。

〖解决方法〗如何确保信息未被修改

在每次发送信息时,先对信息的内容进行一个hash计算得出一个hash值,将信息的内容和这个hash值一起加密后发送。接收方在收到后进行解密得到明文的内容和hash值,然后接收方再自己对收到信息内容做一次hash计算,与收到的hash值进行对比看是否匹配,如果匹配就说明信息在传输过程中没有被修改过。如果不匹配说明中途有人故意对加密数据进行了修改,立刻中断通话过程后做其它处理。

你可能感兴趣的:(java,https,加密通信)