HTTPS主要的计算环节
大象为什么跳不高跑不快?因为它很重。HTTPS为什么访问比较慢为什么消耗CPU资源呢?同样也是因为它很重。HTTPS的重,体现在如下几方面:
1. 大量的计算。SSL的每一个字节都涉及到较为复杂的计算。即使是clientHello,也需要在握手完成时做校验。
2. TLS协议的封装和解析。HTTPS所有数据都是按照TLS record格式进行封装和解析的。
3. 协议的网络交互。从TLS的握手过程可以看出,即使不需要进行任何计算,TLS的握手也需要至少1个RTT(round trip time)以上的网络交互。
其中第2和第3点不是本文重点。本文侧重为大家分析HTTPS计算方面的原理,计算性能的测试和优化。
总体来说,HTTPS主要有如下计算环节:
- 非对称密钥交换。比如RSA, Diffie-Hellman, ECDHE.这类算法的主要作用就是根据客户端和服务端不对称的信息,经过高强度的密钥生成算法,生成对称密钥,用于加解密后续应用消息。
- 对称加解密。服务端使用密钥A对响应内容进行加密,客户端使用相同的密钥A对加密内容进行解密,反之亦然。
- 消息一致性验证。每一段加密的内容都会附加一个MAC消息,即消息认证码。简单地说就是对内容进行的安全哈希计算,接收方需要校验MAC码。
- 证书签名校验。这个阶段主要发生在客户端校验服务端证书身份时,需要对证书签名进行校验,确保证书的真实性。
那上述阶段为什么需要消耗CPU呢?简单介绍一下计算原理。
HTTPS计算原理及算法分析
上一节提到四个主要的计算环节,事实上每个环节都需要用到指定的算法。下面结合腾讯现在主要使用到的证书签名和密码套件分别介绍一下。
什么是密码套件(cipher suite)?它其实是一套算法的统称,包括密钥交换算法、消息认证码算法、内容加密算法和伪随机数算法。
统计线上的cipher suite可以得出一个大概的使用情况,如下表所示:
类型
占比
ECDHE-RSA-AES128-GCM-SHA256
85.67%
ECDHE-RSA-AES128-SHA
8.84%
ECDHE-RSA-AES128-SHA256
5.15%
ECDHE-RSA-AES128-SHA256
~1%
证书签名算法
证书签名算法主要用于身份校验,现在的签名算法主要是SHA(安全哈希)系列,目前SHA1算法已经不安全,不推荐使用,但由于部分比较老的操作系统只支持SHA1算法,所以目前线上使用到的签名算法主要是SHA256和少量的SHA1。
SHA2和SHA1算法最主要的操作还是位之间的运算,包括AND, OR, XOR,然后进行最多不超过80轮的迭代。所以从算法原理来看,安全哈希的计算速度应该会比较快。
算法名
主要数学运算
优点
缺点
SHA1
AND/XOR
兼容性好
已经不安全
SHA256
AND/XOR
安全
兼容性差,老系统(XP)不支持
密钥交换算法
密钥交换就是指客户端和服务端通过交换各自的信息完成共同密钥的生成。
目前线上使用到的主要密钥交换算法主要是如下三类:
算法名
主要数学运算
优点
缺点
ECDHE_RSA
1.ECC加法、乘法2.模幂、模乘计算
1.支持PFS,更加安全;2.性能相比DHE要好
性能相比RSA要差20%
DHE_RSA
模幂、模乘计算
安全、支持PFS
性能最差
RSA
模幂、模乘计算
1.算法简单可靠;2.性能在三者中最好
1.不支持PFS,安全性稍差;2.不支持false start,影响用户访问速度
RSA的安全性建立在大数因子分解很困难的基础上;Diffie-Hellman的安全性建立在离散对数求解比较困难的基础上;ECDHE是在椭圆曲线有限域上实现的Diffie-Hellman算法,具备Diffie-Hellman同样的安全性。
分析上述运算方程有什么意义呢?
- 可以看出RSA和DH的主要计算都是模幂计算。如果指数比较小,比如几十甚至几百,CPU计算会非常快。但是如果指数接近2的2048次方这样大的一个天文数字,这种模幂计算就非常消耗CPU了。即使集合全世界性能最强劲的CPU,也无法在短时间内暴力破解出2048位及以上的RSA密钥。
- 椭圆曲线实际上是一个集合,并且定义了一套计算规则。使用较小的数字就能实现RSA同样的安全强度。如下表所示,ECC使用224位长度的密钥就能实现RSA2048位长度的安全性
对称密钥大小
RSA和DH密钥大小
ECC密钥大小
80
1024
160
112
2048
224
128| 3072| 256
192| 7680| 384 256| 15360| 521
对称加密算法
对称加密算法就是使用相同的密钥对数据进行加解密,常用的对称加密算法如下:
算法名
主要数学运算
优点
缺点
AES_128_CBC
XOR
实现简单,运行速度k
无MAC功能
AES_128_GCM
XOR
有MAC功能
实现复杂,运行速度相比CBC慢
RC4
XOR
实现简单,运行速度快
不推荐使用,已经不安全
CHACHA20_POLY365
XOR
运行速度快,适用于移动端
发明时间短,安全性待验证
由于对称加密算法最主要的数学运算是XOR,虽然不同的模式对速度有一定的影响,但是由于密钥长度短,同时计算过程简单,对称加密的效率非常高。
消息认证码算法
消息认证码算法和证书签名算法的核心操作有点类似,主要是基于安全哈希函数,比如SHA1或者SHA2。所以这里就不做多余介绍。
性能测试
从上一章的数学原理分析可以得出初步的性能结论,RSA类运算应该是最消耗CPU资源的。但是纯数学分析还不能完全代表真正的软件性能。
本章我们使用三种方式测试一下HTTPS的性能。
openssl speed
Openssl提供了一个速度测试的工具:openssl speed。顾名思义,它的功能就是测试openssl支持的全部算法的速度。
Openssl speed测试的基本原理是在指定时间内(比如3S或者10S),循环调用指定的密码算法,最后的运算次数就代表了该算法的性能。 测试平台的信息如下:
操作系统
Linux TENCENT64.site 3.10.94-1-tlinux2-0036.tl2
CPU
Intel(R) Xeon(R) CPU E5-2620 v3 @ 2.40GHz
软件版本
Openssl 1.1.0 pre5
由于线上业务单个请求的平均大小约为4K字节,所以下表统计了openssl加密和安全哈希算法每秒能够处理的字节数以及处理4K字节需要的用户时间。
算法名
每秒处理的字节数(块大小为1K)
处理4K字节需要的时间
aes-128 cbc
117499.22k
0.00003s
aes-192 cbc
97594.71k
0.00004s
aes-256 cbc
83456.68k
0.000047s
SHA1
488445.95k
0.000008s
SHA256
193084.22k
0.00002s
RC4
623545.69k
0.0000064s
aes-128 gcm
1120621.23k
0.0000035s
aes-256gcm
981585.24k
0.000004s
chacha20 poly1305
205781.33k
0.000019s
可以看出,数据加解密和安全哈希的操作时间基本都是10微秒级别以下。其中耗时最多的是SHA256,需要20微秒。
下表统计了RSA签名、校验及椭圆曲线的操作时间:
算法名
Sign
verify
sign/s
verify/s
Rsa 2048
0.001429s
0.000045s
699.8
21982.3
DSA 2048
0.000435s
0.000518s
2297.0
1928.8
ecdsa (nistp256)
0.0001s
0.0005s
7672.1
1960.4
可以看出RSA2048位的签名操作速度很慢,单次操作需要耗时1.4毫秒,ECDSA的操作速度要快一些,大概需要0.5毫秒。
椭圆曲线的操作时间统计如下:
曲线名
Op
Op/s
ecdh (nistp256)
0.0004s
2350.3
椭圆曲线的操作曲线基点选取,耗时大概0.4毫秒。
运行时间分析
Openssl speed只能统计单个算法的性能和执行时间,但这个时间不能代表线上业务真实运行需要消耗的时间,原因是:
1.一次完整请求涉及到不同算法的组合,单个算法无法反映整体时间。
2.HTTPS协议交互时需要协议解析,网络交互,异步异常处理,这里肯定会有一些额外的性能损耗。
3.openssl实现TLS协议栈时需要调用多个应用层函数和系统调用,也会有一定的开销。
所以需要进一步统计真实的运行时间,主要是统计openssl处理各个主要环节的消耗时间。限于篇幅,这里只介绍ECDHE_RSA密钥交换算法的性能,具体的统计函数和时序如下:
从上图所示的数据能够非常明显地看到,ServerKeyExchange消耗了2.4毫秒,要显著超过其他消息的耗时。
那ServerKeyExchange消息为什么消耗时间呢?进一步分析如下:
其中ECC参数生成耗时约108us,RSA签名耗时给2200us。也就是说,整个握手过程中最消耗性能就是RSA签名操作。
Perf事件及火焰图分析
Perf是linux内核提供的一个性能分析工具。它的主要功能是能够周期性地采集各个函数的CPU周期数,从而反映性能瓶颈及热点代码。
火焰图能更加形象直观地展示perf record记录下来的事件。
简单概括一下:
- 和RSA计算相关的事件占全部采样约75%,ECC相关的计算占比约10%。
- 使用RSA密钥交换时,RSA相关的事件采样占整体采样的比例约85%。
性能测试的结论
性能测试的最终目的是为了性能优化。根据之前的测试数据,HTTPS的计算性能优化思路可以总结如下:
- 完全握手对性能的影响非常大,性能降低至普通HTTP性能的 10%以下。应该尽量提升tcp reuse及session resume,减少完全握手的发生。
- 密钥交换过程中的RSA算法对性能的影响非常大,一次正常HTTPS交互过程,RSA计算过程需要消耗整体性能的75%左右。也就是说,如果能够提升RSA的性能,那么整体性能将最多提升4倍。
- ECC曲线相关的计算约占整体计算量的7%,对整体性能的影响不大。但如果RSA计算优化好了,ECC的性能将逐渐成为瓶颈。
- 对称加解密及MAC计算对性能影响很小(微秒级别),暂时不需要考虑优化。