文章来源
最近跟菊厂合作,我司向他们提供SAAS服务。但由于他们对服务安全管控比较严格,内部有专门部门去审核上线的服务。因此菊厂派人来我司专门对安全这块做全面排查,期间加了不少班。其中他们提到了对HTTPS密码套件做配置,当初只知道HTTPS握手后需要非对称加密的算法,后面查询了才知道原来还有这一系列的通讯过程中使用的密码算法。特此写下文章作为学习记录。
HTTPS简介
HTTPS是Hyper Text Transfer Protocol Secure的缩写。是一个计算机系统间进行安全通信的协议,主要用在浏览器和web服务器之间进行通信。HTTP使用明文进行数据传输,而HTTPS则使用加密数据进行传输。
HTTPS可以有效防止黑客在浏览器和web服务器之间窃取和修改数据,即使黑客获取到这些数据,由于数据已经被加密,对黑客来说其实是垃圾数据。
HTTPS使用SSL(Secure Socket Layer)或者TLS(Transport Layer Security)协议来建立起浏览器和web服务器之间的加密连接。
握手过程
- 客户端给出协议版本号、生成的 随机数
Client random
,以及客户端支持的加密方法。 - 服务端确认双方使用的加密方法,并给出数字证书、以及一个 服务器生成的随机数
Server random
。 - 客户端确认数字证书有效,然后生成一个新的 随机数
Premaster secret
,并使用数字证书中的公钥,加密这个随机数,发给服务端。 - 服务端使用自己的私钥,解析获取客户端发来的随机数
Premaster secret
。
上述可以归结为三次通信,但即使上并不止三次,归结为下图。
服务端和客户端据约定的加密方法,使用前面的三个随机数,生成 对话密钥session key
。服务器和客户端将会使用该密码进行对称加密,保证通信过程中信息的安全。
、
CA证书认证流程
在服务端发送CA证书给客户端后,客户端需要进行一系列的验证。
CA证书简介
CA证书其实就是第三方机构,作用是检查证书持有者身份的合法性,并签发证书,以防证书被伪造或篡改。我们都知道CA证书是用来验证网站的安全性,其实,证书除了可以用来验证某个网站,还可以用来验证某个文件是否被篡改。
由于证书所涉及面太宽广,里面涉及到如何签发、格式规范等。本文不做过多涉及。
证书内容
- 证书颁发机构的名称
- 证书本身的数字签名
- 证书持有者公钥
- 证书签名用到的Hash算法
- ...
认证流程
- 首先浏览器读取证书中的证书所有者、有效期等信息进行一一校验。浏览器开始查找操作系统中已内置的受信任的证书发布机构CA,与服务器发来的证书中的颁发者CA比对,用于校验证书是否为合法机构颁发
- 如果找不到,浏览器就会报错,说明服务器发来的证书是不可信任的。
- 如果找到,那么浏览器就会从操作系统中取出颁发者CA 的公钥,然后对服务器发来的证书里面的数字签名进行解密
- 浏览器使用相同的hash算法计算出服务器发来的证书的hash值,将这个计算的hash值与证书中签名做对比
- 对比结果一致,则证明服务器发来的证书合法,没有被冒充
- 此时浏览器就可以读取证书中的公钥,用于后续加密了
密码学套件
简介
密码套件分为三大部分:密钥交换算法,数据加密算法,消息验证算法(MAC,message authentication code)。密钥交换算法用于握手过程中建立信道,一般采用非对称加密算法。数据加密算法用于信道建立之后的加密传输数据,一般采用对称加密算法。MAC顾名思义是一种哈希,用于验证消息的完整性,包括整个握手流程的完整性(例如TLS握手的最后一步就是一个对已有的握手消息的全盘哈希计算的过程)。
获取本机支持套件
#openssl ciphers -V
密码套件名详解
TLS_DHE_RSA_WITH_AES_256_CBC_SHA是一个密码学套件的标准名字。
这里的TLS代表的是TLS协议,如果未来TLS改名,这个名字可能会变,否则会一直是这个名字。WITH是一个分隔单次,WITH前面的表示的是握手过程所使用的非对称加密方法,WITH后面的表示的是加密信道的对称加密方法和用于数据完整性检查的哈希方法。WITH前面通常有两个单次,第一个单次是约定密钥交换的协议,第二个单次是约定证书的验证算法。两个功能都需要使用非对称加密算法。交换信息使用的非对称加密算法是第一个单词,证书使用的非对称加密算法是第二个。
有的证书套件,例如TLS_RSA_WITH_AES_256_CBC_SHA,WITH单词前面只有一个RSA单词,这时就表示交换算法和证书算法都是使用的RSA,所以只指定一次即可。可选的主要的密钥交换算法包括: RSA, DH, ECDH, ECDHE
。可选的主要的证书算法包括:RSA, DSA, ECDSA
。两者可以独立选择,并不冲突。AES_256_CBC指的是AES这种对称加密算法的256位算法的CBC模式,AES本身是一类对称加密算法的统称,实际的使用时要指定位数和计算模式,CBC就是一种基于块的计算模式。最后一个SHA就是代码计算一个消息完整性的哈希算法。
握手过程详解
客户端发出请求
ClientHello
由于客户端(如浏览器)对一些加解密算法的支持程度不一样,但是在TLS协议传输过程中必须使用同一套加解密算法才能保证数据能够正常的加解密。在TLS握手阶段,客户端首先要告知服务端,自己支持哪些加密算法,所以客户端需要将本地支持的加密套件(Cipher Suite)的列表传送给服务端。除此之外,客户端还要产生一个随机数,这个随机数一方面需要在客户端保存,另一方面需要传送给服务端,客户端的随机数需要跟服务端产生的随机数结合起来产生后面要讲到的 Master Secret 。
综上,在这一步,客户端主要向服务器提供以下信息:
- 支持的协议版本,比如TLS 1.0版
- 一个客户端生成的随机数,稍后用于生成"对话密钥"
- 支持的加密方法,比如RSA公钥加密
- 支持的压缩方法
服务器回应
SeverHello
上图中,从Server Hello到Server Done,有些服务端的实现是每条单独发送,有服务端实现是合并到一起发送。Sever Hello和Server Done都是只有头没有内容的数据。
服务端在接收到客户端的Client Hello之后,服务端需要将自己的证书发送给客户端。这个证书是对于服务端的一种认证。例如,客户端收到了一个来自于称自己是www.alipay.com的数据,但是如何证明对方是合法的alipay支付宝呢?这就是证书的作用,支付宝的证书可以证明它是alipay,而不是财付通。证书是需要申请,并由专门的数字证书认证机构(CA)通过非常严格的审核之后颁发的电子证书。颁发证书的同时会产生一个私钥和公钥。私钥由服务端自己保存,不可泄漏。公钥则是附带在证书的信息中,可以公开的。证书本身也附带一个证书电子签名,这个签名用来验证证书的完整性和真实性,可以防止证书被串改。另外,证书还有个有效期。
Server Key Exchange(证书公钥发送)
在服务端向客户端发送的证书中没有提供足够的信息(证书公钥)的时候,还可以向客户端发送一个Server Key Exchange。
Cerficate Request(请求客户端证书)
此外,对于非常重要的保密数据,服务端还需要对客户端进行验证,以保证数据传送给了安全的合法的客户端。服务端可以向客户端发出 Cerficate Request 消息,要求客户端发送证书对客户端的合法性进行验证。比如,金融机构往往只允许认证客户连入自己的网络,就会向正式客户提供USB密钥,里面就包含了一张客户端证书。
跟客户端一样,服务端也需要产生一个随机数发送给客户端。客户端和服务端都需要使用这两个随机数来产生PreMaster Secret
。
最后服务端会发送一个Server Hello Done消息给客户端,表示Server Hello消息结束了。
综上,在这一步,服务器的回应包含以下内容:
- 确认使用的加密通信协议版本,比如TLS 1.0版本。如果浏览器与服务器支持的版本不一致,服务器关闭加密通信
- 一个服务器生成的随机数,稍后用于生成"对话密钥"
- 确认使用的加密方法,比如RSA公钥加密
- 服务器证书
客户端回应
Client Key Exchange(发送客户端证书)
如果服务端需要对客户端进行验证,在客户端收到服务端的 Server Hello 消息之后,首先需要向服务端发送客户端的证书,让服务端来验证客户端的合法性。
Certificate Verify(证书检查)接着,客户端需要对服务端的证书进行检查,如果证书不是可信机构颁布、或者证书中的域名与实际域名不一致、或者证书已经过期,就会向访问者显示一个警告,由其选择是否还要继续通信。如果证书没有问题,客户端就会从服务器证书中取出服务器的公钥。然后,向服务器发送下面三项信息:
一个随机数。该随机数用服务器公钥加密,防止被窃听
编码改变通知,表示随后的信息都将用双方商定的加密方法和密钥发送
客户端握手结束通知,表示客户端的握手阶段已经结束。这一项同时也是前面发送的所有内容的hash值,用来供服务器校验
上面第一项的随机数,是整个握手阶段出现的第三个随机数,它是客户端使用一些加密算法(例如:RSA, Diffie-Hellman)产生一个48个字节的Key,这个Key叫 PreMaster Secret
。
ChangeCipherSpecChangeCipherSpec
一个独立的协议,体现在数据包中就是一个字节的数据,用于告知服务端,客户端已经切换到之前协商好的加密套件(Cipher Suite)的状态,准备使用之前协商好的加密套件加密数据并传输了。
在ChangecipherSpec传输完毕之后,客户端会使用之前协商好的加密套件和Session Secret加密一段 Finish 的数据传送给服务端,此数据是为了在正式传输应用数据之前对刚刚握手建立起来的加解密通道进行验证。
服务器的最后回应
Server Finish
服务端在接收到客户端传过来的 PreMaster 加密数据之后,使用私钥对这段加密数据进行解密,并对数据进行验证,也会使用跟客户端同样的方式生成 Session Secret,一切准备好之后,会给客户端发送一个 ChangeCipherSpec,告知客户端已经切换到协商过的加密套件状态,准备使用加密套件和 Session Secret加密数据了。之后,服务端也会使用 Session Secret 加密一段 Finish 消息发送给客户端,以验证之前通过握手建立起来的加解密通道是否成功。
根据之前的握手信息,如果客户端和服务端都能对Finish信息进行正常加解密且消息正确的被验证,则说明握手通道已经建立成功,接下来,双方可以使用上面产生的Session Secret
对数据进行加密传输了。
golang中配置ssl
tlsconf := &tls.Config{
InsecureSkipVerify: true,
MaxVersion: tls.VersionTLS13,
MinVersion: tls.VersionTLS12,
PreferServerCipherSuites: true,
}
tlsconf.CipherSuites = []uint16{
tls.TLS_AES_128_GCM_SHA256,
tls.TLS_CHACHA20_POLY1305_SHA256,
tls.TLS_AES_256_GCM_SHA384,
tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
}
参考文章
https://blog.csdn.net/zhangta...
https://zhuanlan.zhihu.com/p/...
http://blog.chinaunix.net/uid...
有疑问加站长微信联系(非本文作者)