上一篇:零门槛学习https–(2)https中s的秘密

上一篇我们已经把非对称加密RSA算法的原理已经摸清楚了,有了加密算法,我们就能够开始加密了。当然非对称加密还有好几种,这里我们只讨论RSA

RSA算法的局限性

在RSA的加密原理中,我们看到对明文m的要求是:

  1. m必须是整数。
  2. m必须小于n。

第一个条件很容易满足,文字可以转成arcii,而二进制文件没有小数。问题在第二个条件,通常n的选择是2048位,所以这也就意味着我们每加密一次的数据,二进制长度不得超过2048位,这个局限性就比较大了,因为 2048 / 8 = 256,也就是一次最多只能加密256 byte的东西,所以超出部分就只能分片加密了,而每次加密其实涉及到的计算量还挺大的,都是大数的幂次方计算,所以,如果在一个https请求中,完全采用RSA加密,那么客户端和服务端的计算量简直不可想象,特别是服务端,会造成用户体验异常低下。

非对称加密的解决办法

这里我们已经有了相对来说能够保证安全的方式,但是其计算量太大导致无法大规模应用,其他非对称加密的计算量同样非常大,那么,只能另寻他法了,剩下的算法就只有对称加密和摘要算法了,摘要算法不可逆,加密了之后就没法解了,肯定不适合,那么就只剩下对称加密了。

对称加密

之前我们没有直接用对称加密的原因是因为,如果对称加密的秘钥写死在客户端里面,那么很容易就被人拿到了,如果每次都随机生成,那么无法用加密的方式分发到对方手中。

结论

聪明的革命先烈们这时候就想到了,那我们用非对称加密来加密对称加密的密钥,然后用对称加密不就行了么?这样既避免了非对称加密的庞大的计算量,又能够避免对称加密的密钥被泄露,完美地解决了这个问题。

新的问题出现

上面的解决方案看起来似乎很完美,很快大家都开始实装,代码跑起来没有问题,加密解密也成功得运行了,而且当有人尝试拿到密文,也无从下手解密,突然,人们意识到一个问题:

MIM(man in the middle)中间人攻击

有个很常见的场景,假设用户A通过B的网关上网,那么A的所有流量都会经过B,也就是B能看到A的所有进出的流量,RSA在算法层面虽然没法破解,但是有人想到,RSA任然存在一个传递公钥的过程,并且这是明文的,那么就有如下场景:

1
2
3
4
5
6
7
1. A和服务器S进行通信,并且由S生成公钥和私钥,并在连接建立后,S把公钥给A。
2. 因为A经由B上网,也就是说S的公钥是经由B交给A的。
3. 这个时候,B可以伪装成服务端S1接受A的连接,并生成自己的公钥和私钥,再伪装成客户端C向S发送请求。
4. S把公钥给了B,B再把自己的公钥给A,所以就变成了:
5. A和B通信,B再和S通信,A虽然加密了,但是是用的B的公钥,所以B有私钥能够解密,然后再用S的公钥加密,发送给S,S任然能解密。
6. 整个过程神不知鬼不觉,B就悄悄查看了所有的通信内容
7. 甚至有可能在A申请把自己网银里面的钱转给D时,B也可以偷偷改成自己的,S认为这是A发出的,就把钱转给了B。

问题的原因

显然,人们深刻地认识到,因为数据的可复制性,无论是什么算法,都无法改变数据会被中间人窥探甚至修改的问题(以后量子加密的出现或许能解决这个问题,因为量子一旦被观测,叠加态就会坍缩,接收者就能够知道自己接收到的数据是否被窥探了)。

问题源于生活,那么在生活中一定可以找到答案。你把钱给了银行,银行给你承诺,你想用钱的时候一定会还给你,银行在这里承担了一个被所有人信任的角色,在计算机里面其实也一样,于是,人们为计算机通信引入了一个第三方:CA(Certificate Authority)。

数字证书

CA又称为证书颁发机构,主要用于颁发数字证书,用一个无法篡改的数字证书来表明身份,防止数据在通讯过程中被篡改和窥探,数字证书通常分为以下几种:

  1. 个人身份证书。
  2. 企业或机构身份证书。
  3. 支付网关证书。
  4. 服务器证书。
  5. 企业或机构代码签名证书。
  6. 安全电子邮件证书。
  7. 个人代码签名证书。

