SSL与数字证书
by zhlmmc
<[if !supportLists]>第四章 <[endif]>数字证书
上面讲了这么多都是前戏,现在该到主题了。前面提到的认证(Authentication),说现实生活中可以用身份证和护照来证明身份,那么在虚拟世界里,数字证书就是身份证。和现实生活不同的是,并不是每个上网的用户都有数字证书的,往往只有当一个人需要证明自己的身份的时候才需要用到数字证书。那么什么时候需要证明自己的身份呢?普通用户一般是不需要的,网站并不关心是谁访问了网站,现在的网站只关心流量啊~反过来,网站就需要证明自己的身份了。比如你想要提交信用卡信息给预定航班的网站,那么你如何确定你正在访问的网站就是你所想要访问的那个呢?现在钓鱼网站很多的。比如你想访问的是“www.ctrip.com”,但其实你访问的是“www.otrip.com”,所以在提交自己的信息之前你需要验证一下网站的身份,要求网站出示数字证书。一般正常的网站都会主动出示自己的数字证书。由于证书在网页浏览中最为常见,所以我下面举的例子都是基于浏览器的。
第一节 数字证书的构成
我们的身份证是由公安机关颁发的,并加有很多防伪技术,不能伪造(或者说很难)。同样的,数字证书也有专门的发证机关(Certificate Authority,简称CA,其实是一些商业公司啦)。比较常见的发证机关是VeriSign。数字证书的发证机关会对自己发放的证书加上自己的数字签名,以保证证书不能被伪造。那数字证书到底包含了些什么呢?
<[if !supportLists]>1. <[endif]>持有者姓名(Common Name)
<[if !supportLists]>2. <[endif]>发证机关(Issuer)
<[if !supportLists]>3. <[endif]>有效日期(Validity)
<[if !supportLists]>4. <[endif]>证书持有人的公钥(Subject’s Public Key Info)
<[if !supportLists]>5. <[endif]>扩展信息 (Extension)
<[if !supportLists]>6. <[endif]>用发证机关对该证书的数字签名(Certificate Signature)
基本信息就这些了(这些信息会在后面的章节有所解释),为了更清晰的说明问题,来几张截图:
图1:数字证书的基本内容


图3:数字证书详细内容
这几张截图都是我从Firefox里面拷贝出来的,这张证书已经过期了,不过不影响理解。从图2我们可以看到,Certificate(证书)和Signature(签名)是分开的,但其实这个Signature也是证书的一部分。可以这么理解,数字证书包含证书主体和数字签名。证书中的签名是对证书主体的签名。
第二节 如何验证数字证书?
好了,现在我们有了虚拟世界的身份证了,那如何使用呢?和现实生活中检查身份证一样,包含三个步骤:
<[if !supportLists]>1. <[endif]>检查身份证防伪标记

