一、概念回顾
A <------M------> B
场景:A、B两个人之间通讯,A传输信息M给B,假定是在不安全的通路上传输。
1.明文传输
被中间人C拦截下来,可以随意篡改A发送给B的消息,且可以冒名顶替A直接与B通信。
2.对称加密
加密和解密为同一秘钥。
除非A和B面对面,找个小角落窃窃私语约定秘钥,况且在现实生活中,躲在小房子里面的小声说话,也有可能被别人听见,隔墙有耳大家应该都听过吧。
因为是网络传输,秘钥需要在网络上传输给对方,在不安全的信道上倘若被C截获到对称秘钥,那么仍然会出现数据被中间人篡改和冒名顶替的问题。
3.非对称加密
A生成公钥和私钥,私钥是自己用的保留在本地不再在网络上进行传输,公钥是分发给其他人用的,随便传输给其他人(一般是下发的证书中包含公钥然后返回给请求者),因为公钥私钥是一对,私钥加密的只有公钥才能够解密,若能成功解密(则证明跟你交互的那个人是当初给你公钥的那个人)。
A给B发消息,用A的私钥加密,B收到之后用A的公钥解密;同理B给A发消息,用B自身的私钥加密,A收到后用B颁发的私钥解密,解密成功即可证明发消息的人是当初给你公钥的人。即A、B要使用非对称加密方式进行通讯的话,需要各自保留对方的公钥。
但是客户端和服务器交互,则是服务端一个私钥,而大量客户端用公钥跟他交互。
非对称加密:保证了发消息的人就是当时给你公钥的人。
问题一:中间人C截获到A发给B的加密信息,即便C有A的公钥使得他可以解密看到明文,但是他没有A的私钥所以伪造不了A的身份,但是他可以搞破坏,直接在密文的基础上乱改,然后在发给B。B这时候收到用公钥解密得到的结果肯定和A发给他的不一样,但是他没有办法确认数据是被别人篡改过的,还是A发给他的本身就是有问题的。
如何保证数据在传输过程中是否有被篡改过?
利用数字签名技术,即首先将原文进行哈希运算(不可逆)生成固定长度的数字摘要,(一定要理解摘要的含义,摘要是对总体的一个概括,比如原文件太过于庞大,有上百兆的大小,这时候如果直接对此进行私钥加密那么代价太大,也就是说只要你对原文进行签名,且附带了原文,这样能够让接受者验证原始数据是否被篡改,这就完成了数字签名的任务),只不过全文加密代价太大,我们可以使用对原文的缩略版——摘要进行加密即可达到同样的目的,接收者B收到信息后,首先拿A的公钥解密数字签名得到原始摘要,再对传过来原文进行摘要,二者对比,如果一致则说明数据没有被篡改过。
问题二:公钥解密成功只能说明发消息的人是当初给你公钥的人,但是那个人是A吗?是B吗?还是中间人C呢?归根结底还是上面的问题,除了现实生活中手对手把公钥给你(如果他会易容术呢,冒名顶替也不是不可能)如C跑到B的电脑上将A的公钥替换为C自己的公钥,在不可靠的网络环境下,更有可能出现这个问题,C冒充A说我是A这是我的公钥,你拿去然后和我通信,B不知道给他公钥的这个号称是A的人,到底是不是A。
如何保证发布公钥的A,不是他人冒名顶替的呢?
找一个受信任的机构"证书中心"(certificate authority,简称CA)做认证,证书中心用自己的私钥给(A的公钥+申请者A的信息等)加密,生成数字证书。当下次A给B发消息的时候A会带上CA签发的数字证书,B收到后用CA的公钥解密证书,解密成功则证明这个的确是CA签发的有效证书,而不是不知名的野鸡机构,从而拿到了里面的A的公钥,证明了A就是CA机构认证过的A,这个的的确确就是A的公钥,错了就找CA机构买单,假一赔十。然后拿A的公钥,去解密数字签名得到摘要,在对原文进行摘要算法之后和这个摘要进行对比,一致则说明没有被篡改。
重申的概念
- 非对称加密和数字摘要、数字签名完全是两个不同维度的概念。
- 非对称加密只是一种利用公钥和私钥进行加密一种方式。
- 摘要:对于不定长的数据(这个数据一般很大)进行Hash(如MD5摘要算法)形成固定长度的输出,这个输出的结果叫做摘要。
- 数字签名:利用自己的私钥对上面生成的摘要进行加密,加密生成的结果被叫做数字签名。
- 上面是狭义上的数字签名(摘要被私钥签出来的加密后的信息叫做数字签名)
- 广义上的数字签名指的是非对称加密的一种实际使用用途,即利用非对称加密和哈希算法来保证数据在传输过程中不被篡改。
- 既然是加密,那肯定是不希望别人知道我的消息,所以只有我才能解密,所以可得出公钥负责加密,私钥负责解密;同理,既然是签名,那肯定是不希望有人冒充我发消息,只有我才能发布这个签名,所以可得出私钥负责签名,公钥负责验证
非对称加密的主要用途就是:密钥交换和数字签名。
数字签名的作用主要是:确保发送的报文没有被篡改。
非对称加密主要应用在秘钥协商阶段 !协商好秘钥之后的通信就用对称加密了 !
Https秘钥交换过程
- 客户端要访问一个网站,向支持https的服务器发起请求。
- 客户端向服务器发送自己支持的秘钥交换算法列表。
- 服务器选取一种秘钥交换算法加上CA证书返回给客户端。
- 客户端验证服务器是否合法,并生成一个随机数然后用协商好的加密算法加密生成随机秘钥,并用刚才从CA证书中拿到的公钥对其加密后发送给服务器。
- 服务器收到后用自己的私钥解密(中间人没有服务器的私钥,所以没有办法看到传输的数据,另外确认秘钥交换算法是在第一步,中间人是不知道秘钥交换算法(中间人是无法在第一步做手脚的,那等同于它自己就是一个真实客户端发起了一个新的请求,唯一一种情况攻击人有一个合法CA下发的证书,且客户端(一般为安卓设备)没有对CA下发的证书中的内容网站地址和当前请求地址做对比校验),就算攻击者有公钥,因为不知道协商协议,所以做不出来随机秘钥,顶多就是在传输过程中将报文拦截下来,乱改,但是给到服务器后,私钥是解不开乱改之后的密文的)
- 服务器私钥解密之后,拿到对称秘钥,并且用它再加密一个信息,返回给浏览器。
最关键的一步就是在客户端采用 RSA 或 Diffie-Hellman 等加密算法生成 Pre-master,这个随机秘钥是用来计算最终的对称秘钥的,用公钥加密之后攻击人是不知道这个这个随机秘钥的,只有服务器才能解的开。
Https有可能会有中间人攻击,当然浏览器自身会对CA证书做校验,但是如果自己开发的过程中,尤其是在安卓客户端,只是验证证书是否是由CA签出来的,这个时候如果中间人也有一个从CA签出来的证书,而恰好客户端又没有做校验,那么就会被冒名顶替。
而且要明确中间人攻击的目的是什么?是为了获得某些利益,不可能只在中间环节捣乱,而获取不到任何有价值的信息,那么他是没有必要这么做的。