网络时代,我们的所有通信都会经过网络进行传输,一个最简单的传输过程为:
A --> B
(A对B说,B你好)
A <-- B
(B回复A,A你也好啊)
这个简单的传输会途径互联网中的各种硬件设备,传输的过程是难以控制的,传输的内容也很容易在某个环节被窃听和篡改。
假设C是一个怀有恶意的中间人,在现实中,C可能是运行于某个路由器的恶意程序,那么,A发送给B的信息在途径C的路由器时,会被C窃听,也可能被C篡改:
A --> C --> B
(A对B说,B你好,在B收到消息前,C先收到消息,将内容篡改为“B你真是个傻瓜”后,再发给B,这样A发送的原文就被篡改了,篡改后的内容,其实并不是A想发送给B的)
为了防止被C窃听和篡改我们的通信,需要引入加密层,也就是我们马上要开始讨论的HTTPS!
在讨论HTTPS前,必须要了解两种加密算法,AES和RSA。
对称加密就像是把信息装进一个盒子,然后加上一把锁,这把锁就是密钥,只有知道这把密钥,才能将加密后的内容解密得到原文。对称加密具体算法有很多种,比较常用的是AES,我们用AES来举例。
你好 -- AES加密 --> C4HU/E5dCxuF/hc7sflZWg
(我们使用密钥k4ybj对原文“你好”进行了加密)
C4HU/E5dCxuF/hc7sflZWg -- AES解密 --> 你好
(我们使用密钥k4ybj对加密内容进行了解密)
如果没有k4ybj这把密钥的话,C4HU/E5dCxuF/hc7sflZWg这堆加密内容表达的信息我们是不知道的。
非对称加密算法是许多计算机应用的基石,其数学支撑是欧拉定理,具体算法比较复杂,这里只简单介绍这种算法的用法。非对称加密的基本用法为:
你好 -- Private加密 --> lF9iopuOoG09PgLBl
lF9iopuOoG09PgLBl -- Public解密 --> 你好
你也好啊 -- Public加密 --> 8PixXpUwpPf9XTJ5nhF9tQ
8PixXpUwpPf9XTJ5nhF9tQ -- Private解密 --> 你也好啊
在了解了AES和RSA后,我们可以将通信的内容进行加密了。
我们使用AES来通信,一个最简单的请求为:
发送方A: 你好 -- AES加密 --> C4HU/E5dCxuF/hc7sflZWg
(使用密钥k4ybj对原文“你好”进行了加密)
接收方B: C4HU/E5dCxuF/hc7sflZWg -- AES解密 --> 你好
(使用密钥k4ybj对加密内容进行了解密)
这下在网络中传输的内容,不再是明文,而是“C4HU/E5dCxuF/hc7sflZWg”这一串加密后的内容,如果C不知道密钥k4ybj的话,我们的传输就安全了(C无法窃听到内容,如果篡改内容,B用密钥k4ybj解密也不对)
这种方式通信的问题就在于,密钥k4ybj如果被C知道了,那么整个传输过程也就不再安全了。在AES加密传输过程建立前,常常先需要告知对方AES密钥,此时的传输是明文的,C在这一步就可能先窃听到了密钥,如果C已得到密钥,那么后续的加密也就不再安全。
HTTPS安全连接一旦建立,其具体的传输过程其实就是如上所说对称加密的,关键点变成了如何将密钥k4ybj保密的发给对方。也就是安全连接的建立。这下轮到RSA登场了。
为了让C无法窃听到AES密钥k4ybj,我们使用RSA算法来加密传输这把很关键的密钥。
首先,A和B都使用RSA算法生成自己的密钥对,共有4把:
Public钥匙都公开,Private自己保管好不对外公布。
加密传输密钥的完整过程如下:
仔细观察整个过程,即使C一直在窃听整个通信过程,由于不知道A-Private,所以C是无法得到密钥k4ybj的。那么,我们的传输就肯定安全了吗?
并不是!下面我们来聊聊中间人的篡改攻击。
中间人一旦有篡改消息内容的能力,那么在前面所讲加密传输密钥过程的第2步,可恶的中间人就可以将B-Public替换成它自己的C-Public,将C-Public返回给A,而A以为这是B-Public,用其加密后的内容,C可以用C-Private解密获得,此时C再把C-Public给B,此后A和B拿到的都是C-Public,而双方都以为拿到的是对方的Public。与此同时,C由于拿到了A和B的Public,自己能够用C-Private解密A和B用C-Public加密的内容,所以C达成了通信过程的窃听和篡改。(绕晕了吗?)
中间人之所以能够攻击,是因为我们无法得知B返回的B-Public是否确实是B的没有被篡改或替换。在使用许多应用了不对称加密的应用时,例如ssh,第一次建立连接时,会显示一个密钥的指纹,即B-Public的指纹,问我们是否信任该公钥确实是B的B-Public。如果我们回答yes,就表示信任这个就是B的B-Public了。
如何才能保证B-Public正确且没被篡改呢?下一步,我们引入第三方来解决这个中间人的问题。
CA要达到的目标,是对B的公钥B-Public进行验证,保证B-Public确实是B的公钥。CA通过颁发证书来达成这个目标。
如何证明B-Public确实是B的公钥呢?有点像证明你妈是你妈,然而我们确实是有办法的。
CA自己有一对钥匙,CA-Private和CA-Public。
要证明B自己的B-Public确实是自己的,B首先去CA申请一种叫做证书的东西。这个证书是一段由CA根据特定算法生成的信息,其包含很多东西,其中有:
B拿到CA颁发的证书后,当A希望和B通信时,B不是返回给A自己的B-Public,而是把证书给A。
CA的信息是公开的,由各大浏览器和操作系统维护。A拿到B的证书后,根据证书的CA信息取出对应CA的CA-Public,用CA-Public解密出B-Public和证书Hash(签名),A自己用相同逻辑对证书进行Hash,如果和解密出的证书Hash(签名)一致,代表证书有效,此时用CA-Public解密得到的B-Public得证确实是B的。
中间人如果替换证书呢?假设中间人偷偷替换了B的证书发给A,A用CA-Public解密的时候,是无法通过的,除非C能知道CA-Private。
至此,整个安全传输过程结束了,HTTPS具体的实现和本例并不一样,但基本原理大致如上所述。