数字证书如何生成?

  1. 首先,CA要生成一个自己的公钥和私钥,这里通常只生成一次就行了。
  2. 有人向CA申请证书,把自己的各种身份信息,营业执照,域名,到期时间等等的信息发给CA。
  3. CA严格审核申请者的信息,申请通过后,CA为申请者生成一对公钥和私钥(也可以自己生成),把CA的签发人、地址、签发时间、过期失效时间等信息,加上申请者的基本信息以及DNS、域名、公钥等基本信息整合到一起,生成一个证书,这里的证书还未签名,仅仅是很多信息的聚合而已。
  4. 通过通用的摘要算法(通常是sha256)将信息摘要提取出来,然后用CA的私钥加密,这里因为私钥严格保存,所以别人无法伪造签名,除非拿到私钥。
  5. 把上一步计算出来的信息摘要附加到第三步生成的证书中,之后,这个证书就称为了一个被CA签名过的证书了,因为私钥被CA严格保存,所以没有人能够模仿CA的签名,这也就是签名安全的根本了。
  6. 服务端把这个证书挂到自己的服务器上去,就能够供人使用了。

以上整个过程称为:Public Key Infrastructure(PKI,公开密钥基础建设)

如何验证证书的有效性呢?

  1. 客户端向服务端发起请求,服务端返回数字证书。
  2. 客户端拿到证书之后,首先解析证书,拿到被私钥加密的摘要密文,然后再拿出证书的元数据。
  3. 用CA的公钥进行解密,CA的公钥是公开的,任何人都可以获取(会内置在操作系统里面,或者在CA的官方网站中可以获取),解密后拿到摘要的原文。
  4. 对元数据再次执行摘要算法,拿到摘要信息,然后和第三步的结果进行对比,只有当结果一致的时候,才认为证书是有效的。

整个过程可以理解为下图:

如果我们获取CA的公钥的时候,已经被替换了怎么办?

设想一下,当我们获取CA公钥的时候,已经被人替换了,这时候真正的证书反而没法解析,只有被伪造的证书才能被解析了,这里就有了证书链的概念。

证书链

通常在一个证书链中包含以下三种结构:

  1. end-user。终端用户,也就是https中真正用来加密通信的证书。
  2. intermediates。给end-user签发证书的CA的证书,主要用来校验end-user的证书是否合法的证书。
  3. root。root也是CA证书,区别在于,root证书是给intermediates签发证书的,用来校验intermediates的合法性。

证书链的签发。

  1. 首先,root自己先生成一对公钥和私钥,然后用自己的私钥给自己自签名,因为root的绝对信任。
  2. 二级CA向root申请证书,root按照上面提到的数字证书的生成方式,先给CA生成一对公钥和私钥,然后
  3. 把CA的各种信息算出摘要,再用自己的私钥加密,加上给二级CA生成的公钥,就组成了一张CA的证书。
  4. 然后有用户向二级CA申请证书时,按照这个步骤一步步签发,就形成了证书链。
  5. 证书一级一级签发,中间无法伪造,因为root证书的绝对安全,保证了整个证书链的安全。
  6. 证书链是有长度限制的,root颁发证书的时候会添加此字段,所以证书申请者无法再为别人签发证书。

CA的类型

上面提到intermediates和root都是CA证书,所以CA其实也就分为root CAs和intermediates CAs,root CAs可以认为是一个品牌,而intermediates CAs则是真正使用这个品牌生产产品的企业,举个例子:

1
2
3
4
哇哈哈母公司,拥有哇哈哈品牌,但是并没有自己的产品,做的只是给子公司授权品牌,也就是root.
子公司A,生产矿泉水,是一个intermediates.
子公司B,生产八宝粥,是一个intermediates.
子公司C,生产橙汁,也是一个intermediates.

为什么不能用root CA的私钥直接签名?

主要还是从安全性上考虑,私钥是需要放到服务器上去做签名用的,所以不可避免可能服务器会被人攻破,导致私钥泄露,所以root的私钥隔离得越远越好,如果某个intermediates的私钥被窃取了,那么用root的私钥再签发一个intermediates证书即可,不会威胁到整个root证书下所有人的安全。root CA的私钥一般锁在大金库里面,完全得物理隔离,以下是godaddy对这个的解释:

intermediate certificates are used as a stand-in for our root certificate. We use intermediate certificates as a proxy because we must keep our root certificate behind numerous layers of security, ensuring its keys are absolutely inaccessible.

