Contents

HTTPS 笔记

基本概念

对称加密

加密和解密用的是同一个密钥。

非对称加密

加密和解密需要用到一对不同的密钥 A 和 B,其中可以被公开的称为公钥,不公开的称为私钥,用 A 加密的则必须由 B 来解密,反之亦然。

中间人攻击

客户端和服务端之间传输的消息被一个「中间人」截获,中间人冒充二者与对方交换信息而二者毫不知情。

散列

通过某种算法将,将任何一组任意长度的数据都转换成一个固定( 多半如此)长度的散列值。可用于签名认证,来检查某段信息是否被修改。比如已知信息 A,按某种散列算法 M 散列后得到 α,即 M(A)=α,现得到信息 B 和 α,如果 M(B)=α 也成立,那么依赖这种散列算法 M 自身的特性,理论上我们就认为 A=B,即得到的信息与原始信息一致,在传输过程中没有被篡改。

HTTP 传输的不足之处

明文传输,容易被攻击。

HTTP 避免明文传输的解决方法

对传输的信息进行对称加密

首先客户端先向服务端请求密钥,服务端将密钥明文传输给客户端,以后二者发送信息前均用密钥加密,收到信息后均用密钥解密。看起来像是解决了明文传输的问题,但密钥本身就是用明文传输的,无法防止泄露,只要密钥泄露,加密等于没加密。

对传输的信息进行单向非对称加密

服务端生成一对密钥,将公钥明文传给客户端,客户端向服务端发送、接受信息时,使用公钥加、解密,服务端像客户端发送、接受消息时,使用私钥加、解密。这样一来,即便公钥泄露,也只有服务端发送的消息加密失效。因为私钥始终在服务端,得不到私钥,客户端发送给服务端的消息无法被解密。

对传输的信息进行双向非对称加密

客户端也生成一对公、私钥,将公钥发送给服务端,服务端用客户端的公钥加密,客户端用服务端的公钥加密,然后用各自的私钥解密,这样一来,即便传输过程中两个公钥都泄露,只要本地的私钥不泄露,双方交流的信息就不会泄露。

单向非对称加密 + 对称加密

虽然上面双向非对称加密的方法可以解决明文传输的问题,但是需要两对非对称密钥,未免有点繁琐,而且非对称加密所花费的时间也不可小觑。这样的话,我们是不是可以利用单向非对称加密「起码可以保证客户端使用服务端公钥加密之后发送给服务端的信息无法被解密」的这个特点做点什么?是的,可以通过公钥加密一个对称密钥发送给服务端,后续彼此的信息交流都用这个密钥进行加、解密,这样一来只需要服务端的一对非对称密钥和客户端生成一个对称秘钥即可解决明文传输的问题,显然会比双向非对称加密来的有效率。

但是「单向非对称加密 + 对称加密」也只是解决了避免明文传输的问题,都还没有考虑如果客户端收到的公钥压根儿就不是服务端的公钥要怎么办?或者如果避免那种情况发生?设想一下如果在客户端、服务端之间存在一个可以截获双方来往所有信息的「中间人」,这个时候这个中间人会好到只满足于「偷窥」以外什么都不做么?

只加密传输信息无法防止中间人攻击

拿上面最繁琐的双向非对称举例,

  1. 客户端、服务端像彼此发送各自的公钥 A、B,但都被中间人截获,中间人以自己的公钥 C 顶替 A、B
  2. 客户端、服务端都收到中间人的公钥 C
  3. 客户端通过公钥 C 发送加密消息给服务端,但被中间人截获,(中间人使用自己的私钥解密,拿到信息后)通过服务端的公钥 B 冒充客户端发送加密消息给服务端
  4. 客户端收到消息后使用自己的私钥解密,然后用公钥 C 返回加密消息给客户端,依然被中间人截获,(中间人使用自己的私钥解密,拿到信息后)通过客户端的公钥 A 冒充服务端发送加密消息给客户端

这样客户端和服务端之间的通信完全被中间人截获,从而导致它们收到的信息完全有可能不是来自对方(假如这个中间人够坏的话),而双方毫不自知。所以,只要存在中间人,那么仅仅止步于加密是完全不够的。

