透视HTTP协议-HTTPS、对称加密与非对称加密&数字签名与证书

2,730 阅读17分钟

HTTPS

为什么要有HTTPS,简单的回答是“因为HTTP不安全”。

什么是安全?

通常认为,如果通信过程中具备了四个特性,就可以认为是“安全”的,这四个特性是:机密性、完整性、身份认证和不可否认。

  • 机密性(Secrecy/Confidentiality)是指对数据的”保密“,只能由可信的人访问,对其他人是不可见的”秘密“,简单来说就是不能让不相关的人看到不该看的东西。
  • 完整性(Integrity,也叫一致性)是指数据在传输过程中没有被篡改,不多也不少,”完完整整“地保持着原状。
  • 身份认证(Authentication)是指确认对方的真实身份,也就是”证明你真的是你“,保证消息只能发送给可信的人。
  • 不可否认(Non-repudiation/Undeniable),也叫不可抵赖,意思是不能否认已经发生过的行为,不能”说话不算数“”耍赖皮“。

什么是HTTPS?

HTTPS为HTTP增加了刚才所说的四大安全特性。

HTTPS其实是一个”非常简单“的协议,RFC文档很小,只有短短的7页,里面规定了新的协议名”https“,默认端口号443,至于其他的什么请求-应答模式、报文结构、请求方法、URI、头字段、连接管理等等都完全沿用HTTP,没有任何新的东西。

那HTTPS怎么做到机密性、完整性这些安全特性的呢?

秘密就在于HTTPS名字里的”S“,它把HTTP下层的传输协议由TCP/IP换成了SSL/TLS,由”HTTP over TCP/IP“变成了”HTTP over SSL/TLS“,让HTTP运行在了安全的SSL/TLS协议上,收发报文不再使用Socket API,而是调用专门的安全接口。

SSL/TLS

SSL即安全套接层(Secure Sockets Layer),在OSI模型中处于第5层(会话层),由网景公司于1994年发明,有v2和v3两个版本,而v1因为有严重的缺陷从未公开过。

SSL发展到v3时已经证明了它自身是一个非常好的安全通信协议,于是互联网工程组IETF在1999年把它改名为TLS(传输层安全,Transport Layer Security),正式标准化,版本号从1.0重新算起,所以TLS1.0实际上就是SSLv3.1。

到今天TLS已经发展出了三个版本,分别是2006年的1.1、2008年的1.2和2018年的1.3,每个新版本都紧跟密码学的发展和互联网的现状,持续强化安全和性能,已经成为了信息安全领域中的权威标准。

目前应用的最广泛的 TLS 是 1.2,而之前的协议(TLS1.1/1.0、SSLv3/v2)都已经被认为是不安全的,各大浏览器即将在 2020 年左右停止支持,所以接下来的讲解都针对的是 TLS1.2。

TLS由记录协议、握手协议、警告协议、变更密码规范协议、扩展协议等几个子协议组成,综合使用了对称加密、非对称加密、身份认证等许多密码学前沿技术。

浏览器和服务器在使用TLS建立连接时需要选择一组恰当的加密算法来实现安全通信,这些算法的组合被称为”密码套件“(cipher suite,也叫加密套件)。TLS的密码套件命名非常规范,格式很固定。基本的形式是”密钥交换算法+签名算法+对称加密算法+摘要算法“。例如“ECDHE-RSA-AES256-GCM-SHA384”的意思是“握手时使用 ECDHE 算法进行密钥交换,用 RSA 签名和身份认证,握手后的通信使用 AES 对称算法,密钥长度 256 位,分组模式是 GCM,摘要算法 SHA384 用于消息认证和产生随机数。”

OpenSSL

说到TLS,就不能不谈到OpenSSL,它是一个著名的开源密码学程序库和工具包,几乎支持所有公开的加密算法和协议,已经成为事实上的标准,许多应用软件都会使用它作为底层库来实现TLS功能,包括常用的Web服务器Apache、Nginx等。OpenSSL是著名的开源密码学工具包,是SSL/TLS的具体实现。

