1. https和http有什么区别了?
HTTPS 和 HTTP 的关系
https它把http下层的传输协议由TCP/IP换成了SSL/TLS,由["HTTP over TCP/IP"] 变成了 ["HTTP over SSL/TLS"] 让HTTP 运行在了安全的SSL/TLS 协议上,收发报文不再使用[Soket API] 而是调用专门的安全接口。
https是为http增加了四大安全特性;本身是一个非常简单的协议RFC文档很小,只有短短的7页,里面规定了新的协议名“https” ,默认的端口号 “443”,至于其他的什么请求-应答模式、报文结构、请求方法、uri、连接管理等都沿用http,没有任何新的东西。
四大安全特性
[机密性]:是指对数据的“保密”,只能由可信的人访问,对其他人是不可见的秘密。
对称加密和非对称加密
[完整性]:是指数据在传输过程中没有被篡改,不多也不少,完整的保持最初请求时的状态。
摘要算法,数字签名算法
[身份认证]:是指确认对方的真实身份,保证消息只发给可信的人。
数字签名和ca认证
[不可否认]:也叫不可抵赖,意思是不可否认已经发生的行为,不能“说话不算数”。
数字签名
提炼
1. 因为http是明文传输,所以不安全容易被篡改或黑客窃听。
2. 通讯安全必须同时具备机密性、完整性、身份认证、不可否认四个特性。
3. https的语法、语义仍然是http,但下层的协议由TCP/IP 换成了SSL/TLS。
4. SSL/TLS是信息安全领域中的权威标准,采用多种先进的加密技术保证通讯安全。
5. OpenSSL是著名的开源密码学工具包,是SSL/TLS加密算法的具体实现。
2. 对称加密和非对称加密理解
- 加密含义
- 对称加密:相同密钥(加密速度快)
- 非对称加密:公钥和私钥(加密速度慢)
- 混合加密:TLS 通讯采用的方式
加密含义
实现机密性最常用的手段是加密(encrypt),把消息用某种方式转换成谁也看不懂的乱码,只有掌握特殊钥匙的人才能转换出原始内容。这里的钥匙就叫做密钥(key),加密前的消息叫做“明文”,加密后的乱码叫密文,使用密钥还原明文的过程叫做解密(decrypt),加密解密的过程叫加密算法。按照密钥的使用方式,加密可以分为两大种,对称加密和非对称加密。
对称加密算法
对称加密很好理解,就是指加密和解密时使用的密钥都是同一个,是对称的,只要保证了密钥的安全,那整个通讯过程就可以说具有了机密性。
TLS里有非常多的对称加密算法,比如RC4、DES、3DES、AES等。
AES 的意思是“高级加密标准”(Advanced Encryption Standard),密钥长度可以是 128、192 或 256。它是 DES 算法的替代者,安全强度很高,性能也很好,而且有的硬件还会做特殊优化,所以非常流行,是应用最广泛的对称加密算法。
堆成加密看上去好像完美地实现了机密性,但其中有一个很大的问题,如何把密钥安全地传输给对方?
因为在对称加密算法中,只要持有密钥就可以解密,如果你和网站约定的密钥在传输过程中被黑客窃取,那他就可以在之后随意解密收到的数据,通讯过程也就没有安全可言了。
非对称加密算法
它有两个密钥,一个叫公钥(public key),一个叫私钥(private key),两个密钥是不对称的,公钥可以给任何人使用,而私钥必须严格保密。
公钥和私钥有个特别的单向性,虽然都可以用来加密和解密,但公钥加密后只能用私钥解密,反过来,私钥加密后只能用公钥解密。
非对称加密可以解决密钥交换的问题,密文只能由私钥持有者才能解密。而黑客因为没有私密=钥=,所以无法解开密文。
很遗憾,虽然非对称加密没有密钥交换问题,但它是基于复杂的数学难题,运算速度很慢,如果仅仅用非对称加密,虽然保证了安全,但是通讯速度有如乌龟,实用性就变成了零。
RSA:非对称加密的代名词,基于大数分解的数学难题; ECDHE:椭圆曲线加密算法,比 RSA 算法更安全,TLS1.3 握手是基于 ECDHE 算法,TLS1.2 可选该算法作为加密套件
提炼
1. 对称加密只使用一个密钥,运算速度快,密钥必须保密,无法做到密钥安全交换。
2. 对称加密使用两个密钥:公钥和私钥,公钥可以任意分发而私钥保密,解决了密钥交换问题但速度慢,常用的有RSA和ECHDE。
3. 把对称加密和非对称加密结合起来就得到了“又好又快”的混合加密,也是TLS使用的加密方式。
3. 摘要算法和数据签名算法
- 哈希函数(哈希碰撞)
- 摘要算法:SHA2摘要算法
- 数字签名:摘要算法 + 私钥
- 实现:完整性、不可否认性、身份确定性
摘要算法
实现完整性的手段主要是摘要算法(Digest Algorithm),也就是常说的散列函数、哈希函数(Hash Function)。
你可以把摘要算法理解成一种特殊的压缩算法,它能够把任意长度的数据,压缩成固定长度、而且独一无二的摘要字符串,就好像给数据生成一个数字指纹。
它只有算法,没有密钥,加密后的数据无法解密,不能从摘要逆推出原文。因此只能对比两份摘要是否相同判断有无被篡改。
摘要算法实际上是把数据从一个“大空间”映射到了“小空间”,所以就存在“冲突”(collision,也叫碰撞)的可能性,「就如同现实中的指纹一样,可能会有两份不同的原文对应相同的摘要」。好的摘要算法必须能够“抵抗冲突”,让这种可能性尽量地小。
因为摘要算法对输入具有“单向性”和“雪崩效应”,输入的微小不同会导致输出的剧烈变化,所以也被 TLS 用来生成伪随机数
你一定在日常工作中听过、或者用过 「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 字节的摘要。
「摘要算法保证了“数字摘要”和原文是完全等价的。所以,我们只要在原文后附上它的摘要,就能够保证数据的完整性」。
不过摘要算法不具有机密性,如果明文传输,那么黑客可以修改消息后把摘要也一起改了,网站还是鉴别不出完整性。
所以,真正的完整性必须要建立在机密性之上,在混合加密系统里用会话密钥加密消息和摘要。
数字签名
加密算法结合摘要算法,我们的通讯过程可以说比较安全了。但这里还有漏洞,就是通讯的两个端点。
在 TLS 里有什么东西和现实中的签名、印章很像,只能由本人持有,而其他任何人都不会有呢?只要用这个东西,就能够在数字世界里证明你的身份。
这个东西就是非对称加密里的“私钥”,使用「私钥再加上摘要算法」,就能够实现“「数字签名」”,同时实现“「身份认证」”和“「不可否认」”。
数字签名的原理其实很简单,就是把公钥私钥的用法反过来,之前是公钥加密、私钥解密,现在是私钥加密、公钥解密。
但又因为非对称加密效率太低,所以「私钥只加密原文的摘要」,这样运算量就小的多,而且得到的数字签名也很小,方便保管和传输。
签名和公钥一样完全公开,任何人都可以获取。但这个签名只有用私钥对应的公钥才能解开,拿到摘要后,再比对原文验证完整性,就可以像签署文件一样证明消息确实是你发的。刚才的这两个行为也有专用术语,叫做“「签名」”和“「验签」”。
4. TLS 握手
- 握手目的: 为对称加密安全交换密钥
- RSA经典握手
- ECHDE握手:ECDHE 算法参数交换、抢跑
- TLS1.3握手:必须采用 ECHDE 算法,压缩为 1RTT
握手目的
「实现 HTTPS 通信的机密性」,在通信刚开始的时候使用非对称算法,比如 RSA、ECDHE,首先解决密钥交换的问题。然后用随机数产生对称算法使用的“「会话密钥」”(session key),再用公钥加密。 对方拿到密文后用私钥解密,取出会话密钥。这样,双方就实现了对称密钥的安全交换,后续就不再使用非对称加密,全都使用对称加密。
RSA 握手过程
RSA 可能是加密算法中最著名的一个,几乎可以说是非对称加密的代名词,它的安全性基于“整数分解”的数学难题,使用两个超大素数的乘积作为生成密钥的材料,想要从公钥推算出私钥是非常困难的。
大体上分为三个阶段:「明文共享阶段、CA 认证阶段、生成主秘钥阶段」
第一阶段:明文共享阶段
在 TCP 建立连接之后,浏览器会首先发一个“Client Hello”消息,里面有客户端的版本号、支持的密码套件,还有一个随机数(Client Random),用于后续生成会话密钥。
服务器收到“Client Hello”后,会返回一个“Server Hello”消息。把版本号对一下,也给出一个随机数(Server Random),然后从客户端的列表里选一个作为本次通信使用的密码套件以及公钥。
服务器为了证明自己的身份,就把证书也发给了客户端(Server Certificate)。
Server Done
这样第一个消息往返就结束了(两个 TCP 包),结果是客户端和服务器通过明文共享了三个信息:Client Random、Server Random 和 公钥。
第二阶段:证书验证
客户端这时也拿到了服务器的证书,那这个证书是不是真实有效的呢?这就要用到第 25 讲里的知识了,开始走证书链逐级验证,确认证书的真实性,再用证书公钥验证签名,就确认了服务器的身份:“刚才跟我打招呼的不是骗子,可以接着往下走。”
第三阶段:主密钥生成
客户端通过 RSA 公钥对生成的 pre-master 进行加密,并发送给服务端。
现在客户端和服务器手里有了三个随机数:Client Random、Server Random 和 Pre-Master。用这三个作为原始材料,就可以生成用于加密会话的主密钥,叫“Master Secret”。
有了主密钥和派生的会话密钥,客户端发一个“Change Cipher Spec”,然后再发一个“Finished”消息,把之前所有发送的数据做个摘要,再加密一下,让服务器做个验证。
服务器也发送“Change Cipher Spec”和“Finished”消息,双方都验证加密解密 OK,握手正式结束,后面就收发被加密的 HTTP 请求和响应。
ECDHE 握手过程
第一阶段:明文共享阶段(C/S 两端共享随机数 和 服务器的椭圆曲线加密参数)
在 TCP 建立连接之后,浏览器会首先发一个“Client Hello”消息,里面有客户端的版本号、支持的密码套件,还有一个随机数(Client Random),用于后续生成会话密钥。
服务器收到“Client Hello”后,会返回一个“Server Hello”消息。把版本号对一下,也给出一个随机数(Server Random),然后从客户端的列表里选一个作为本次通信使用的密码套件。
接下来是一个关键的操作,因为服务器选择了 ECDHE 算法,所以它会在证书后发送“Server Key Exchange”消息,里面是椭圆曲线的公钥(Server Params),用来实现密钥交换算法,再加上自己的私钥签名认证。
服务器为了证明自己的身份,就把证书也发给了客户端(Server Certificate)。
Server Done
这样第一个消息往返就结束了(两个 TCP 包),结果是客户端和服务器通过明文共享了三个信息:Client Random、Server Random 和 Server Params。
第二阶段:证书验证同上
第三阶段:主密钥生成
客户端按照密码套件的要求,也生成一个椭圆曲线的公钥(Client Params),用“Client Key Exchange”消息发给服务器。
根据密钥交换算法的两个参数(Client Params、Server Params)用 ECDHE 算法计算出“Pre-Master”,其实也是一个随机数。
现在客户端和服务器手里有了三个随机数:Client Random、Server Random 和 Pre-Master。用这三个作为原始材料,就可以生成用于加密会话的主密钥,叫“Master Secret”。而黑客因为拿不到“Pre-Master”,所以也就得不到主密钥。
有了主密钥和派生的会话密钥,客户端发一个“Change Cipher Spec”,然后再发一个“Finished”消息,把之前所有发送的数据做个摘要,再加密一下,让服务器做个验证。
服务器也发送“Change Cipher Spec”和“Finished”消息,双方都验证加密解密 OK,握手正式结束,后面就收发被加密的 HTTP 请求和响应
「和 RSA 加密算法的区别:」
服务器端在发送 Server Hello 时会发出“Server Key Exchange”消息并携带加密算法参数。
因为使用了 ECDHE,客户端可以不用等到服务器发回“Finished”确认握手完毕,就可以立即发出 HTTP 报文,「省去了一个消息往返的时间浪费」。这个叫“抢跑”,和“TCP Fast Open”有点像,都是不等连接完全建立就提前发应用数据,提高传输的效率。
TLS1.3 握手
HTTPS 建立连接时除了要做 TCP 握手,还要做 TLS 握手,在 1.2 中会花费两个消息往返(2-RTT),可能导致几十毫秒甚至上百毫秒的延迟,在移动网络中延迟还会更严重。
现在 TLS1.3 密码套件大幅度简化,也就没有必要再像以前那样走复杂的协商流程了,「规定必须使用椭圆曲线算法」。TLS1.3 压缩了以前的“Hello”协商过程,删除了“Key Exchange”消息,把握手时间减少到了“1-RTT”,效率提高了一倍。
5. HTTPS 优化策略有了解吗?
握手阶段慢
硬件优化
软件优化
协议优化
会话复用: session ID
慢在哪里?
通常所说的“HTTPS 连接慢”指的就是刚开始建立连接的那段时间。在 TCP 建连之后,正式数据传输之前,HTTPS 比 HTTP 增加了一个 TLS 握手的步骤,这个步骤最长可以花费两个消息往返,也就是 2-RTT。而且在握手消息的网络耗时之外,还会有其他的一些“隐形”消耗,比如:产生用于密钥交换的临时公私钥对(ECDHE);验证证书时访问 CA 获取 CRL 或者 OCSP;非对称加密解密处理“Pre-Master”。
硬件优化
HTTPS 连接是计算密集型,而不是 I/O 密集型。
可以选择更快的 CPU,最好还内建 AES 优化,这样即可以加速握手,也可以加速传输。
可以选择“SSL 加速卡”,加解密时调用它的 API,让专门的硬件来做非对称加解密,分担 CPU 的计算压力。
第三种硬件加速方式:“SSL 加速服务器”,用专门的服务器集群来彻底“卸载”TLS 握手时的加密解密计算,性能自然要比单纯的“加速卡”要强大的多。
软件优化
软件升级实施起来比较简单,就是把现在正在使用的软件尽量升级到最新版本,比如把 Linux 内核由 2.x 升级到 4.x,把 Nginx 由 1.6 升级到 1.16,把 OpenSSL 由 1.0.1 升级到 1.1.0/1.1.1。由于这些软件在更新版本的时候都会做性能优化、修复错误,只要运维能够主动配合,这种软件优化是最容易做的,也是最容易达成优化效果的。
协议优化
如果有可能,应当尽量采用 TLS1.3,它大幅度简化了握手的过程,完全握手只要 1-RTT,而且更加安全。
如果暂时不能升级到 1.3,只能用 1.2,那么握手时使用的密钥交换协议应当尽量选用椭圆曲线的 ECDHE 算法。它不仅运算速度快,安全性高,还支持“False Start”,能够把握手的消息往返由 2-RTT 减少到 1-RTT,达到与 TLS1.3 类似的效果。
会话复用
HTTPS 建立连接的过程:先是 TCP 三次握手,然后是 TLS 一次握手。这后一次握手的重点是算出主密钥“Master Secret”,而主密钥每次连接都要重新计算,未免有点太浪费了,如果能够把“辛辛苦苦”算出来的主密钥缓存一下“重用”,不就可以免去了握手和计算的成本了吗?
这种做法就叫“会话复用”(TLS session resumption),和 HTTP Cache 一样,也是提高 HTTPS 性能的“大杀器”,被浏览器和服务器广泛应用。
会话复用分两种,第一种叫“Session ID”,就是客户端和服务器首次连接后各自保存一个会话的 ID 号,内存里存储主密钥和其他相关的信息。当客户端再次连接时发一个 ID 过来,服务器就在内存里找,找到就直接用主密钥恢复会话状态,跳过证书验证和密钥交换,只用一个消息往返就可以建立安全通信