PKI概述

Public Key Infrastructure,即公钥基础设施。

以下摘自百度百科:

公钥基础设施是一个包括硬件、软件、人员、策略和规程的集合,用来实现基于公钥密码体制的密钥和证书的产生、管理、存储、分发和撤销等功能。
PKI体系是计算机软硬件、权威机构及应用系统的结合。它为实施电子商务、电子政务、办公自动化等提供了基本的安全服务,从而使那些彼此不认识或距离很远的用户能通过信任链安全地交流。

当然,要是光看定义能看懂的话,想必各位也不会见到这一篇文章了,贴出定义只是个人习惯,咱们往下看。

明文与密文

首先咱们要知道,咱们能够阅读理解的东西是明文,比如远在天边的网友给你发的一条qq消息,你看到的时候它就是明文,这样你才能看得懂你的网友想和你说些什么。

当然,你看得懂,别人也看得懂,中文嘛,大家都学过。
你想着,我要是不想赤裸裸的让别人窥探我的聊天内容是吧,咱们多少还是希望能有些隐私的。

加密自然而然的出现了。

我们通过某种方法对明文原本的信息进行可逆的改变,别人只要不知道我们是如何改变的,就无法还原,只有我们才能够还原为明文。
加密后无法直接理解的信息,我们就叫做密文

前置知识

密钥

通常也是一组数据,就像现实世界的钥匙,是加锁/解锁的关键。

对称加密

首先创建一把密钥

通过这把密钥可以加密明文;
对密文的解密也需要同样的一把密钥
如同常见的钥匙和锁一般,加锁和解锁都是同一把钥匙。

缺陷:在公共的网络环境中,密钥难以安全传递。

非对称加密

创建两把密钥,一把公钥,一把私钥,这两把密钥是对应关系
公钥是公开的,任何人都可以获得。
私钥是私有的,只有创建者持有。

公钥加密的东西,只有对应的私钥能够解密;
私钥加密的东西,只有对应的公钥能够解密。

相对对称加密而言,不存在密钥无法安全传递的问题。

缺陷:基本上基于数学难题,加密速度十分缓慢。

信息摘要

数据的指纹,具有不可逆的性质。

一般输出的指纹数据长度都是固定的,便于传输。
通常可以用于验证数据是否被篡改。
数据被篡改一位,都会导致计算出来的信息摘要不同。

安全通信

有了上述基础,你能否在公共网络中构建安全通信信道呢?
我们来尝试一下。

基本框架:非对称加密

当然,我们的数据不能在公网上裸奔,因此首先就需要对明文进行加密。

但此时我们难以解决密钥安全传输的问题,故需要引入非对称加密
你可能会想到,如果我把密钥也加密呢?那如何解密加密后的密钥呢?是不是也需要一把新的密钥?这把密钥如何传输呢?
往复下去也不会有变化,并没有改变无法安全传输密钥的根本问题。

通信过程

  1. 假设A、B需要通信,各自创建私钥与公钥,并且交换公钥;

    • 公钥是可以公开的,任何人都可以持有。
  2. A向B发送消息之前,使用B的公钥加密,再发送给B;

    • 密文只有B能够解密,因为只有B持有对应的私钥。
  3. B向A发送消息也是如此,使用A的公钥加密,再发送给A。

第一个问题:计算效率

在基础中提及到,非对称加密的计算缓慢,假设传输的数据较多,那么需要消耗大量的时间进行计算。

性能提高:引入对称加密

此时,对称加密计算效率高的特性能够完美弥补这个缺陷,故我们还是需要引入对称加密
加密方案基本上都会首先基于流行的加密算法,只有这种经过全世界密码学家考验的加密算法才是可靠的。

通信过程改进

  1. A、B交换公钥;
  2. A生成本次通信的密钥,使用B的公钥加密,再将加密后的密钥发送给B;
  3. B生成本次通信的密钥,使用A的公钥加密,再将加密后的密钥发送给A;
    • 此步并不一定需要,可以共用一把对称加密密钥。
  4. 各自用私钥解密密钥,往后的通信都使用这把密钥加密/解密。