图4:Firefox内置的发证机关的数字证书
虽然Firefox内置的是数字证书,但是有数字证书就有公钥,所以是一样的。当浏览器拿到一个数字证书,先看发证机关,然后找到相应的发证机关的证书,获得发证机关的公钥,用此公钥解密被加密的MD5,这样就获得了此证书的MD5值,我们称它为Hash1。然后浏览器用MD5算法对此证书重新计算一遍MD5,获得Hash2。然后比较Hash1和Hash2是否相等。如果相等就证明这张证书是由发证机关颁发的,并且没有被篡改过。回过头去看看上面讲Hash和MD5的部分,你应该能想明白为什么的。
<[if !supportLists]>1. <[endif]>核对相貌
在现实生活中,你的身份证只有一张,你应该好好保管不被别人拿到。但难免钱包丢了,身份证跟着遭殃。所以我们在验证完身份证的真假之后我们要验证持证的人,和身份证上所声明的那个人是不是同一个,我们往往通过比较相貌来辨别。那在虚拟世界又是怎样的呢?你应该已经发现,任何人都可以拥有你的证书就像我们装的Firefox就有很多发证机关的证书。所以核对持有证书人的身份就很重要了。这就要依赖证书里面包含的公钥了。此公钥是这张证书所有者的公钥(注意,我这里指的是所有者,而不是持有者!),我们用此公钥加密一段信息发送给证书的持有者,如果持有者能发送回(可以是被私钥加密,也可以是明文,没有关系)被加密的这段信息的话就证明该持有者拥有该证书对应的私钥,也就是说,该持有者就是该证书的所有者。
<[if !supportLists]>2. <[endif]>核对姓名
最后一步,也是最重要的一步。看清楚了,站在你面前的人的名字和登记在册的名字一样。举个例子,我拿着护照去机场登机,护照和人都没有问题,问题是我根本没有买机票。如果机场工作人员只核对了前面两步的话,我就可以登机了,岂不是很荒谬?同样的,在虚拟世界,比如那个“ctrip”的例子,你拿到了一个证书,并且验证没有问题,但是证书上的Common Name明明写的是“otrip”,你还继续吗?
第三节 数字证书的级联(Certificate Chain)
根据上述讨论,我们可以知道,所有数字证书都是基于另外一张默认为可信任(浏览器内置)的数字证书的。也就是说,我们必须用一张已知合法的数字证书去验证另外一张未知的数字证书。第二节提到的发证机关的数字证书就是默认为可信任的。事实上,发证机关的证书是自己签发给自己的,验证没有意义。因为这些证书是人工配置在我们电脑上的,所以默认为安全的。这些证书称为“根证书”。

图5:级联的数字证书
这里的“www.paypal.com”是由二级代理“VeriSign Class 3 Extended Validation SSL SGC CA”签发的,而二级代理的证书又是由一级代理“VeriSign Class 3 Public Primary Certification Authority – G
图6:级联证书的验证流程
需要注意的是,这是一个递归过程,所以这里的返回只是返回到上层递归。对于我们这个例子中的级联证书的验证可能是这样的:

图7:级联证书验证流程示例
这个过程看起来没有什么问题。但是仔细一想,发现有一个大问题。任何一个拥有合法证书的人都可以给别人签发证书了,不就是在这个继承关系上面多加一层吗?荒凉大梦!事情没那么简单啦~能够签发证书的叫CA,不管是否是代理,它都是CA,只有CA的证书才能拥有下级,那如何判断一张证书是否是CA呢?还记得我们在第一节讲过的证书中包含的扩展信息吗?这里可以放很多东西,包括这张证书的合法用途,如下图所示:



图8:证书的扩展信息
这里我们很清楚的可以看到用户证书是不能作为CA来用的,白纸黑字写着“Is not a Certificate Authority”。而CA的证书也有不同的权限。“Maximum number of intermediate CAs”说明了这个CA的权限大小。如果这个数字是0(比如这里的二级代理的证书),说明这个CA只能签发用户证书,而不能再授权其他机构为CA。如果这个数字是1,说明这个CA可以再授权一层代理,以此类推。图中没有显示根证书的Extension,因为根证书没有Extension,没有表示没有限制。在验证级联证书的时候,浏览器会检查证书的Extension,如果某个证书超范围使用了,浏览器会发出警告的。级联证书为证书的签发带来了很大的方便和灵活性。事实上我们可以看到,任何一张用户证书都应该是级联的,至少拥有一个上级证书(根证书)。所以在我们前面的例子中的“ebiz.isir.cmu.edu”这张证书是很奇怪的,不是标准的证书。
关于数字证书,我还有几点想要提一下:
<[if !supportLists]>1. <[endif]>数字证书本身不加密,加密的是数字证书的hash。数字证书加密了就很麻烦了,如何获知发证机关呢?不知道发证机关就不知道解密的公钥啊!还有,明文的数字证书可以显示数字证书的信息,即使不能验证数字证书的真伪,但是给了人为判断一个机会。
<[if !supportLists]>2. <[endif]>数字证书中的公钥可以是自己指定的,也可以是发证机关生成的。不同的发证机关可能有不同的要求。
申请证书的过程是安全的。如果申请证书的过程都不安全的话,后面的一切都面谈了。现实生活中,申请数字证书往往要求邮寄,或者电话,传真,甚至当面申请的。
心情: 挺好