对称加密和非对称加密

实现机密性最常用的手段是”加密“(encrypt),就是把消息用某种方式转换成谁也看不懂的乱码,只有掌握特殊”钥匙”的人才能再转换出原始文本。

这里的“钥匙”就叫做“密钥”(key),加密前的消息叫“明文”(plain text/clear text),加密后的乱码叫“密文”(cipher text),使用密钥还原明文的过程叫“解密”(decrypt),是加密的反操作,加密解密的操作过程就是“加密算法”。

所有的加密算法都是公开的,任何人都可以去分析研究,而算法使用的“密钥”则必须保密。由于HTTPS、TLS都运行在计算机上,所以“密钥”就是一长串的数字,但约定俗成的度量单是”位“(bit),而不是”字节“(byte)。比如,说密钥长度是128,就是16字节的二进制串,密钥长度1024,就是128字节的二进制串。

对称加密

对称加密就是指加密和解密时使用的密钥是同一个,是”对称“的。只要保证了密钥的安全,那整个通信过程就可以说具有了机密性。

TLS里有非常多的对称加密算法可供选择,比如RC4、DES、3DES、AES、ChaCha20等,但前三种算法都被认为是不安全的,通常都禁止使用,目前常用的只有AES和ChaCha20。

AES的意思是”高级加密标准“(Advanced Encryption Standard),密钥长度可以是128、192或256。它是DES算法的替代者,安全强度很高,性能也很好,而且有的硬件还会做特殊优化,所以非常流行,是应用最广泛的对称加密算法。

ChaCha20是Google设计的另一种加密算法,密钥长度固定为256位,纯软件运行性能要超过AES,曾经在移动客户端上比较流行,但ARMv8之后也加入了AES硬件优化,所以现在不再具有明显的优势,但仍然算得上是一个不错的算法。

加密分组模式

对称算法还有一个”分组模式“的概念,它可以让算法用固定长度的密钥加密任意长度的明文,把小秘密(密钥)转化为大秘密(即密文)。

最新的分组模式被称为AEAD(Authenticated Encryption ),在加密的同时增加了认证的功能,常用的是GCM、CCM和Poly1305。

把上面这些组合起来,就可以得到TLS密码套件中定义的对称加密算法。

比如,AES128-GCM,意思是密钥长度为128位的AES算法,使用的分组模式是GCM;ChaCha20-Poly1305的意思是ChaCha20算法,使用的分组模式是Poly1305。

非对称加密

对称加密看上去好像完美地实现了机密性,但其中有一个很大的问题:如何把密钥安全地传递给对方,术语叫”密钥交换“。

所以,就出现了非对称加密(也叫公钥加密算法)。 它有两个密钥,一个叫”公钥“(public key),一个叫”私钥“(private key)。两个密钥是不同的,”不对称“,公钥可以公开给任何人使用,而私钥必须严格保密。

公钥和私钥有个特别的”单向“性,虽然都可以用来加密解密,但公钥加密后只能用私钥解密,反过来,私钥加密后也只能用公钥解密。

非对称加密可以解决”密钥交换“的问题。网站秘密保管私钥,在网上任意分发公钥,你想要登录网站只要用公钥加密就行了,密文只能由私钥持有者才能解密。

非对称加密算法的设计要比对称算法难的多,在TLS里只有很少的几种,比如DH、DSA、RSA、ECC等。

RSA可能是其中最著名的一个,几乎可以说是非对称加密的代名词,它的安全性基于”整数分解“的数学难题,使用两个超大素数的乘积作为生成密钥的材料,想要从公钥推算出私钥是非常困难的。

