代码改变世界

程序员之网络安全系列(五):数字证书以及12306的证书问题

2016-01-12 15:12  敏捷的水  阅读(5930)  评论(20编辑  收藏  举报

系列目录:

前文回顾

假如,明明和丽丽相互不认识,明明想给丽丽写一封情书,让隔壁老王送去

  1. 如何保证隔壁老王不能看到情书内容?(保密性)
  2. 如何保证隔壁老王不修改情书的内容?(完整性)
  3. 如何保证隔壁老王不冒充明明?(身份认证)
  4. 如何保证明明不能否认情书是自己写的?(来源的不可否认)

程序员之网络安全系列(二):如何安全保存用户密码及哈希算法 我们保证了数据的完整性

程序员之网络安全系列(三):数据加密之对称加密算法
我们对数据进行了加密

程序员之网络安全系列(四):数据加密之非对称加密算法
我们使用了非对称密钥算法,我们让“隔壁王叔叔”传递了秘钥。

中间人攻击

上面几步还是不够的,比如王叔叔在交换秘钥的过程中做了手脚呢?

如何做手脚?看下图:

  1. 王叔叔自己生成一个公私钥,和明明以及丽丽交换。
  2. 王叔叔冒充丽丽把自己的公钥发给明明。
  3. 明明用王叔叔的公钥对信件加密。
  4. 王叔叔用自己的私钥解密就可以看到明明给丽丽的邮件。
  5. 王叔叔冒充明明把自己的公钥发给丽丽。
  6. 丽丽用王叔叔的公钥对信件加密。
  7. 王叔叔用自己的私钥解密就可以看到丽丽给明明内容。

那么明明如何知道王叔叔给的公钥就是丽丽的公钥呢?那么就引入了数字证书

数字证书

概念介绍

那么王叔叔要让明明相信他给的公钥就是丽丽的公钥,那么他可以开一个证明,比如找权威机构“敏捷的水”给开个介绍信,介绍信上给加个公章。那么这里的介绍性就是数字证书, 公章就是数字签名, 那么"敏捷的水"就是颁发证书的机构CA(Certificate Authority),也就是证书授权中心

CA CA 是“Certificate Authority”的缩写,也叫“证书授权中心”。
它是负责管理和签发证书的第三方机构,就好比例子里面的“敏捷的水”。一般来说,CA 必须是大家都信任的、认可的。因此它必须具有足够的权威性。只有明明和丽丽都信任的人才能来证明,对吧?

CA证书: CA 证书,就是CA颁发的证书。

证书之间的信任关系: 用一个证书来证明另一个证书是真实可信。

证书信任链: 证书之间的信任关系,是可以嵌套的。比如,A 信任 A1,A1 信任 A2,A2 信任 A3......,这就是证书的信任链。只要你信任链上的第一个证书,那后续的证书,都是可以信任的。

根证书(Root Certificate): 下图,处于最顶上的树根位置的那个证书,就是“根证书”。除了根证书,其它证书都要依靠上一级的证书来证明自己。那谁来证明“根证书”?根证书自己证明自己,这时候我们用户就需要自己选择是否相信某个根证书。

根证书是整个证书体系安全的根本。如果某个证书体系中,根证书不再可信了,那么所有被根证书所信任的其它证书,也就不再可信了。  

证书内容

我们看一下亚马逊的证书,当我们点击浏览器左边绿色的锁时,我们可以看到如下的证书。

我们挑重点的解释一下

  • Issuer (证书的发布机构)
    指出是什么机构发布的这个证书,也就是指明这个证书是哪个公司创建的(只是创建证书,不是指证书的使用者)。对于上面的这个证书来说,就是指"Symantec Corporation"这个机构。

  • Not valid before, Not valid after (证书的有效期)

  • Public key (公钥)

这个我们在前面介绍公钥密码体制时介绍过,公钥是用来对消息进行加密的。
  • Subject (主题)

这个证书是发布给谁的,或者说证书的所有者,一般是某个人或者某个公司名称、机构的名称、公司网站的网址等。

  • Signature algorithm (签名所使用的算法)

就是指的这个数字证书的数字签名所使用的加密算法,这样就可以使用证书发布机构的证书里面的公钥,根据这个算法对指纹进行解密,指纹的加密结果就是数字签名。

  • Thumbprint, Thumbprint algorithm (指纹以及指纹算法)

这个是用来保证证书的完整性的,也就是说确保证书没有被修改过,其原理就是在发布证书时,发布者根据指纹算法(一个hash算法)计算整个证书的hash值(指纹)并和证书放在一起,使用者在打开证书时,自己也根据指纹算法计算一下证书的hash值(指纹),如果两者一致,就说明证书没有被修改过,因为证书的内容被修改后,根据证书的内容计算的出的hash值(指纹)是会变化的。 注意,这个指纹会使用CA这个证书机构的私钥用签名算法(Signature algorithm)加密后和证书放在一起,只有用CA的公钥才能解开这个签名。

证书是如何保证身份认证的

申请证书:

  1. Amazon.com 向Symantec 公司(CA) 申请证书。
  2. Symantec(CA) 生成一对公钥A和私钥B。
  3. Symantec(CA) 有自己的公钥C和私钥D。
  4. Symantec(CA) 把Issuer,公钥A,Subject(一般是网站的域名),Valid from,Valid to等信息以明文的形式写到证书里面,然后用一个指纹算法(SHA1或者MD5
    )计算出这些数字证书内容的一个指纹(摘要),并把指纹和指纹算法用自己的私钥D进行加密,然后和证书的内容一起发给Amazon.com。
  5. Symantec(CA) 把私钥B给Amazon.com.

如何使用证书

  1. 用户访问amazon.com 这个网站
  2. amazon.com 把证书发给用户
  3. 浏览器读取证书。
  4. 浏览器发现证书机构是Symantec,然后会在操作系统中受信任的发布机构的证书中去找Symantec的证书,如果找不到,那说明证书的发布机构是个假的,或者不是被权威机构认证的,证书可能有问题,程序会给出一个错误信息。
  5. 如果在系统中找到了Symantec的证书,那么应用程序就会从证书中取出Symantec的公钥C,然后对amzon.com公司的证书里面的指纹和指纹算法用这个公钥C进行解密,然后使用这个指纹算法计算amazon.com证书的指纹,将这个计算的指纹与放在证书中的指纹对比,如果一致,说明amazon.com的证书肯定没有被修改过并且证书是Symantec发布的,证书中的公钥肯定是amazon.com的公钥A, 然后我们就可以用这个公钥A和amazon.com进行通信,因为只有amazon.com 有私钥B, 所以只有amazon.com才能解开信息。

注意 权威机构的证书都是内置在操作系统里的。

由此可见,一个证书受不受信任,那就要看你要不要添加到操作系统里,权威的认证机构的证书都内置在操作系统里的。

另外,我们自己也可以制作自签名的证书,但是需要别人认可你,这个在企业内部或者开发阶段是可以,我们可以自己制作一个证书添加到操作系统里。

那么,问题来了,当你访问https://www.12306.cn 时,你就会得到下面的结果

这是为什么呢?

我相信你看完本文应该清楚,那是因为12306 自己给自己发了个证书,而这个证书默认是没有被操作系统信任,

但是当我把根证书添加到操作系统后,依然是https://www.12306.cn 不行,然后我发现是证书对应的域名不对,证书对应的域名是https://kyfw.12306.cn 访问这个域名后,虽然证书验证通过,但是浏览器的锁还是没有变绿

为什么呢? 看提示,是因为12306使用了一个比较弱的机密算法(This site uses a weak security configuration (SHA-1 signatures), so your connection may not be private.),我猜他们是为了性能??

但是,就算浏览器地址栏的锁不能变绿,我们还得订票不是吗?

我觉得12306可能需要一个操作系统内置的认证机构来发一个证书,不然普通的用户根本不知道怎么安装证书,如果不使用https,那么安全性如何得到保证呢?

最后

回到开头的例子,明明和丽丽可以找一个权威机构来发一个证书,而且自己都内置了这个权威机构的证书。当王叔叔把丽丽的证书给明明时,明明就可以知道证书是不丽丽给的,因此就可以确定证书里的公钥是否是丽丽的,如果可以确定是丽丽的,那么就可以确保加密的内容只有丽丽可以解开,因为只有丽丽有对应的私钥。