非对称加密的那些事

非对称加密指的是加密和解密使用不同秘钥,它们分别叫做公钥私钥, 在这里公钥私钥都可以用来加密以及解密,RSA就是非对称加密算法中最有名的一种。

非对称加密相对于对称加密效率低,加密速度慢,但是却非常有用,因为对称加密算法加密和解密使用同一个秘钥,和多方通信的话,需要所有人都持有这个秘钥,则秘钥很容易泄露,这样加密也就没有意义了。而非对称加密算法可以将公钥公开给所有人,而私钥只有自己持有。

非对称加密因此也比对称加密复杂很多,有一些概念需要理顺一下,才能更好的理解这种加密算法。

公钥和私钥

公钥(Public Key)私钥(Private Key)是配对的秘钥对,公钥可以公开给所有人,而私钥要保证只有自己持有,不能泄露出去。

很多人都会说,公钥用来加密,私钥用来解密,这种说法是对的,但这种说法并不完整。其实公钥和私钥都可以用来对某一信息进行加密和解密,只不过两者的作用不同,这也是比较不容易理解的地方,所以下面会具体讲到。

公钥加密的信息,只有私钥才能解密,这就是为什么我们可以将公钥公开给任何人,但私钥只能自己留着。如果某人 A 想要与 B 使用非对称加密的方式通信,那么 B 先把自己的公钥给 A,然后 A 使用 B 的公钥加密要传输的信息再发送给 B,B 就可以使用自己的私钥来解密这段信息了。因为私钥始终只有自己持有,所以也就只有 B 才能解密 A 发过来的信息。公钥因为本来就可以公开,谁在这个过程中把 B 的公钥拿走了都没关系,所以只要保证 A 确实是拿的 B 的公钥来加密信息的,这样这段信息就只有 B 能解密了。

但是问题来了,A 怎么保证他就是拿的 B 的公钥来加密信息的呢?有没有可能在 A 不知情的情况下,有人 C 偷偷把 A 这边 B 的公钥换成了它自己的公钥,然后 A 其实是拿着 C 的公钥对信息加密发送给 B 呢?这当然是可能的,非对称加密算法保证了公钥加密的信息只有私钥可以解密,但是它不能保证通信双方确实是拿了对方的公钥来通信,在一般情况下,通信的双方其实没法保证自己拿在手上的公钥就是对方的公钥,因为也可能中间就被人掉包了。

在上面的例子中,假设 C 就是中间干这个事的人。A 想要发信息给 B,则 B 把自己的公钥发送给 A,这个时候 C 在中间把它们传递公钥的请求给截获了,他保留 B 的公钥,而把自己的公钥给了 A。这样 A 拿到的公钥并不是 B 的公钥,而是 C 的公钥,但 A 和 B 却都不知情。这时候 A 用他以为是 B 的其实是 C 的公钥对某一信息进行了加密,然后发送给 B,C 又在中间截获了该信息,如果 A 确实是拿的 B 的公钥来加密的话,C 是无法解密的,但现在 A 用的是 C 的公钥来加密的,所以 C 可以用自己的私钥来解密这段信息,从而可以窃取甚至篡改该信息,然后 C 再用 B 的公钥重新加密该信息,发送给 B。B 收到信息之后依然可以正常解密,但他不知道其实信息在中间已经被窃取甚至篡改了。

那么怎么来避免这种情况呢?我们总不能对交换秘钥的过程再进行一次相同的加密吧?这样的话就要陷入鸡生蛋蛋生鸡的问题中去了。所以解决办法就是双方不再直接交换秘钥了,而是通过一个可信任的第三方来帮助交换秘钥,这就是下面要说的数字证书的内容。

数字证书

https 中,通信的双方建立连接的过程中也使用了非对称加密算法,在这里,这个值得信任的第三方机构就是 CA。通信的双方都信任这个第三方,把自己的公钥交给他,委托他来帮忙传递自己的公钥。那么具体是怎么做的呢?

在之前的例子中,假设有一个可信任的第三方 X。还是 A 想要发送信息给 B,在通信开始前,B 先去向 X 请求一个数字证书,第三方 X 也有自己的公钥和私钥,所谓的数字证书,就是 X 用自己的私钥对 B 的公钥进行了加密产生的密文。