ECC(Elliptic Curve Cryptography)是非对称加密里的“后起之秀”,它基于“椭圆曲线离散对数”的数学难题,使用特定的曲线方程和基点生成公钥和私钥,子算法 ECDHE 用于密钥交换,ECDSA 用于数字签名。

比起 RSA,ECC 在安全强度和性能上都有明显的优势。160 位的 ECC 相当于 1024 位的 RSA,而 224 位的 ECC 则相当于 2048 位的 RSA。因为密钥短,所以相应的计算量、消耗的内存和带宽也就少,加密解密的性能就上去了,对于现在的移动互联网非常有吸引力。

混合加密

非对称加密虽然没有”密钥交换“的问题,但因为它们都是基于复杂的数学难题,运算速度很慢,即使是ECC也要比AES差上好几个数量级。如果仅使用非对称加密,虽然保证了安全,但通信速度过慢没有实用性。

混合加密方式就是把对称加密和非对称加密结合起来呢,两者互相取长补短,即能高效地加密解密,又能安全地密钥交换:

在通信刚开始的时候使用非对称算法,比如RSA、ECDHE,首先解决密钥交换的问题。

然后用随机数产生对称算法使用的”会话密钥“(session key),再用公钥加密。因为会话密钥很短,通常只有16字节或32字节,所以慢一点也无所谓。

对方拿到密文后用私钥解密,取出会话密钥。这样,双方就实现了对称密钥的安全交换,后续就不再使用非对称加密,全都使用对称加密。

数字签名和证书

加密实现了机密性,但仍无法保证完整性和身份认证等特性

摘要算法

实现完整性的手段主要是摘要算法(Digest Algorithm),也就是常说的散列函数、哈希函数(Hash Function)。

你可以把摘要算法近似地理解成一种特殊的压缩算法,它能够把任意长度的数据”压缩“成固定长度、而且独一无二的”摘要“字符串,就好像是给这段数据生成了一个数字”指纹“。也可以把摘要算法理解成特殊的”单向“加密算法,它只有算法,没有密钥,加密后的数据无法解密,不能从摘要逆推出原文。

因为摘要算法对输入具有”单向性“和”雪崩效应“,输入的微小不同会导致输出的剧烈变化,所以也被TLS用来生成伪随机数(PRF,pseudo random function)。

MD5(Message-Digest 5)、SHA-1(Secure Hash Algorithm 1)就是最常用的两个摘要算法,能够生成16字节和20字节长度的数字摘要。但这两个算法的安全强度比较低,不够安全,在TLS里已经被禁止使用了。

目前TLS推荐使用的是SHA-1的后继者:SHA-2。SHA-2实际上是一系列摘要算法的统称,总共有6种,常用的有SHA224、SHA256、SHA384,分别能够生成28字节、32字节、48字节的摘要。

完整性

摘要算法保证了”数字摘要“和原文是完全等价的。所以,我们只要在原文后附上它的摘要,就能够保证数据的完整性。

不过摘要算法不具有机密性,如果明文传输,那么黑客可以修改消息后把摘要也一起改了。所以,真正的完整性必须要建立在机密性之上,在混合加密系统里用会话密钥加密消息和摘要,这样黑客就无法得知明文了。

这有个术语,叫哈希消息认证码(HMAC)。

数字签名

加密算法结合摘要算法,我们的通信过程可以说是比较安全了。但这里还是有漏洞,就是通信的两个端点(endpoint)。黑客可以伪装网站来窃取消息,也可以伪装为你,向网站发送支付、转账等消息。

那么,在数字世界里如何证明你的身份呢?由于非对称加密里的”私钥“只能由本人持有,那么使用私钥再加上摘要算法,就能够实现”数字签名“,同时实现”身份认证“和”不可否认“。

数字签名的原理其实很简单,就是把公钥私钥的用法反过来,之前是公钥加密,私钥解密,现在是私钥加密、公钥解密。但又因为非对称加密效率太低,所以私钥只加密原文的摘要,这样运算量就小的多,而且得到的数字签名也很小,方便保管和传输。

