Open meishaoming opened 4 years ago
当我们用浏览器访问一个网页的时候,由于 HTTP 访问的数据是明文的,如果有人在中间修改了网页,我们也发现不了。
有哪些途径可以在「中间」修改网页?
比如,一般我们都是通过路由器上网,如果在路由器要解析到回传给你的是一个 HTML ,那就可以在 HTML 中插入一些数据再返回给你。
我们访问目标网站中间不仅仅经过自己家里的路由器,还经过运营商的很多节点路由才最终能跟服务器交互,那么这中间任何一环都有可能篡改我们的数据。
要解决这个问题,就需要对客户端、服务器两者之间交互的数据进行加密。也就是说,传输的数据只有客户端和服务器看得懂,其它人看不懂。数据一旦被更改就会被发现。
分解一下这里的需求:
发送数据之前先取数据的「摘要」,收到数据的时候以同样的算法也算一遍「摘要」。对比两份摘要就知道数据有没有被篡改。
但仅仅有「摘要」还是不够的。如果有人改完数据、重新算了一份「摘要」呢?所以我们不仅要能识别数据完整,而且还要有能力验证这份数据是不是「我们认为的对方」生成的。
把生成的「摘要」用私钥加密。私钥是非对称加密里的概念,非对称加密的特点是私钥加密只能由公钥解密,公钥加密只能由私钥解密,公钥和私钥是完全不同的。
这样的话,服务端生成一对密钥:私钥+公钥。私钥保存起来,公钥就放到公网上大家都可以拿到。
如果用服务端的公钥成功解密了一串数据,那这串数据肯定是由这个服务器生成的。
对数据生成一个「摘要」,然后服务端用私钥加密这个「摘要」,最后得到的就是对这串数据的「签名」。有了「签名」,就可以验证数据的来源。
我收到了来自服务端的数据,想要服务端用的公钥解密「签名」。问题来了:
如果有个人生成了一对公钥+私钥,把公钥给我并且欺骗我这就是服务端的公钥,然后用它的私钥加 密数据发给我。那我岂不是认为这个数据是来自服务端的?
所以问题是:我从哪里去拿到服务端的公钥?我怎么知道我拿到的就是这个服务端的公钥?
现实生活中是这样解决的:
注意,不是谁都能随随便便用证书中心的私钥去加密自己的公钥,这需要经过一系列申请和付费才行。(letsencrypt 是免费的,但三个月要刷新一下)。
我们要对 HTTP 加密。不仅要确认数据完整性、确认数据来源,还需要对数据本身加密,要让别人看不懂数据的内容。比如我们可能在通过 HTTP 向服务器提交账户、密码等关系信息,明文的肯定不行。
要想对数据本身加密,在客户端和服务器之间就必须先协商好一个密钥,我们叫作 key。这个密钥是对称加密的密钥。如何协商呢?
这就相当于 A 和 B 对话,需要经过 C 来传达,那么 A 和 B 如何协商一个 key 让 C 都不知道呢?
TCP 连接建立之后,HTTPS 的交互过程:
C 能不能知道这个 key ?
不能。因为 client 生成的 pre-master secret 用服务端的公钥加密,只能被服务器的私钥解密。
非常清新明了
一、首先来看我们要解决什么问题?
当我们用浏览器访问一个网页的时候,由于 HTTP 访问的数据是明文的,如果有人在中间修改了网页,我们也发现不了。
有哪些途径可以在「中间」修改网页?
比如,一般我们都是通过路由器上网,如果在路由器要解析到回传给你的是一个 HTML ,那就可以在 HTML 中插入一些数据再返回给你。
我们访问目标网站中间不仅仅经过自己家里的路由器,还经过运营商的很多节点路由才最终能跟服务器交互,那么这中间任何一环都有可能篡改我们的数据。
要解决这个问题,就需要对客户端、服务器两者之间交互的数据进行加密。也就是说,传输的数据只有客户端和服务器看得懂,其它人看不懂。数据一旦被更改就会被发现。
分解一下这里的需求:
二、如何实现数据完整性?
发送数据之前先取数据的「摘要」,收到数据的时候以同样的算法也算一遍「摘要」。对比两份摘要就知道数据有没有被篡改。
但仅仅有「摘要」还是不够的。如果有人改完数据、重新算了一份「摘要」呢?所以我们不仅要能识别数据完整,而且还要有能力验证这份数据是不是「我们认为的对方」生成的。
三、如何确认数据来源?
把生成的「摘要」用私钥加密。私钥是非对称加密里的概念,非对称加密的特点是私钥加密只能由公钥解密,公钥加密只能由私钥解密,公钥和私钥是完全不同的。
这样的话,服务端生成一对密钥:私钥+公钥。私钥保存起来,公钥就放到公网上大家都可以拿到。
如果用服务端的公钥成功解密了一串数据,那这串数据肯定是由这个服务器生成的。
对数据生成一个「摘要」,然后服务端用私钥加密这个「摘要」,最后得到的就是对这串数据的「签名」。有了「签名」,就可以验证数据的来源。
四、从哪里获取公钥?
我收到了来自服务端的数据,想要服务端用的公钥解密「签名」。问题来了:
所以问题是:我从哪里去拿到服务端的公钥?我怎么知道我拿到的就是这个服务端的公钥?
现实生活中是这样解决的:
注意,不是谁都能随随便便用证书中心的私钥去加密自己的公钥,这需要经过一系列申请和付费才行。(letsencrypt 是免费的,但三个月要刷新一下)。
五、HTTPS
我们要对 HTTP 加密。不仅要确认数据完整性、确认数据来源,还需要对数据本身加密,要让别人看不懂数据的内容。比如我们可能在通过 HTTP 向服务器提交账户、密码等关系信息,明文的肯定不行。
要想对数据本身加密,在客户端和服务器之间就必须先协商好一个密钥,我们叫作 key。这个密钥是对称加密的密钥。如何协商呢?
这就相当于 A 和 B 对话,需要经过 C 来传达,那么 A 和 B 如何协商一个 key 让 C 都不知道呢?
TCP 连接建立之后,HTTPS 的交互过程:
C 能不能知道这个 key ?
不能。因为 client 生成的 pre-master secret 用服务端的公钥加密,只能被服务器的私钥解密。
参考: