我们以 Alice 与 Bob 一次通信来贯穿全文,一开始他们都是用明文的形式在网络传输通信内容。
如果在他们的通信链路出现了一个 Hacker,由于通信内容都是明文可见,所以 Hacker 可以嗅探看到这些内容;
也可以篡改这些内容。
公众号的文章之前就遇到很多被挟持篡改了内容,插入广告。
既然明文有问题,那就需要对明文进行加密处理,让中间人看不懂内容,于是乎要对原来的内容变成一段看不懂的内容,称为加密,反之则是解密。
而本质其实就是一种数学运算的逆运算,类似加法减法,例如发送方可以将 abcd…xyz 每个字母 +1 映射成 bcd…yza,使得原文的字母变成看不懂的序列,而接收方只需要将每个字母 -1 就可以恢复成原来的序列,当然这种做法规律太容易被破解了。
如果对 2 个二进制数 A 和 B 进行异或运算得到结果 C, 那 C 和 B 再异或一次就会回到 A,所以异或也可以作为加密解密的运算。把操作数 A 作为明文,操作数 B 作为密钥,结果 C 作为密文。加密解密运用同一个密钥 B,把这种加解密都用同一个密钥的方式叫做对称加密。
Alice 与 Bob 如果能提前拿到一个对称加密的密钥,他们就可以通过加密明文来保证他们说话内容不会被 Hacker 看到了。
刚刚还引发另一个问题,这个对称加密用到的密钥怎么互相告知呢?如果在传输真正的数据之前,先把密钥传过去,那 Hacker 还是能嗅探到,那之后就了无秘密了。于是乎出现另外一种手段:
这就是非对称加密,任何人都可以通过拿到 Bob 公开的公钥对内容进行加密,然后只有 Bob 自己私有的钥匙才能解密还原出原来内容。
RSA 就是这样一个算法,具体数学证明利用了大质数乘法难以分解、费马小定理等数学理论支撑它难以破解。相对于前边的对称加密来说,其需要做乘法模除等操作,性能效率比对称加密差很多。
由于非对称加密的性能低,因此我们用它来先协商对称加密的密钥即可,后续真正通信的内容还是用对称加密的手段,提高整体的性能。
上边虽然解决了密钥配送的问题,但是中间人还是可以欺骗双方,只要在 Alice 像 Bob 要公钥的时候,Hacker 把自己公钥给了 Alice,而 Alice 是不知道这个事情的,以为一直都是 Bob 跟她在通信。
一般我们现实生活是怎么证明 Bob 就是 Bob 呢?一般都是政府给我们每个人发一个身份证,我只要看到 Bob 身份证,就证明 Bob 就是 Bob。
网络也可以这么做,如果有个大家都信任的组织 CA 给每个人出证明,那 Alice 只要拿到这个证明,检查一下是不是 CA 制作的 Bob 证书就可以证明 Bob 是 Bob。所以这个证书里边需要有两个重要的东西:Bob 的公钥 + CA 做的数字签名。
前边说到用公钥进行加密,只有拥有私钥的人才能解密。数字证书有点反过来:用私钥进行加密,用公钥进行解密。CA 用自己的私钥对 Bob 的信息(包含 Bob 公钥)进行加密,由于 Alice 无条件信任 CA,所以已经提前知道 CA 的公钥,当她收到 Bob 证书的时候,只要用 CA 的公钥对 Bob 证书内容进行解密,发现能否成功解开(还需要校验完整性),此时说明 Bob 就是 Bob,那之后用证书里边的 Bob 公钥来走之前的流程,就解决了中间人欺骗这个问题了。
这种方式也是一种防抵赖的方式,让对方把消息做一个数字签名,只要我收到消息,用对方的公钥成功解开校验这个签名,说明这个消息必然是对方发给我的,对方不可以抵赖这个行为,因为只有他才拥有做数字签名的私钥。
CA 其实是有多级关系,顶层有个根 CA,只要他信任 B,B 信任 C,C 信任 D,那我们基本就可以认为 D 是可信的。
上边基本上已经解决了保密性和认证,还有一个完整性没有保障。虽然 Hacker 还是看不懂内容,但是 Hacker 可以随便篡改通信内容的几个 bit 位,此时 Bob 解密看到的可能是很乱的内容,但是他也不知道这个究竟是 Alice 真实发的内容,还是被别人偷偷改了的内容。
单向 Hash 函数可以把输入变成一个定长的输出串,其特点就是无法从这个输出还原回输入内容,并且不同的输入几乎不可能产生相同的输出,即便你要特意去找也非常难找到这样的输入,因此 Alice 只要将明文内容做一个 Hash 运算得到一个 Hash 值,并一起加密传递过去给 Bob。Hacker 即便篡改了内容,Bob 解密之后发现拿到的内容以及对应计算出来的 Hash 值与传递过来的不一致,说明这个包的完整性被破坏了。