注意了,这里和之前不一样了,这里第三方 X 使用的是自己的私钥来加密。私钥加密的信息,所有和该私钥配对的公钥都可以解密,所以这个过程我们更应该称之为签名而不是加密。这个签名是为了生成数字证书, 和下面要说的数字签名在意义上还是有点区别的,虽然都是用的私钥加密,公钥解密的方式,下面会具体讲到。

现在 A 去请求 B 的公钥的时候,B 不是直接给它自己的公钥,而是将之前从可信任的第三方 X 申请得到的数字证书返回给 A,然后 A 用自己这边保存的第三方 X 的公钥来对该数字证书进行验证,如果可以验证解密,说明这个数字证书没有问题,解密之后的就是 B 的公钥,然后就可以用该公钥加密信息发送给 B 了。如果 A 无法用 X 的公钥来对该数字证书解密的话,那说明这个数字证书有问题,中间被人掉包了,那通信的 A 这方就可以意识到了。

这里大家可能有一个疑问,A 哪来的 X 的公钥,如果也是去请求得到的,那不是 X 的公钥也可能是被掉包的吗?所以 X 的公钥不是通过请求得来的,而是 A 本来就有。什么意思呢?因为 X 是大家都信任的第三方机构,所以所有人本来就都持有 X 的公钥。在 https 中反应出来就是浏览器中都内置了那些第三方可信机构 CA 的公钥。

通过引入可信任的第三方,使用数字证书,貌似已经解决了公钥被掉包的问题,但其实并没有。我们之前说了数字证书是可信任的第三方使用自己的私钥对通信一方的公钥进行签名之后得到的密文。既然 B 可以向 X 申请数字证书,那其他人也可以向 X 申请数字证书,假如 C 也向 X 申请证书呢?X 当然会颁发给他的证书,这样就会导致一个问题,即 C 依然截获 A 请求获得 B 数字证书的请求,将自己的数字证书返回给 A,这样 A 拿到了 C 的数字证书,用 X 的公钥依然可以对其验证解密,然后得到的却是 C 的公钥,这个时候 A 就意识不到数字证书其实被掉包的事了。

那这个时候该怎么办呢?需要向 X 申请证书的人有许多,如果这些人的证书没有任何区分度,都可以被 X 的公钥直接验证解密得到里面的公钥,而通信的双方都意识不到被掉包的话,那引入可信任第三方也就没有意义了。

数字签名

解决上面数字证书被掉包的方法,就是引入数字签名。所谓的数字签名也是由可信的第三方根据申请数字证书的主体的一些信息生成的一串文本,该文本同样也用第三方机构的私钥进行了签名,然后被包含在数字证书中。

还是在刚才的例子中,B 向 X 申请数字证书,X 用自己的私钥给 B 的公钥进行了签名生成数字证书,同时将 B 的公钥以及 B 的个人信息用某种 hash 算法例如 MD5 计算得到一个信息摘要,然后再用自己的私钥对该摘要签名,得到签名后的数字签名,也放到数字证书中,再颁发给 B。数字证书中同时附有数字签名的生成方法(此例中即使用 MD5 对 B 的公钥以及个人信息计算信息摘要),方便拿到该数字证书的人验证该证书知否确实是 B 的数字证书,而没有被掉包。

这样 A 请求 B 的数字证书之后,A 可以通过验证 B 的数字证书中的数字签名来确定该证书是不是 B 的数字证书。假设 C 拿自己的数字证书调换了 B 的数字证书,因为 C 没有 X 的私钥,所以即使它可以用同样的方式生成制作数字签名,但该数字签名没法用 X 的私钥进行签名,所以 A 一验证就可以发现得到的数字证书是否有问题。

总结

上面解释了一些非对称加密中常见的概念,同时这也简单解释了 https 建立连接的过程中的加密措施。https 同时使用了对称加密和非对称加密,在用非对称加密的方式建立起连接,并且协商出秘钥之后,就可以通过对称加密的方式来传输内容了。

非对称加密的私钥非常重要,从上面解释中我们可以看到私钥不仅可以用来解密用公钥加密的密文,也可以用来签名,即证明“你”就是“你”,如果你的秘钥落到了别人手里,那么“他”就可以冒充“你”了。