在上一章【网络编程】应用层协议——HTTP协议讲过HTTP可以使用GET和POST方法发送请求,POST能保证私密性,但是都不能保证安全,因为HTTP协议内容都是按照文本的方式明⽂进行传输,这就导致在传输过程中信息被轻易窃取、篡改。
https协议属于应用层协议之一,是在http协议的基础上引入了⼀个加密层。发送和接收必须用同一种方式(HTTP或者HTTPS)区分就用端口号。
由于经过加密层,所以在网络中是密文发送,在应用层是明文的。保证了数据在网络中的安全。
比方说有a 和 key,现在要对a加密,那么我们就让它们异或得到密文:b = a^key,当我嫩想要把密文解密的时候,再异或一次key即可:a ^ key ^ key = a。
这里我们把a叫做原始数据,b叫做密文,key叫做密钥。
加密就是把明文(要传输的信息)进行一系列变换, 生成密文;解密就是把密文再进行一系列变换, 还原成明文。
我们在下载东西的时候会出现这样的情况:我们明明要下载的是a软件,但是实际下载下来的却是b软件。
为什么会出现这种情况呢?
因为http的内容是明文传输的,而且要进过多个节点,如果信息在传输过程中被劫持,传输的内容就完全暴露了。劫持者还可以篡改传输的信息且不被对方察觉,这就是中间人攻击 ,所以我们才需要对信息进行加密。
采用单钥密码系统的加密方法,同一个密钥可以同时用作信息的加密和解密,这种加密方法称为对称加密,也称为单密钥加密,特征:加密和解密所用的密钥是相同的。
特点:算法公开、计算量小、加密速度快、加密效率高
按位异或就是一个简单的对称加密,不过HTTPS 中并不是使用按位异或。
需要两个密钥来进行加密和解密,这两个密钥是公开密钥(公钥)和私有密钥(私钥)。
特点:算法强度复杂、安全性依赖于算法与密钥但是由于其算法复杂,而使得加密解密速度慢。 公钥和私钥是配对的,公钥可以认为是一把锁,私钥是锁的钥匙,锁给谁都行,但是只有持有私钥的人才能打开。
通过公钥对明文加密, 变成密文;通过私钥对密⽂解密, 变成明文
当然也可以反着用:
通过私钥对明文加密, 变成密文;通过公钥对密⽂解密, 变成明文
对称加密的速度快、非对称加密的速度慢
不存在不可被破解的加密,我们可以从算力成本角度来分析:比如我们加密的成本是100块,而解密的花费却要100亿,这种我们就可以称为是安全的。
现在有一篇很大的文章,我们可以通过哈希函数把这个文章处理成一个固定长度字符串,现在就选修改了一个标点符号,字符串也会变化。我们把这个固定长度的字符串就叫做hash摘要。
而这个过程就叫做数据摘要。
其基本原理是利⽤单向散列函数(Hash函数)对信息进行运算生成⼀串固定长度的数字摘要。数字指纹并不是一种加密机制,但可以用来判断数据有没有被窜改,如果对数据某个地方进行小小的改动,重新生成的哈希摘要也和改动前的大不一样。
摘要特征:和加密算法的区别是,摘要严格意义不是加密,因为没有解密,只不过从摘要很难反推原信息(hash是不可逆的),通常用来进行前后数据的对比,观察数据是否被修改过,也可以用于实现网盘的秒传功能、公司数据库密码存储等。
网盘秒传功能:
比方说我们很多人都想保存同一个电影到网盘中,如果网盘把每个人的请求全部保存起来, 那么会浪费很多空间。其实我们只用保存一份,形成hash摘要,当另一个用户也要保存同一部电影时,要先形成摘要,然后在网盘中的一大堆摘要中进行对比,如果有这个摘要,那么直接建立映射关系即可,不需要再保存。
数据密码存储同理,把密码形成摘要,因为涉及到密码的东西都要进行加密。
每次用户登录时都将转换成哈希摘要与数据库的哈希摘要进行对比,所以数据库泄露也不怕。
因为摘要是把无限变有限,所以可能存在碰撞,但是概率极低,就像指纹一样。
可能摘要的信息也不想让别人看到,我们把对数据摘要再加密形成的数据叫做数据签名。
网络通信中,需要解决两个问题:
1️⃣ 数据被监听2️⃣ 数据被篡改
先来看几种手段:
如果通信双方只使用一个密钥进行加密通信,那么完全可以实现加密通信,除非密钥被破解。但是一台服务器将来可能会面对多个客户端,每个客户端的密钥肯定得不一样,如果只使用对称加密,那么服务器就不知道每一台客户端的密钥是啥(除非建立映射关系),还有一个问题:密钥也要先传递过去,那么密钥又怎么传递呢?加密?就变成了死循环无解问题,不加密?会被黑客拿到。
所以在进行正常加密数据通信之前,首先要解决的是密钥如何被对方安全的收到?
非对称加密既可以使用公钥加密,也可以使用私钥加密。但是使用公钥加密必须使用私钥解密,使用私钥加密必须使用公钥解密。
这样就算中间人在通信过程中获取了公钥,但是没有私钥也无法进行解密。由此保证了从客户端发送给服务端数据的安全。 但是客户端给服务器发送的消息是不安全的。因为使用公钥加密的密文发给客户端,客户端没有私钥,解不了密;那响应的时候把私钥用传过去行不行?不行的,因为私钥一但暴露到公网中,就可能被劫持,黑客拿到私钥原地破解密文。
既然一方使用非对称加密可以保证一个方向通信的安全性,那么两方都使用非对称加密不就可以实现互相的通信安全了吗。
具体实现:
客户端形成公钥C和私钥C’,服务端形成公钥S和私钥S’
1️⃣ 客户端把公钥C推送给服务端
2️⃣ 服务端把公钥S推送给客户端
然后按照一方非对称的流程就完成了双方的通信。
这里有两个问题:首先是速度慢,其次是也有安全问题。
首先解决速度慢的问题:
使用非对称加密使双方知道对称密钥,后续再使用对称加密的方式进行通信。
只有首次使用了非对称加密,后续所有的通信都将采用对称加密,对称加密的速度快,大大提高了通信速度。
上面这两种为什么有安全问题呢?
公钥交换完了确实能保证安全,但是如果在交换公钥的时候就出现了问题呢?
这样以后中间人也得到了C,利用C先解密再加密后发送给服务端,那么即使修改了数据客户端和服务端也不知道中间人的存在。
该场景的本质问题是服务器在返回公钥的时候,被中间人截取并替换了公钥,并且客户端没有能力辨别公钥是否合法。 所以需要客户端具有判别公钥是否合法的能力。
服务端在使用HTTPS前,需要向CA机构申领⼀份数字证书,数字证书里含有证书申请者信息、公钥信息等。客户端向服务器请求公钥时,服务器把证书传输给浏览器,浏览器从证书里获取公钥就行了,证书就如身份证,是服务端公钥的身份证明。
证书可以理解成一个结构化的字符串,客户端接收服务端的数据里不仅仅有公钥,是证书里包含了公钥要发送过去,只有证书是合法的时候才会进行非对称加密。
申请证书的时候,需要在特定平台生成CSR文件,同时生成公钥和私钥。这对密钥就是用来在网络通信中进行明文加密以及数字签名时使用的。其中公钥会随着CSR文件,一起发给CA进行权威认证,私钥服务端自己保留,后续用于通信使用(主要就是用来交换对称密钥)。
从上图也可以看到证书包含了数据签名和明文信息。
比方说现在我们有了数据(比如明文信息),我们把这个数据进行摘要形成数据摘要(数据指纹),然后把数据指纹用签名者(比如CA机构)的私钥进行加密形成了签名,然后再把明文信息和签名放在一起形成了数字签名的数据(比如证书)。
首先把数据签名的数据分成数据和签名,然后先对数据进行相同的摘要方式形成数据摘要,然后把用公钥加密过的签名用私钥解密,得到数据摘要,两者比对即可。散列值不一样说明有人篡改了签名或者数据,一样说明没有被篡改过。
数据签名的本质是为了防止被篡改。
我们把这个过程类比到证书上:
当服务端申请CA证书的时候,CA机构会对该服务端进行审核,并专门为该网站形成数字签名,过程如下:
1️⃣ CA机构拥有非对称加密的私钥A和公钥A’。
2️⃣ CA机构对服务端申请证书的明文数据进行hash摘要(公开的),形成数据摘要。
3️⃣ CA机构用自己的私钥A加密数据摘要形成数据签名。
4️⃣ CA机构把明文数据和签名结合起来形成证书。
因为我们使用的是CA形成的数据签名,所以只有CA能形成可信任的证书。
此时服务器会把证书响应给客户端,证书里面包含了公钥。
1️⃣ 先看过没过期。
2️⃣ 把数据签名和明文信息分开。
3️⃣ 对明文信息进行hash摘要(公开的),形成数据摘要。然后用CA的公钥把数据签名解密,得到了数据摘要,这里的公钥是哪来的呢?(CA会在所有的浏览器中内置自己的公钥)
4️⃣ 把两个数据摘要进行对比,相等就说明内容没有被篡改,不相等说明被篡改了。
那么有没有可能原文和签名全部都被替换了呢?
原文中的公钥确实能被修改,那么签名呢?改不了,因为私钥只有CA有,用自己的私钥的话浏览器不认识。
中间人能不能直接把整个证书替换掉?
首先因为浏览器里面内置了CA的私钥,那么我们替换的证书必须是一个真正的证书,因为假证书没有办法解密。而证书里面的域名信息,域名是唯一的,不可能一样。所以做不到整体替换。
在客户端和服务器刚一建立连接的时候, 服务器给客户端返回数字证书,证书明文包含了服务端的公钥, 也包含了网站的身份信息等。由此验证了公钥的合法性。
所以非对称加密+对称加密保证了通信的安全,数字证书保证了通信之前交换密钥的安全。
HTTPS整个工作过程中涉及的密钥有三组:
第⼀组(非对称加密): CA机构给的非对称密钥对,用于校验证书是否被篡改。
服务器持有私钥(私钥在形成CSR文件与申请证书时获得), 客户端持有公钥(操作系统包含了可信任的 CA 认证机构有哪些, 同时持有对应的公钥)。
第⼆组(非对称加密): 服务端生成的非对称密钥对,用于生成对称加密的密钥。
第三组(对称加密): 客户端生成的对称密钥,客户端和服务器后续通信都通过这个对称密钥进行加密解密。