您的位置:首页 > 其它

TLS/SSL 协议详解(6) SSL 数字证书的一些细节1

2017-09-06 15:37 344 查看
  证书关系到了SSL的众多安全性,比如身份认证,密钥交换。所以有必要单拉出一章来讲证书。本章完善一下前几节中的身份认证的一些缺点。

  首先,通过前面讲解,我们知道,证书需要几个重要的字段。例如“拥有者”、“颁发者”、“截止日期”。另外,生成证书的时候会自动生成一份“公钥”以及对应的“私钥”。现在假设我开了一个网站,准备用SSL加密的,需要让全世界信任我这个网站,那么我就需要一个证书,这时候我该怎么做?

 

  假设目前全世界就Google有那么一个root证书(根证书),名字叫做“Google”,显然,它的“颁发者”也是“Google”,因为根证书都是用工具生成的,并且根据第四章的知识,你应该知道,根证书没有颁发者,所以理所当然的,颁发者也是它自己。现在,全世界都信任这个证书,换句话说,浏览器里面都信任这个证书(约定俗成的)。我们也想和谷歌一样,有一个全世界都信任的证书,怎么做?

  第一步:给Google钱。

  第二步:告诉谷歌,我想要的证书名字叫做“www.dp.com”。

  第三步:等着谷歌返回给你:证书、公钥、私钥。

 

  谷歌收到钱后是怎么做的呢?首先肯定对你的网站、公司进行调查,确保你不是坏人,以免全世界都信任你了你却干坏事,这会让谷歌丢脸。

  第一步:用工具生成一对公钥和私钥。

  第二步:构造证书,把公钥嵌入到证书里面(即证书里面其实有一个字段是公钥,明文的)

  第三步:最重要的一步,谷歌拿自己的根证书签名一个第三步构造好的证书。

  所谓签名:就是对第三步的证书做摘要,MD5或者SHA1,或者MD5+SHA1,得到结果,然后拿自己根证书的私钥加密这个结果,然后添加到证书最后面。

第四步:把证书和私钥交给你。



这就是一个证书的生成过程。后续将讲解为什么这么生成证书。

证书验证(如何保证你是证书的拥有者)

上一节我们花很多钱,让谷歌生用自己的证书为我们签名了一个证书。现在我们可以把谷歌给我们的证书,安装到我们的网站中了。如果有一个客户端,访问我们的网站,我们发送我们的证书给客户端,客户端如何验证呢?(注意,第四章的验证比较简单,这里才是真正的验证)

 

之前说过,客户端信任了许多根证书,比如客户端信任一个叫做“Google”的证书。首先浏览器收到我们的证书之后,查看它的颁发者,哦,是“Google”,于是到信任的根证书里面找一个名字叫做“Google”的证书,通过字符串比较,我们很容易找到“Google”这个证书。然后进行验证:

第一步:对我们的证书(除了“签名值”)全部内容进行MD5/SHA1,得到一个结果1

第二步:用“Google”证书中的公钥,对我们证书中的“签名值”进行解密,得到结果2

第三步:比较结果1 和结果2 ,发现一样,那么认证通过。理论上,如果中间没人改动我们的证书,那么,结果1结果2 都是“asdfghjklqwertyu”。

 

那么上面的操作,如何保证了服务器身份能够被客户端认证呢?我们换个角度来思考,假设我是坏人,我想欺骗客户端,怎么办?

 

第一种方法:我们想到,既然浏览器信任一个叫做“Google”的证书,那我就在我的网站导入它不就行了吗?但是根据第四章中“密钥的协商、交换”一节中提到的那样,公钥和私钥是一对的,我虽然得到了“Google”证书,证书中也有Google的公钥,但是我没有它对应私钥,我虽然把证书发给客户端,客户端的确认证了,然后客户端用证书中的公钥加密一个密钥,可是我没有对应私钥所,以没办法解密!后面的会话都解密不了。

 

第二种方法:那我就也用工具,随便生成一个根证书,名字叫做“Google”,对应该证书,也会随机生成一个公钥和私钥,然后模仿谷歌的,拿这个根证书的私钥签名一个证书:颁发者填写“Google”,拥有者填写“www.dp.com”
,然后做MD5/SHA1,得到结果“asdfghjklqwertyu”,拿刚才自己生成的“Google”证书的私钥,对这个结果加密,得到“lkjhgfd”:



我把这个证书发给客户端,客户端找到叫做“Google”的证书,拿它的公钥解密这个签名值,问题来了,这个由于这个签名值是由我刚才假冒的“Google”证书的私钥签名的,所以,正宗的“Google”正宗的公钥解密得到的结果,压根不是“asdfghjklqwertyu”,当客户端对我们这个证书做摘要,结果是“asdfghjklqwertyu”,但是对签名解密的结果却是另外一个值,那么浏览器就不信任你了。

第三种方法:看来生成证书的方法行不通,拿只能随便找一个证书,修改里面的颁发者和拥有者。



但是问题又出现了,我们签名值没办法更改,浏览器会对证书的签名用Google的公钥解密,然后对比证书的摘要,如果直接我们不该签名值,浏览器就不认了,如果我们要改签名值,就需要颁发者即“Google”的私钥,不过这显然不可能。

 

上面伪造身份的结果的是失败的,其安全性都是基于那个“签名值”,签名值是用颁发者自己的私钥加密的,只要颁发者的私钥不泄密,那么不可能有人伪造证书。

证书链

之所以存在证书链这个东西,是因为验证证书的时候需要。



假设如上图所示,“Google”签名了一个“Android”,然后“Android”签名了一个“CyanogenMod”,我们浏览器只信任“Google”,如果服务器只发送一个叫做“CyanogenMod”,那么我们无法查找到叫做“Android”的根证书,无法验证服务器的身份。此时,作为服务器,我们可发送“Android”+“CyanogenMod”,这样,客户端会首先验证CyanogenMod是否是Android的颁发者(验证签名),如果是,那么在自己的根证书里面找“CyanogenMod”的颁发者“Google”,然后验证“CyanogenMod”是否是由“Google”颁发的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: