前言:每当Client从Server收到一张证书,有2件事Client需要去验证:
- 证书是否有效?
- 证书只是文件中的文本
- Client如何知道内容能够信任?
- Server是否是证书真正的拥有者?
- 证书可以公开获取
- Client如何知道Server是真正的拥有者?
1、证书是否有效?
- Certificate Authority(须知道CA是证书的实际创造者)
- 往期内容(《SSL证书里包含的具体内容》)提到过证书包含3个部分(证书数据、签名算法和签名),当CA创建证书时,会将证书数据(如subject、validity、public key等)填到证书中。
- 之后,CA会创建证书数据所有内容的哈希值(通过哈希算法),如上图1fc616f4...
- 再然后,CA会用自己的私钥加密这段哈希值,生成的就是签名,如上图ad3a0c30...
- 之后将ad3a0c30...放置到证书的第三部分,也即签名,这个签名能用来验证证书内容的有效性。
- Client
- 需要知道的是,在Client连接到Server前,Client其实已经有了CA的证书(当我们安装浏览器时其实已经安装了,重要的是Client已经有了CA的公钥,该公钥可以用来验证来自CA的所有证书)
- Client获得了Server的证书
- 用CA的公钥解密签名,得到一段哈希值H1
- Client计算证书数据的哈希值H2
- 如果得到的结果H2和证书签名解密得到的结果H1相同,这就说明证书内容从CA创建它之后没有被修改过
这也就意味着,如果我们信任CA,其实我们就信任了证书的有效性。
所以,回答证书是否有效的问题,包含用我们已安装的CA公钥来验证签名。
以上所讨论的内容是RSA签名证书,而DSA签名证书(只有两步操作,证书生成+证书验证)的过程是类似的。
- 当CA创建证书时,CA将在证书数据上运行DSA的“证书生成”操作,该操作需要CA的私钥,生成的结果就是签名(这也将被安置于证书的第三部分)。
- Client之后将在证书签名上运行DSA的“证书验证”操作,该操作需要CA的公钥(客户已经有了),得到的结果是1或0代表True or False,结果如果是1,则表明证书有效。
一旦证书被验证了,就可以检查以下简单的内容:
- Validity - 证书是否已到期
- Subject - 地址栏中的URL和Subject的CN(通用名)是否匹配,或者主体替代名称中的条目(Subject Alternative Name)相匹配
- 还有一个问题就是证书是否被撤销(Certificate Revoked),因为是不同的过程,将在以后进行讲述
2、Server是否是证书真正的拥有者?
一般情况下,Client要连接Server,Server会提供自己的证书给Client(假设Server是freessl.cn,那么freessl.cn就是本篇将提到的证书真正的拥有者)。在没有进行SSL连接之前,我们没法阻止钓鱼网站去发送Server的证书给Client,他会伪装自己是freessl.cn,当Client收到了这个证书,证书会表明它是有效的,而这张证书是freessl.cn的,所以Client要验证该证书的时候,就只是检查一下。这就是为什么第二个问题很重要。
- 要回答这个问题,我们要证明的是Server是否拥有私钥,该私钥匹配证书里的公钥。只有true owner拥有匹配公钥的私钥,钓鱼网站能够伪装说自己有相同的证书,但它没有匹配的私钥。
- 2种方法:
- Client Initiated(客户端发起)
- Client生成随机值(如6d5da73e),然后用服务器的公钥(在证书中)加密这个值(得到3e5f5ff2)
- 加密后的密文会进行在线传输,那么这个世界上能够拿到3e5f5ff2,并且提取到原始值的,就是Server的私钥(只有True owner才有私钥)
- Server用自己的私钥解密密文,然后提取出原始值(6d5da73e)
- 现在双方都有了相同的值,但现在Server不能简单地将解密后的值在线传回给Client,并以此来证明自己可以解密内容(否则任何中间人就可以截取信息并传回Client来假装自己是Server)
- 取而代之的是,值被用来生成会话密钥(Session Keys),它们是对称密钥,用来保护在Client和Server之间的批量数据传输
- 方法是,当Client发送应用程序数据给Server时,会用会话密钥来进行保护;然后Server会用会话密钥解密接收到的应用数据。这就表明,Server拥有和Client相同的会话密钥,也就是说Server有着相同的初始值(6d5da73e)来创建会话密钥;同时也表明,Server能够用自己的私钥提取出初始的随机值。这也就向Client表明,该Server是证书的真正拥有者。
- Server Initiated(服务器发起)
- 在某些时候进行SSL握手时,Server必须要发送一个值(随机值b87c20db)给Client
- 在线传输这个值(b87c20db)之前,Server会用自己的私钥来给这个值进行签名
- 之后该签名以及值会在线传输给Client,然后Client会用Server的公钥来验证该签名,如果签名正确,那就告诉我们,唯一能加密该签名的(能够用公钥验证)就是拥有私钥的人。因此,该Server一定是证书的真正拥有者。
- 那么,万一这个值像上面一样,被用来生成会话密钥,但这个值是以明文形式在线传输的。我们所做的是签名,签名提供不提供保密性(Confidentiality),只提供完整性(Integrity)和真实性(Authentication)。所以,任何正在聆听的人都能得到该值(b87c20db)的副本。因而,我们不能直接用该值来生成会话密钥。
- 取而代之,该值需要与其他值(只有Client和Server知道)结合起来,来生成会话密钥
- 我们发现,第二个方法的值是间接使用的(与其他值结合起来使用),而第一个方法则是直接使用
- Client Initiated(客户端发起)
总结:
关于RSA、DH、DSA更多详情,请看《SSL证书之RSA、Diffie-Hellman和DSA》
- 我们使用方法1或者方法1,取决于我们想要用什么协议来提供Authentication,什么协议来提供Key Exchange
- 注意到方法1提到,用公钥加密,私钥解密,唯一能做到的非对称加密协议就是RSA。意味着,如果Client想要用RSA进行Authentication,用RSA来进行Key Exchange,Client就要执行方法1
- 方法2提到签名,我们注意到有2个协议和签名有关,即RSA和DSA。意味着,如果Client和Server决定用RSA或者DSA来提供Authentication,就要执行方法2
- 方法2重要的是有Key Exchange,有2个协议(RSA、DH)提供密钥交换。RSA的密钥交换包含公钥加密/私钥解密,那我们注意到方法2没有提到加密,因而,我们不能用RSA来作密钥交换,我们可以用DH来进行密钥交换。
- 方法2的随机值其实不是随机值,它其实是Diffie-Hellman公钥(回顾下,在DH中,双方公开分享数据,并将其与只有他们知道的值相结合,来达到分享秘密的目的),这个secret就是用来生成会话密钥的
- 因此,决定选择方法1或者方法2,取决于Key Exchange。如果要选RSA作密钥交换,我们可以选择方法1;如果选择DH作密钥交换,我们可以选择方法2。
- 此外,2种方法都提供了Authentication和Key Exchange,而Authentication回答了Server是否是true owner的问题
参考文献
1、网站:Practical Networking.net:Practical TLS
标签:私钥,证书,CA,笔记,Server,SSL,Client,签名 From: https://blog.csdn.net/Taki_UP/article/details/141866874