第二个问题:中间人攻击

  1. A、B交换公钥;
    • 假设A、B交换公钥的通信信道被C窃听了,C也生成了自己的公钥与私钥对,将A、B的公钥保存起来,并将信道上的A、B的公钥替换为C的公钥发给对方;
    • A收到的是C的公钥,B收到的也是C的公钥。
  2. A、B交换密钥;
    • A使用C的公钥加密密钥,发往B;
      • 依旧被C劫持,C通过私钥解密,得到原始密钥,再将其通过B的公钥加密,替换后发往B。
    • B收到B的公钥加密的密钥,用B的私钥解密,得到密钥。
    • B发往A同理。

这个过程中,A和B看似正常安全的通信,实际上自以为隐私的通信信道早已被C看得干干净净。

  • 对于A而言,C伪造身份为B与A通信
  • 对于B而言,C伪造身份为A与B通信

避免篡改:数据指纹

你可能会想到,既然信息摘要可以避免数据被篡改,那么能不能在发送公钥的时候顺带发送信息摘要来避免中间人伪造身份?

实际上是不行的,因为中间人完全可以重新使用相同的信息摘要算法重新计算被替换的公钥,得到新的指纹,将信息摘要也替换。
而接收者无法辨别信息摘要是否已被替换。

验明身份:数字证书

首先想一下,现实世界咱们是如何证明你是你呢?
多数情况下都是亮出身份证,对吧,我们有国家颁发的身份证。
因为是国家颁发的,有权威性公信力,大家伙都相信和认可。

在公网上证明你是你的话,也得拿出证据说话,随便说说我是不认的,谁知道你是不是中间人那个坏蛋呢?

因此,证书自然就出现了。


证书

证书类似”身份证”,用于证明某个人(公司)的身份,如:

所有者:ABC, www.abc.com
公钥:xxxxxx
颁发CA机构:XXX


证书当中记录了一些必要的信息,当然,就简简单单的在证书里写我是XXX,那肯定也不行,因为一点可信度都没有,中间人也可以给你发这么一串数据,说他也是XXX,你是信还是不信呢?

因此引入证书也不可避免的产生了一个问题:证书也能被替换

拒绝伪造:数字签名

上面我们提到过,私钥加密的东西,只有公钥才能解密。
咋一看好像没什么鸡蛋饼用,我这私钥加密,所有人都能解密,这有个啥用啊?
实际上,这也是验证身份的核心关键:不可抵赖性

如果我们将这个特性应用到证书上呢?

A的私钥只有A持有,那么A用私钥加密的A证书,只有用A的公钥才能正确解密。
B想要判断A的身份,只需要用A的公钥解密A证书,如果能够正确解密的话,那么这个证书就一定是A的,别人无法伪造的东西,A自然无法抵赖,也就验明了A的身份。

我们就把经过公钥加密的证书叫做数字证书

而用私钥加密数据的过程就叫做数字签名
数字签名具备不可抵赖性

咋一看好像已经完结撒花了,实际上还是无法真正避免中间人攻击。
因为A的公钥需要在公网上传播,就存在被C偷天换日,替换为C的公钥的可能。

B以为拿到的是A的公钥,实际上还是C的公钥,因此C用C的私钥伪造数字证书再发给B,B当然能够正确解密,这也给了B一个错觉:和我通信的A的身份没有问题。
所以A和B见面后:

B:就是你,A!你为什么要骂我?我要和你绝交!
A:????啥啊,我说啥了!
B:还想抵赖?我都能用你的公钥解开你的数字证书!

无奈之举:本地预装

哪里都有C这个小人,咱们实在是没法子了,干脆直接在本地计算机中预先存放公钥吧,这样C就没有替换公钥的机会了。

但是这样又会出现其他的问题:

  • 如何提前预装需要与其通信的对象的公钥?这就跟如何安全交换对称加密密钥是一个难度了,属于物理层面的难题。

最终解法:权威机构

人们怎么能被C这个小人打败呢?于是,这么一套验证体系出现了:
在本地计算机中预装权威机构CA颁发的数字证书,通过CA的数字证书来验证经过了公网的数字证书是否可信,避免中间人攻击。

CA证书授权中心

CA证书授权(CertificateAuthority)中心是数字证书发行的唯一机构。