root证书的获取

回到我们最初的问题,获取证书的时候就已经被替换了怎么办?这里我们只需要保证root证书的获取没有问题,那么只要其他中间证书被替换,最后校验root证书这里还是没法通过,那么如果保证root证书的获取是安全的呢?

  1. 首先,成为一个CA的一个前提是你要向微软等操作系统厂商申请加入他们的白名单,就是把自己的root证书内置在操作系统里面,随着系统的安装和升级的过程就已经被安装到操作系统里面。
  2. 浏览器等终端在验证的时候,就直接调用操作系统的接口,获取证书,用来验证,例如chrome和ie。
  3. 有些浏览器类似firefox有一套自己的证书系统,是随着安装firefox的时候,安装到本地,这样,即使操作系统的证书被篡改了,firefox依然有能力验证证书的有效性。

root证书并不会很多,目前主流的基本就只有:Symantec(VeriSign/GeoTrust)、Comodo、GoDaddy,也是被这几家垄断,签发证书躺着赚钱,所以现在也有一些公益的组织开始提供免费证书。

CRL(Certificate Revocation List)

CRL是证书吊销列表,早先的浏览器通过这种方式把这个列表缓存在本地,用以验证证书是否有效。但是因为客户端时间不可控,所以这种方式还是存在一定的风险。

OCSP协议(Online Certificate Status Protocol)

除了CRL的方式,还有一种在线证书状态协议OCSP,验证的时候会从CA直接获取验证结果,主要用于证书过期吊销等的验证,主流浏览器都已经支持,可以防止因为缓存或者客户端时间不正确导致的证书过期时间判断不准确的问题。

如何验证二级CA的证书?

浏览器和操作系统里面只内置了根证书,那么那些二级CA的证书又该如何验证呢?

这里有两种情况:

服务端没有返回中间证书

我们来看看谷歌的证书:

证书颁发机构信息访问,这一栏里面标示了此证书的证书颁发机构如何访问和验证,标红框的地址就是CA的证书下载地址,下面还有OCSP协议的验证地址。

服务端返回了中间证书

比较适用于实际情况,因为上一种情况会产生额外的http请求,访问速度就会比较慢了。

这里返回了三个证书:

证书链类似下面这样,可以自由配置:

1
2
3
4
5
6
7
8
9
-----BEGIN CERTIFICATE-----
自己的crt证书
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
父级的crt证书
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
父级的父级crt证书
-----END CERTIFICATE-----

end-user证书的类型

申请者能够申请的证书种类非常多,价格相差也很大,主要有以下几种:

  1. OV(Organization Validation SSL),以某个组织为维度签发证书,通常这都是一个公司,域名采用通配符的方式来签发,以适应组织业务的灵活发展,例如:*.tmall.com
    ,也就是任何tmall.com的三级域名都可以使用这个证书,避免重复申请。使用OV证书的网站访问时候类似下面这样:

  2. DV(Domain Validation SSL),一个域名对应一个证书,无法使用通配符,这是最便宜的证书,申请无需人工干预,不需要组织信息,因为价格便宜,由某CA最早推出来之后,很受欢迎,但是因为没有人工审核,很多犯罪网站都使用DV。

  3. EV(Extended Validation Certificate),扩展验证证书,价格最高,审核最严,也是安全性最高的证书,能够使用一些安全性更高的加密算法,例如椭圆曲线算法,访问时还能在浏览器地址栏显示绿色,并且显示组织的名称,看起来非常高大上,如下图:

总结

目前整个互联网建立在对CA信任的基础上,要是CA作恶,那么整个互联网就会混乱了。之前就有发生过有CA误签发google证书,导致google差点被中间人攻击。

至此,整个https的加密原理和安全认证机制理论知识我们都已经讲完了,我们来回顾一下:首先客户端先校验证书,从服务端证书到二级CA再到根证书,然后双方生成一个对称加密的密钥,用证书里面的公钥加密,发送给服务端,服务端用自己的私钥解密,拿到对称加密的密钥之后,双方开始通信。

这套加密系统其实适用于所有客户端和服务端的通信,所以网景公司在1994年推出浏览器时,同时推出了ssl,应用到http就变成了https。后面咱们来看看https中,ssl协议的一些具体细节。

零门槛学习https–(4)https协议详解