出现这种问题的根源是什么?如何解决?显然,问题在于客户端、服务端双方都无办法保证「自己收到的公钥确确实实是来自对方」,所以如果能有这种保证,问题就能解决。那么如何保证?盖戳,就像现实中通过盖戳来证明一份文件的效力,服务器给客户端发送的公钥可以是一个盖了戳的公钥,那么当客户端收到公钥时,会验证上面的戳,如果是有效的,则认为公钥确确实实来自服务端;否则便认为是不安全的。当然,现在新出现一个问题是,如何保证戳的权威性和不被篡改?数字证书。

HTTPS 基本原理

HTTPS 比 HTTP 多出的内容基本可以概括为:

  1. 通过非对称加密 + 对称加密来实现通讯加密
  2. 通过数字证书来避免中间人攻击

第 1 点如前所述。第 2 点主要涉及如下概念:

  • 数字签名:签名者有一对公、私钥,用私钥将某段讯息加密后生成的内容就称之为数字签名,公钥公开,有了公钥,就可以对数字签名进行解密,解密后的的讯息与原讯息作对比就可以知道讯息是否被修改。
  • 数字证书:又称身份证书,用于证明某一公钥拥有者的身份,证书一般包含公钥信息、公钥拥有者的身份信息,以及「数字证书认证机构」(即颁发此证书的主体)对该证书的数字签名,这个数字签名的生成步骤一般为:1.对证书的内容进行散列得到一个散列值;2.数字证书认证机构使用自己的私钥对散列值加密便生成数字签名。打个比喻,证书就好像一纸合同,数字签名就是合同上的戳,但是这个戳是根据合同的内容生成的,合同加戳就是完整的数字证书。通过戳、合同的内容以及数字证书认证机构公布的公钥就可以校验拿到手的合同的内容是否在运输过程中被修改。
  • 数字证书认证机构:Certificate Authority(CA),专门对某些需要认证的公钥拥有者颁发证书的权威机构。

可以想见 CA 的权威性得以保证的前提是至少满足如下条件:

  1. 不管用何种手段,它必须保证用以生成数字证书上数字签名的私钥不会泄露出去(就好像一个公司的公章不能被泄露以及被伪造)
  2. 它自身不会充当「中间人」(公章的持有人有过硬的信誉)

明了证书相关的概念之后,HTTPS 的通讯过程就很好理解:

  1. 客户端像服务端请求数字证书
  2. 服务端返回数字证书
  3. 客户端拿到数字证书后,提取证书上的数字签名、根据证书内容生成散列值的散列算法,按照散列算法生成散列值,然后使用 CA 公布的公钥对数字签名进行解密,再对比解密后的内容与按照散列算法生成散列值,若一致则认为证书上的公钥以及证书的内容未被篡改,即公钥是可信的(,否则是不可信的)
  4. 拿到可信公钥后,客户端使用公钥将由自己生成的一个用于对称加密的密钥加密后发送给服务端
  5. 服务端使用自己的私钥解密后就拿到客户端传过来的密钥
  6. 后续的通信内容都通过那个密钥进行对称加、解密

4、5、6 步涉及的 TLS/SSL 协议的具体握手细节虽不可知,但整个 HTTPS 建立安全通信的过程大体如此。

可能还有疑问: Q:由于数字签名的存在,证书的内容或者直接说证书上的公钥好像不太可能被篡改,但是直接被调包呢?

A:虽然可能不适当,但是可以这样通俗的理解,证书就好像身份证,被调包分为两种情况:

  1. 中间人 A 拿着自己的身份证冒充服务端,显然无法得逞,身份证上有证书所有者的身份信息
  2. 中间人 A 拿着服务端 B 的身份证冒充服务端,这样好像可以?这个时候得逞的条件十分苛刻,中间人首先必须拿到证书,然后还要拿到证书上公钥对应的私钥,但其实既然连私钥都拿到了,也没必要冒充了

所以不管是 CA 的私钥还是服务端的私钥,只要二者任一被中间人拿到,那么通信就不再安全。

Q:CA 的公布的公钥如何保证可信? A:另一个 CA1 对其进行认证?可是 CA1 的公钥又该谁来认证?所以最终只能是至少存在某个 CA 对自己的公钥进行认证,否则一切的认证都是无根之木,而由某个 CA 对其自身公钥进行认证的证书便称为「根证书」,这个根证书安装在浏览器或操作系统里,安装了某个 CA 的根证书之后,所有由该 CA 直接或间接签发的证书都是可信的。这个最初给自己颁发证书的 CA 就好像最初从人变成鬼而且还能把其他人变成鬼的鬼王无惨,被 CA 认证的其他 CA 就好像十二鬼月。