CA机构持有自己的公钥与私钥

  • 公钥是公开的,会包含在数字证书内,预置到操作系统/浏览器中。
    • 即CA机构会生成一份自己的明文证书(里面的公钥就是公开的公钥),然后自己用私钥签名(又或者是交给其他CA机构去签名),自签发的数字证书就应该是根证书,不管是自签发还是其他CA机构签发的,最后都会得到数字证书
  • 私钥由CA机构自行保存。
    • 这样子就保证了数字签名的可靠,因为别人是无法得到CA机构的私钥的,也就无法伪造该CA机构所签发的数字证书。

签发数字证书

B假定是服务器,他如果想和客户端建立安全信道,得到客户端的信任,就需要先向CA机构申请数字证书。

  • B提交证书;
  • CA机构对证书进行签名,得到数字证书,交回给B。

签发后的数字证书包含了:证书内容摘要算法加密摘要信息 三部分。

CA机构使用摘要算法对证书内容进行计算,得到摘要信息,再对摘要信息使用私钥进行加密。
为什么不直接加密证书内容?因为加密摘要信息可以减少计算量,同样也可以保证数字证书不被篡改。

客户端收到B的数字证书时,就会先使用预装的CA数字证书(包含了CA的公钥)对加密摘要信息进行解密,同时用摘要算法对证书内容进行计算,得到摘要信息。
最后比较解密后的摘要信息与计算得出的摘要信息,相同则表示数据并未被篡改。

看到这里想必有些读者就迷糊了:
CA机构颁发的数字证书和服务器的数字证书到底是不是一回事呢?
可以说是一回事,他们是逐层签发的关系。
我先信任我计算机中的数字证书,而服务器发过来的数字证书又是我所信任的数字证书对应的私钥(CA机构持有)签发的(通过我所信任的数字证书进行验证),故我再信任服务器发过来的数字证书。

可为什么预装的是数字证书,而不是直接是公钥呢?
有更多的信息需要存放,因此将其封装是更好的选择。

为什么是服务器申请数字证书,客户端不需要吗?
首先数字证书通常需要向权威机构申请,并且是需要钱的;
其次也很难为全世界所有计算机都分配数字证书;
最后通常也无需验证客户端的身份,因为服务器所服务的对象绝大多数应用场景下并不特指某个客户端(不管你是正常用户还是坏蛋,我都一视同仁),只需要客户端认证服务器的身份就足够了。

验证过程

签名:

  1. A生成证书(填好个人信息),发给CA机构。
  2. CA机构通过散列函数对明文证书进行计算,得到明文证书的信息摘要。
  3. CA机构通过持有的私钥加密信息摘要,其结果即数字签名
  4. 将明文证书以及数字签名打包,即得到数字证书,再发给申请者A。

验签:

  1. B收到A发来的数字证书,包含了明文证书与CA机构签发的数字签名
  2. B通过本地预置的CA机构数字证书中的公钥,对数字签名进行解密,得到信息摘要
  3. B通过散列函数对明文证书进行计算,得到明文证书的信息摘要。
  4. 比较计算明文证书得到的信息摘要与解密数字签名得到的信息摘要,不同则表示明文证书被篡改了。

补充

  • CA是有能力进行中间人攻击的,因为CA持有大家伙本地计算机预置公钥的私钥。

    • CA叫做CA的意义就在这里,CA机构必须是权威公信的,不能做出这种行为,否则将会失去大家伙的信任。
  • 数字签名并非只能用于签名明文证书得到数字证书,可以用于签名任何数据防止篡改。

证书信任链

如公司ABC的数字证书,就是由A机构签发的,需要用A机构的数字证书来验签;
而A机构的数字证书又是B机构签发的,需要用B机构的数字证书来验签;
这样就形成了信任链。

信任过程就是逐层向上的验签,直到根证书(Root,即自签名的证书)为止;
对根证书只能无条件信任。

WindowsPE文件数字签名简述

Windows的PE文件如果存在数字签名,那么在其安全目录中,即包含了数字证书,再将PE文件散列值进行数字签名(由PE文件数字证书的所有者签名),同样也包含在内。
首先通过本地预置数字证书证明PE文件中数字证书的可靠性,再通过PE文件中的数字证书的公钥解密(验签)数字签名,得到正确的散列值,再计算PE文件的散列值进行比较。

参考文献

https://blog.csdn.net/sky8336/article/details/113696551
https://zhuanlan.zhihu.com/p/43789231