数字证书和 CA
综合使用对称加密、非对称加密和摘要算法,我们已经实现了安全的四大特性,是不是已经完美了呢?
不是的,这里还有一个“公钥的信任”问题。
因为谁都可以发布公钥,我们还缺少防止黑客伪造公钥的手段,也就是说,怎么来判断这个公钥就是你或者某宝的公钥呢?
http://www.ruanyifeng.com/blog/2011/08/what_is_a_digital_signature.html
1.zfb 生成自己的公钥,私钥 ,公钥挂在网站上任人下载
2.小明下载了 zfb公钥,利用这个公钥 加密一段信息 data1(生成订单请求)为data1_enc 发送给zfb
3.zfb到加密信息data1_enc 用自己的私钥解开为data1
处理相关数据后 计算出要处理的业务数据data2(通知小明这个订单的支付情况),
用hash算法对data2生成摘要data2_digest
用自己的私钥加密摘要加密为 data2_digest_enc 即为数字签名signature
然后把data2+data2_digest_enc 发送给小明
4.小明收到data2+data2_digest_enc,用zfb的公钥解密data2_digest_enc
解开为data2_digest由此证明,信息是zfb发给自己的
然后对data2使用hash函数得到的结果与data2_disget比较,如果1致说明信息是完整的没有被篡改过
-------------------------------------------------------------
但是有1天小明被小灰把他之前获取的zfb公钥偷偷替换为小灰自己的公钥了
(也有可能是小灰把支付宝网站攻击了换成自己的公钥,然后小明去下载其实下载的是小灰的公钥而不是zfb的)
小明这边有人(其实就是小灰)下单后把数据用小灰的公钥加密,发给zfb,
当然支付宝用自己的私钥解不开,
小灰途中获取到小明发给支付宝的数据,用自己的私钥解密了,
在没扣款的情况下,通知小明支付成功,小明发货后,发现账户里没收到这笔订单的钱
-------------------------------------------------------------------------
小明发现异常后,决定找信任机构CA,让zfb带着他的公钥去CA 让CA为他做公钥认证
CA用自己的私钥把zfb的公钥和一些他的其它信息加密
生成数字证书
之后zfb给小明发消息时 连带他的数字证书一起发过去
小明收到消息后,用CA的公钥解开证书里的信息获取到zfb真实的公钥
现在唯一的问题就是CA是可信的
我们可以用类似密钥交换的方法来解决公钥认证问题,用别的私钥来给公钥签名,显然,这又会陷入“无穷递归”。但这次实在是“没招”了,要终结这个“死循环”,就必须引入“外力”,找一个公认的可信第三方,让它作为“信任的起点,递归的终点”,构建起公钥的信任链。这个“第三方”就是我们常说的 CA(Certificate Authority,证书认证机构)
它就像网络世界里的公安局、教育部、公证中心,具有极高的可信度,由它来给各个公钥签名,用自身的信誉来保证公钥无法伪造,是可信的。
CA 对公钥的签名认证也是有格式的,不是简单地把公钥绑定在持有者身份上就完事了,还要包含序列号、用途、颁发者、有效时间等等,把这些打成一个包再签名,完整地证明公钥关联的各种信息,形成“数字证书”(Certificate)。
知名的 CA 全世界就那么几家,比如 DigiCert、VeriSign、Entrust、Let’s Encrypt 等,它们签发的证书分 DV、OV、EV 三种,区别在于可信程度。DV 是最低的,只是域名级别的可信,背后是谁不知道。EV 是最高的,经过了法律和审计的严格核查,可以证明网站拥有者的身份(在浏览器地址栏会显示出公司的名字,例如 Apple、GitHub 的网站)。
不过,CA 怎么证明自己呢?这还是信任链的问题。
小一点的 CA 可以让大 CA 签名认证,但链条的最后,也就是 Root CA,就只能自己证明自己了,这个就叫“自签名证书”(Self-Signed Certificate)或者“根证书”(Root Certificate)。你必须相信,否则整个证书信任链就走不下去了
有了这个证书体系,操作系统和浏览器都内置了各大 CA 的根证书,上网的时候只要服务器发过来它的证书,就可以验证证书里的签名,顺着证书链(Certificate Chain)一层层地验证,直到找到根证书,就能够确定证书是可信的,从而里面的公钥也是可信的。
实验环境里使用的证书是“野路子”的自签名证书(在 Linux 上用 OpenSSL 命令行签发),肯定是不会被浏览器所信任的,所以用 Chrome 访问时就会显示成红色,标记为不安全。但你只要把它安装进系统的根证书存储区里,让它作为信任链的根,就不会再有危险警告。
证书体系的弱点
证书体系(PKI,Public Key Infrastructure)虽然是目前整个网络世界的安全基础设施,但绝对的安全是不存在的,它也有弱点,还是关键的“信任”二字。
如果 CA 失误或者被欺骗,签发了错误的证书,虽然证书是真的,可它代表的网站却是假的。
还有一种更危险的情况,CA 被黑客攻陷,或者 CA 有恶意,因为它(即根证书)是信任的源头,整个信任链里的所有证书也就都不可信了。
这两种事情并不是“耸人听闻”,都曾经实际出现过。所以,需要再给证书体系打上一些补丁。
针对第一种,开发出了 CRL(证书吊销列表,Certificate revocation list)和 OCSP(在线证书状态协议,Online Certificate Status Protocol),及时废止有问题的证书。
对于第二种,因为涉及的证书太多,就只能操作系统或者浏览器从根上“下狠手”了,撤销对 CA 的信任,列入“黑名单”,这样它颁发的所有证书就都会被认为是不安全的
- 摘要算法用来实现完整性,能够为数据生成独一无二的“指纹”,常用的算法是 SHA-2
- 数字签名是私钥对摘要的加密,可以由公钥解密后验证,实现身份认证和不可否认
- 公钥的分发需要使用数字证书,必须由 CA 的信任链来验证,否则就是不可信的
- 作为信任链的源头 CA 有时也会不可信,解决办法有 CRL、OCSP,还有终止信任
保密性:靠混合加密解决,非对称加密实现对称加密秘钥传递,对称加密实现内容加密。
完整性:靠摘要算法解决。
身份认证:靠数字证书解决,数字证书因为CA机构的信任变成一个完整信任链条,从而实现通过数字证书证明了对方真实身份,但注意身份真实也可能是挂羊头卖狗肉,是一个坏人,所以,有了CRL、OCSP,还有终止信任。
不可否认:靠数字签名解决,内容摘要算法得到摘要,私钥加密摘要,对方使用对应公钥解密,得到摘要,再和自己得到的服务器提供的原文摘要对比,一致说明这个内容就是原服务器提供的,由证书说明了服务器的身份。
服务器返回证书链(不包括根证书,根证书预置在浏览器中),
然后浏览器就可以使用信任的根证书(根公钥)解析证书链的根证书得到一级证书的公钥+摘要验签,
然后拿一级证书的公钥解密一级证书拿到二级证书的公钥和摘要验签,
再然后拿二级证书的公钥解密二级证书得到服务器的公钥和摘要验签,验证过程就结束了
数字签名和数字证书只用于TSL/SSL的握手阶段,主要是保证服务器的公钥能够正确地传给浏览器(不被中间人伪装发送假的公钥)
具体流程大概是:
- 1.服务器去CA机构申请证书,证书中包含了要发给客户端的公钥、签发者、到期时间等等信息。
如果这样简单地把证书发给浏览器,中间人可以轻松地修改成自己的公钥,之后的通信就是不安全的了
于是需要一定的加密手段,这里的做法就是使用数字签名:将证书的信息利用摘要算法计算出摘要之后,用CA的秘钥进行加密,生成数字签名
- 2.服务器将数字证书和数字签名一起发给浏览器,因为有数字签名,所以数字证书无法被中间人做修改(修改之后生成的数字签名和原数字签名不一致了),浏览器拿到数字证书之后,去本地的信任机构中查询到对应的机构,利用其公钥解密数字签名,验证证书是否有被修改过。
这一步就保证了浏览器获取到的公钥一定是正确的。 - 3.公钥正确地传给浏览器之后,接着就是协商对称加密的密钥,然后通信等等