签名和公钥一样完全公开,任何人都可以获取。但这个签名只有用私钥对应的公钥才能解开,拿到摘要后,再比对原文验证完整性,就可以像签署文件一样证明消息确实是你发的。

刚才的这两个行为也有专用术语,叫做”签名“和”验签“。

只要你和网站互相交换公钥,就可以用”签名“和”验签“来确认消息的真实性,因为私钥保密,黑客不能伪造签名,就能够保证通信双方的身份。

数字证书和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)一层层地验证,直到找到根证书,就可以确定证书是可信的,从而里面的公钥可以可信的。

证书体系的弱点

证书体系(PKI,Public Key Infrastructure)虽然是目前整个网络世界的安全基础设施,但绝对的安全是不存在的,它也有弱点,还是关键的”信任“二字。

如果CA失误或者被欺骗,签发了错误的证书,虽然证书是真的,可它代表的网站却是假的。

还有一种更危险的情况,CA被黑客攻陷,或者CA有恶意,因为它(即根证书)是信任的源头,整个信任链里的所有证书也就都不可信了。

所以,需要再给证书体系打上一些补丁。

针对第一种,开发出了CRL(证书吊销列表,Certificate revocation list)和OCSP(在线证书状态协议,Online Certificate Status Protocol),及时废止有问题的证书。

对于第二种,因为涉及的证书太多,就只能操作系统或者浏览器从根上”下狠手“了,撤销对CA的信任,列入”黑名单“,这样它颁发的所有证书就都会被认为是不安全的。

Q&A

Q:你能说出 HTTPS 与 HTTP 有哪些区别吗?

A:https与http协议相比,最重要的是增加安全性,这种安全性的实现主要是依赖于两个协议底层依赖的协议是不同的,https在传输的应用层与传输层协议之间增加了ssl/tls,这就使得http在固有协议之上增加一层专用用于处理数据安全的工具。另外http和https的端口号不同,http端口号是80,https端口号是443

Q:你知道有哪些方法能够实现机密性、完整性等安全特性呢?

A:机密性由对称加密AES保证,完整性由SHA384摘要算法保证,身份认证和不可否认由RSA非对称加密保证

Q:加密算法中“密钥”的名字很形象,你能试着用现实中的锁和钥匙来比喻一下吗?

A:没有锁的大门是不安全的,谁想进就进,谁想拿的啥就拿点啥,就好像在网络中奔跑的HTTP报文。 为了安全性需要给明文加密,同样为了安全性需要给大门上锁,加密的明文变成了密文,没有没有解密是看不懂的,没有钥匙的人打不开锁是进不了门的。 一把钥匙一把锁,其他钥匙开不了,这就是对称加密。一把钥匙锁门,N把其他的钥匙都能打开,这就是非对称加密,那那把锁门的钥匙有啥用呢?可以证明这个院子是我的,证明锁是我上的。

Q:在混合加密中用到了公钥加密,因为只能由私钥解密。那么反过来,私钥加密后任何人都可以用公钥解密,这有什么用呢?

A:公钥加密私钥解密,私钥签名公钥验签。

Q:为什么公钥能够建立信任链,用对称加密算法里的对称密钥行不行呢?

A: 非加密算法需要公开公钥从而让客户端能解密。如果用对称加密,加密秘钥公开,就达不到加密效果了

Q:假设有一个三级的证书体系(Root CA=> 一级 CA=> 二级 CA),你能详细解释一下证书信任链的验证过程吗?

A:客户端发现当前网站的证书是二级CA,在可信任签发机构中找不到,就会去拿二级CA的数字证书的签发机构去做检查,发现它是一级CA,也不在可信任签发机构中,再找一级CA的数字证书的签发机构,发现是受信任的ROOT CA,至此完成验证。如果到最后一层CA都不受信任,就会警告用户