PKI(公钥基础设施)流程全解析

PKI是通过将非对称加密算法和对称加密算法组合起来的安全通信策略,旨在让让两个互不认识的实体安全通信,验证身份。

流程:

一、证书的生成

用户生成公钥+私钥→管理员(申请者)将公钥+身份信息用自己的私钥签名,形成.csr文件→

发送给属于证书颁发机构(CA)的注册机构RA→

RA进行身份验证→

CA从csr提取出公钥和身份信息,然后加上有效期、Issuer、序列号然后计算哈希H,再用自己的私钥签名得到签名S→

包含公钥+算法、有效期、序列号等+签名S的证书发给网站管理员,证书和密钥一起配置在服务器中。

二、证书的使用

浏览器向服务器发送client Hello,包含随机数A→
服务器向浏览器发送Server Hello,包含随机数B以及自己的证书server.crt→
浏览器收到证书之后,首先读取Issuer,在操作系统的信任储存中查到对应机构的公钥,RSA加密算法用该公钥计算签名S计算出H1,然后再根据证书内容自行计算签名得到H2,如果两个签名满足H1==H2,则证书内容没有被篡改→

继续验证证书是在有效期,是否被吊销→检查全部通过,浏览器信任这个证书→

继续通信。

三、密钥的交换

RSA密钥交换:浏览器发送网站公钥的加密的pre-master secret,服务器收到后解密。这样服务器和浏览器都有了随机数A、B以及pre-master secret,各自用三者计算出会话加密密钥K→此后所有的会话使用该密钥K对称加密(AES-GCM传输)

然而RSA密钥交换存在前向安全性的问题。RSA密钥的安全性依赖于私钥K。设想一下:如果hacker记录了流量内容,而服务器的私钥K通过其他方式泄露了,那么曾经的会话内容hacker都可以解密,因此传统的RSA算法不具备前向安全性,目前TLS 1.3 已移除 RSA 密钥交换。

因此目前主流是使用了Diffie-Hellman算法,简称DH算法,中心思想就是将密钥区分为长期密钥和临时密钥,长期密钥用于签名以及验证签名,临时密钥则用完就丢弃,同时避免网络传输,使用结合律和中间方程解出来的极低可能性构建算法的安全性。

具体而言:DH算法首先双方约定公共参数p,g,p是一个巨大的质数,g为底数。然后服务器和浏览器各自生成一个密钥对,双方私钥记为a,b(浏览器,服务器的顺序),然后双方计算各自公钥A,B并互相发送,浏览器收到:

1
2
A=(g^a)mod p
B=(g^b)mod p

互相交换:最后浏览器计算共享密钥为shared_key=(B^a) mod p,服务器计算为shared_key=(A^b) mod p,看着输入不同,但实际上就是单纯的调整了计算顺序,最终完整的计算过程都是:shared_key=g^(ba) mod p也就是共享密钥是一样的。但是共享密钥在此过程中并未进行任何传递。那可不可以根据A、B推出密钥a或者b呢?数学上这是大质数的离散对数问题,解出来所需要的算力及其大,因此这就保证了DH算法的安全性。

DH算法进一步发展为ECDH算法,原理实际上是差不多的,但是由一般的离散对数问题变成了椭圆曲线离散对数问题,公式如下:

1
2
3
A=a × G
B=b × G
shared_key=(ab) × G

仍然是一个只传输中间值而中间方程几乎不可解的思路。

最后无论是DH还是ECDH,shared_key都经过 HKDF 等 KDF 派生出真正的加密密钥和 MAC 密钥。

那么长期密钥又有何作用呢?无论在椭圆曲线DH算法还是最初始的DH算法,长期私钥主要用于给临时公钥签名,防止公钥被中间人替换。浏览器经过证书里的长期公钥验证签名验证临时公钥是否来自服务器,签名算法可能是 RSA 或 ECDSA,取决于证书类型。

1
2
3
4
5
6
7
#解释说明:RSA算法:公钥(e,n),密钥(d,n),d叫私钥指数,e叫公钥指数,n为模数,三者的关系为:
将p拆成两个相乘的质数p和q,计算欧拉函数φ(n)=(p-1)(q-1),de≡1modφ(n),由于模数分解构成了大整数分解问题,所以,RSA的安全性由此产生。
加密:密文=(明文^e) mod n
解密:明文=(密文^d) mod n
签名:签名=(哈希^d) mod n
验证签名:哈希=(签名^e) mod n
数学上来说,签名是个解密过程,而验证签名是个加密过程