上一篇记录了一下HTTP协议以及基于UDP协议实现的可靠传输协议QUIC协议。
众所周知,HTTP协议是直接进行明文传输的,交互过程以及数据传输都没有进行加密,通信双方也没有进行任何认证,因此通信过程非常容易遭遇劫持、监听、篡改。严重情况下,会造成恶意的流量劫持。
所以在复杂的网络环境中,急需一个传输安全的协议,于是HTTPS协议就产生了。
(1)对称加密
加密解密使用相同的密钥
(2)非对称加密
加解密使用过的密钥不同,一个是公开的公钥,一个是私有的私钥,公钥加密的信息,只要私钥才能解密,私钥加密的信息,只有公钥才能解密。
客户端发送,使用服务端公钥加密,服务端发送,使用客户端公钥加密。
证书由权威机构CA发布,证书里有公钥、证书所有者、证书发布机构和证书有效期。
CA会用一个签名算法给证书签名,用只掌握在权威机构手里的东西签名了才行,这就是CA的私钥。
下图是微信公众号网站的证书:
签名算法:
对信息做一个 Hash 计算,得到一个 Hash 值,这个过程是不可逆的,也就是说无法通过 Hash 值得出原来的信息内容。在把信息发送出去时,把这个 Hash 值加密后,作为一个签名和信息一起发出去
此时请求会得到一个证书,证书有个发布机构CA,只要获取此CA的公钥,去解密证书的签名,解密成功并Hash也对的上,就说明这个公钥没有问题。
请求的时候将证书(证书也是通过CA私钥加密的)发给服务端,服务端获取到相应机构的公钥,用来解密证书,解密后,校验Hash值,如果校验成功,说明公钥没问题,此时就会获取到客户端的公钥。
如何确定CA的公钥就是正确的?
CA 的公钥也需要更牛的 CA 给它签名,然后形成 CA 的证书。
要想知道某个 CA 的证书是否可靠,要看 CA 的上级证书的公钥,能不能解开这个 CA 的签名。
这样层层上去,直到全球皆知的几个著名大 CA,称为 root CA,做最后的背书。
通过这种层层授信背书的方式,从而保证了非对称加密模式的正常运转。
https 通信分为四个步骤:
此时,客户端有第一步自己生成的随机数,第二步收到服务端的随机数,第三步的 pre-master-key,服务端也是如此,他们就可以用这三个随机数使用约定的算法生成同一个密钥来加密以后的通信数据了。
有了加密和解密,黑客截获了包也打不开了,但是它可以发送 N 次。
这个往往通过 Timestamp 和 Nonce 随机数联合起来,然后做一个不可逆的签名来保证。
Nonce 随机数保证唯一,或者 Timestamp 和 Nonce 合起来保证唯一,同样的,请求只接受一次,于是服务器多次收到相同的 Timestamp 和 Nonce,则视为无效即可。
如果有人想篡改 Timestamp 和 Nonce,还有签名保证不可篡改性,如果改了用签名算法解出来,就对不上了,可以丢弃了。
Nonce是由服务器生成的一个随机数,在客户端第一次请求页面时将其发回客户端;客户端拿到这个Nonce,将其与用户密码串联在一起并进行非可逆加密(MD5、SHA1等等),然后将这个加密后的字符串和用户名、Nonce、加密算法名称一起发回服务器;服务器使用接收到的用户名到数据库搜索密码,然后跟客户端使用同样的算法对其进行加密,接着将其与客户端提交上来的加密字符串进行比较,如果两个字符串一致就表示用户身份有效。这样就解决了用户密码明文被窃取的问题,攻击者就算知道了算法名和nonce也无法解密出密码。
每个nonce只能供一个用户使用一次,这样就可以防止攻击者使用重放攻击,因为该Http报文已经无效。可选的实现方式是把每一次请求的Nonce保存到数据库,客户端再一次提交请求时将请求头中得Nonce与数据库中得数据作比较,如果已存在该Nonce,则证明该请求有可能是恶意的。然而这种解决方案也有个问题,很有可能在两次正常的资源请求中,产生的随机数是一样的,这样就造成正常的请求也被当成了攻击,随着数据库中保存的随机数不断增多,这个问题就会变得很明显。所以,还需要加上另外一个参数Timestamp(时间戳)。
Timestamp是根据服务器当前时间生成的一个字符串,与nonce放在一起,可以表示服务器在某个时间点生成的随机数。这样就算生成的随机数相同,但因为它们生成的时间点不一样,所以也算有效的随机数