1. 前言
最近工作涉及到 https
和 jwt
,突然发现自己对加密解密以及相应的算法的理解还是很模糊,因此写这边文章主要是想理清脑子中的一些困惑。这篇文章不会涉及到算法的数学原理,如果想了解其数学原理的同学可能就需要去参阅其它资料了。
2.从对称和非对称加密说起
在互联网通信过程中,我们希望传递的信息是安全的。安全主要由体现在如下几个方面:
其中使用加密算法就可以保证数据的私密性,发送方将明文用某种加密方法
加密成密文,接收方使用相应的解密方法
对密文进行解密,还原出明文。在这里需要注意一点是:这里加密方法
和解密方法
可以描述成一种加密算法。比如:对称加密(DES,RC5)和 非对称加密(RSA)。你可能会看到一些文章说 RSA 是签名算法,这里可以更具体一点说:RSA是一种可以完成签名功能的算法,当然它也可以完成加解密功能(只不过签名是依赖于它的加解密功能来完成的)。
注意:我们描述一种算法,主要是看它能否完成某个功能。比如后面还会提到的 密钥交换算法(Key exchange algorithms)和 消息认证码算法(Message Authentication Code algorithms)
对称加密算法使用同一个公钥进行加密和解密,而非对称加密算法使用公钥加密,私钥解密。
2.1 场景分析
不俗套的我们又是经典人物 Bob 和 Alice 两个人进行通信。
2.1.1 简单的使用对称加密进行通信
如下面所示:Alice 和 Bob 之间通过对称加密算法进行加解密。
缺陷:Alice 和 Bob 之间使用公钥必须协商好,那么协商好的公钥要通知对方,必须经过网络传输并且不能加密(不然对方看不懂公钥内容是什么)。这里如果密钥泄露了,相当于就是明文传输,第三方可以使用泄露的密钥对 Alice 和 Bob 之间的信息进行解密。这样就不能保证信息通信中的私密性。
2.1.2 使用非对称加密
在上面提到的对称加密通信过程,没有解决公钥的安全传输问题,所以引入了非对称加密。
如下面所示:Alice 和 Bob 之间通过非对称加密算法进行加解密。Alice 使用 Bob 生成的公钥对明文进行加密,然后 Bob 使用自己的私钥对密文进行解密得到明文。
Bob 自己生成一对公钥和私钥,私钥只有 Bob 知道,公钥可以让任何人知道。因此可以直接将公钥发送给 Alice,被第三方截获也没有关系。
当 Bob 想要给 Alice 发送信息时,可以使用 Alice 生成的公钥进行加密,然后 Alice 使用自己的私钥进行解密。
缺陷:
当有个第三方 Eve 使用 Bob 的公钥冒充 Alice 给 Bob 发送消息,那么 Bob 无法证明该消息是来自 Alice 还是 Eve,这就是信息传递过程的不可否认性问题。
2.1.3 数字签名
前面我们谈到,即使使用非对称加密加密也无法解决信息传递过程中的不可否认问题,Bob 虽然可以用自己私钥来解密其它人用 Bob 的公钥加密的内容,但是 Bob 不能认证这个人的身份。所以就需要一种机制来保证,Bob 能够确定给他发信息的这个人的身份,这就是需要这个人的签名
。使用非对称算法产生一对公钥和私钥,可以完成签名验证。因为私钥加密的内容,只能由这个私钥相对应的公钥才能解密。假设 Alice 用自己私钥生成签名,然后发送给 Bob,Bob 就可以用 Alice 公钥进行解密,如果能解开,说明这条消息的来源就是 Alice,而不是其他人,保证这一点的是 Alice 没有被别人窃取。所以一般使用数字签名来达到不可否认性。
采用数字签名的发送消息的过程如下:
可以看出采用来数字签名可以达到数据完整性验证和不可否认性验证。
缺陷:前面提到的数字签名和非对称加密能够有效的前提之一是:能够可靠安全的拿到通信双方的公钥。假如 Alice 在给 Bob 发送公钥的过程中,被第三方 Eve 截获。Eve 就可以将自己公钥发送给 Bob,这样 Bob 以为是 Alice的,使用 Eve 的公钥对明文加密发送给 Bob,这个消息也被 Eve 截获,那么这个时候 Eve 就可以使用自己的私钥对密文进行解密,得到明文,这样消息传递的私密性就被打破了。同理,Bob 给 Alice 传递自己公钥的过程被 Eve 截获,Alice 发送给 Bob 信息的私密性也得不到保证。
注:这里数字摘要生成算法,可以使用 hash 或者 MAC(Message Authentication Code)函数。
有关 MACs, hashs 和 签名之间的区别和联系可以参阅这里。
2.1.4 数字证书
当无法安全获得某个用户的公钥时,需要一个公正机构,确保你在公正机构获得这个用户的公钥都是正确且安全的。数字证书认证机构(CA)是是负责发放和管理数字证书的权威机构,并作为电子商务交易中受信任的第三方,承担公钥体系中公钥的合法性检验的责任。
引入 CA 后,Bob 就可以去为自己的公钥做认证,其中也包括 Bob 的一些相关信息,CA 利用自己的私钥对 Bob 的信息(包括公钥)进行加密。Alice 在电脑上可以用 CA 的公钥对 Bob 的数字证书进行解密,得到 Bob 的公钥,同时 Bob 也可以在电脑上用 CA 的公钥对 Alice 数字证书进行解密得到 Alice 的公钥。这样公钥的安全传递就通过 CA 完成,这样就满足了消息传递的源认证。
注:电脑上会安装 CA 的公钥。
2.2 总结
在上面我们描述了四个场景,利用不同的技术解决了消息传递过程中的私密性,完整性,不可否认性和源认证。
但是还是有一个缺点,因为上述我们的对明文的加密和解密依然使用的非对称密钥,非对称的加密的计算量大,所以对明文的加密通信,还是会使用对称加密,这就涉及到 密钥交换(key exchange algorithms),后面在 TSL/SSL 握手过程中的 密码套件(Cipher suite)中会再介绍。
3.TLS/SSL
3.1 背景
HTTP 的通信是不安全的,所以后面推出了 HTTPS,以 SSL(Secure Sockets Layer) 进行加密,这是 SSL 的起源。后面 IETF 将 SSL 进行标准化,1999年 公布 TLS(Transport Layer Security) 1.0 标准。
下面我们会谈到建立安全的 TSL/SSL 连接涉及到的几个步骤。TLS/SSL 安全协议采用非对称加密和对称加密的组合,客户端和服务器必须协商使用的算法并交换密钥信息。
本文使用 TLS 1.2 版本,TLS 1.2的过程几乎与所有先前版本的 SSL/TLS 相同。然而,在最新版本的传输层安全协议中,这个过程得到了极大地简化。
TLS/SSL 建立安全连接最重要部分称为握手(handshake)。在 TLS 握手阶段,服务器和客户端交换用于确定连接的重要信息。下面这个例子是基于 Web 浏览器的握手,但对于其他 TLS/SSL 握手也适用。
3.2 握手过程
3.2.1 Client Hello(Client → Server)
首先,客户端向服务器发送 Client Hello。Client Hello 包括如下几个信息:
- Client Version:客户端发送一个包含其支持的所有 TLS/SSL 协议版本列表的请求,首选项通常排在列表的第一个。首选项通常是最新可用的版本。例如,TLS 1.2 的客户端版本是 3,3。这是因为 TLS 1.0 被视为安全套接字层(SSL 3.0)的一个次版本,所以 TLS 1.0 是 3,1,TLS 1.1 是 3,2,依此类推。
- Client Random:这是一个 32 字节的随机数。客户端随机数和服务器随机数稍后用于生成加密密钥。
在最初的 TLS 1.2规范中,前 4 个字节应表示客户端的当前日期和时间(以时间戳格式),其余的 28 个字节应为随机生成的数。然而,IETF 后来建议不要这样做。(后面生成加密密钥的过程会使用到该随机数) - Session ID:这是用于连接的会话 ID。如果会话 ID 不为空,服务器将搜索之前缓存的会话,并在找到匹配项时恢复该会话。
- compression_methods:这是用于对SSL数据包进行压缩的方法。通过使用压缩,我们可以实现更低的带宽使用,因此传输速度更快。不过,稍后在本文中,我们将看到为什么使用压缩是有风险的。
- Cipher Suites:密码套件是密码算法的组合。通常,每个密码套件包含以下任务的密码算法:密钥交换(key exchange)、身份验证(authentication)、批量(数据)加密(bulk (data) encryption)和消息认证(message authentication)。客户端按优先顺序发送其支持的所有密码套件的列表。这意味着客户端理想情况下希望使用发送的第一个密码套件建立连接。密码套件通过字符串进行标识。一个示例的密码套件字符串是:
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, - TLS 表示使用的协议
- ECDHE 表示 key exchange 算法(Elliptic curve Diffie–Hellman)
- ECDSA 表示身份验证算法(Elliptic Curve Digital Signature Algorithm)。
- AES_128_GCM 表示数据加密算法(Advanced Encryption Standard 128 bit Galois/Counter Mode)。
- SHA256 是消息认证码(MAC)算法(Secure Hash Algorithm 256 bit)
此时我们可以看到身份验证算法也就是我们前面提到的数字签名算法,而消息认证码算法就是我们前面提到的数字摘要算法。这里我们还未介绍的就是 key exchange 算法 和 data encryption 算法(对称加密)。
- Compression Methods:这是一个将用于压缩数据(在加密之前)的方法列表。如果使用压缩,可以降低带宽使用,加快传输速度。然而,压缩是有风险的,不建议使用:请参考有关 CRIME and BREACH 攻击的信息。
- Extensions:客户端可以通过扩展来请求连接的其他功能。这可以通过支持 groups for elliptic curve cryptography、point formats for elliptic curve cryptography、signature algorithms 等进行。如果服务器无法提供额外的功能,客户端可以根据需要中止握手过程。
3.2.2 Server Hello(Server → Client)
在服务器收到客户端的 Hello 消息后,它会回复一个服务器 Hello 消息。服务器 Hello 消息可能包含已选取的选项(从客户端 Hello 提议的选项中选择),或者可能是一个握手失败的消息。
- Server Version:服务器从客户端提供的 TLS/SSL 协议版本中选择首选的版本。
- Server Random:这是一个 32 字节的随机数。服务器随机数和客户端随机数后来被用于生成加密密钥。在最初的 TLS 1.2 规范中,前 4 个字节应该表示客户端的当前日期和时间(以纪元格式),剩下的 28 个字节应该是一个随机生成的数字(就像客户端随机数的情况一样)。然而,IETF后来不建议这样做。
- Session ID:如果客户端会话 ID 不为空,服务器将搜索之前缓存的会话,并且如果找到匹配项,则使用该会话 ID 恢复会话。如果客户端会话 ID 为空,则服务器可能会创建一个新的会话,并将其发送到服务器会话 ID 中。
- Cipher Suites:服务器从客户端 Hello 中发送的密码套件中选择密码套件。
- Compression Methods:服务器从客户端Hello中发送的压缩方法中选择压缩方法。
3.3.3 Server Certificate(Server → Client)
服务器现在向客户端发送一个经过签名的 TLS/SSL 证书,证明了其身份。它还包含服务器的公钥。客户端收到服务器的公钥,后面可以使用公钥来加密信息,发送给服务器。
3.3.4 Client Certificate (Client → Server, Optional)
在极少数情况下,服务器可能需要客户端使用客户端证书进行身份验证。如果是这样,客户端将向服务器提供其经过签名的证书。
3.3.5 Server Key Exchange (Server → Client)
仅当服务器提供的证书对于客户端来说不足以进行 pre-master secret 交换时,服务器才发送服务器密钥交换消息。(这里的 pre-master secret 是为了后面的步骤生成 master secret,如果服务端提供的证书不足以生成 master secret,则 server 就会发送 server key exchange 消息)。这适用于DHE_DSS、DHE_RSA和DH_anon 方法。
3.3.6 Server Hello Done (Server → Client)
服务器发送此消息给客户端,以确认Server Hello消息已完成。
3.3.7 Client Key Exchange (Server → Client)
在接收到服务器发送的 Server Hello Done 消息后,客户端将发送 Client Key Exchange 消息。如果服务器要求客户端证书,则在此之后发送 Client Key Exchange 消息。在这个阶段,客户端创建一个 pre-master secret。
- Pre-Master Secret:客户端通过使用服务器提供的证书中提取的服务器公钥进行加密,创建 pre-master secret,并将其与服务器共享。在将 pre-master secret 发送给服务器之前,客户端使用服务器公钥进行加密。这意味着只有服务器可以解密消息,因为对于 pre-master secret 交换,使用了非对称加密(密钥对)。
- Master Secret:在服务器接收到 pre-master secret 后,它使用自己的私钥进行解密。现在,客户端和服务器使用之前交换的随机值(客户端随机数和服务器随机数)以及伪随机函数(PRF, Pseudo-Random Function)计算出主密钥。 PRF 是用于生成任意量伪随机数据的函数。
master_secret = PRF(pre_master_secret, "master secret", ClientHello.random + ServerHello.random) [0..47];
生成的 master secret 将作为对称加密算法的输入,用于客户端和服务器之间余下通信数据的对称加密/解密。master secret 的长度为 48 字节,可以用于会话期间的加密和解密操作。
客户端和服务器创建了一个包含3个密钥的集合:
- client_write_MAC_key: Authentication and Integrity check(身份验证和完整性检查)
- server_write_MAC_key: Authentication and Integrity check(身份验证和完整性检查)
- client_write_key: Message encryption using symmetric key (使用对称密钥进行消息加密)
- server_write_key: Message encryption using symmetric key (使用对称密钥进行消息加密)
- client_write_IV: Initialization Vector used by some AHEAD ciphers (一些 AHEAD 密码算法使用的初始化向量)
- server_write_IV: Initialization Vector used by some AHEAD ciphers (一些 AHEAD 密码算法使用的初始化向量)
客户端和服务器将使用 master secret 生成 session keys,这些 session keys 将用于加密/解密数据(对称加密)。
3.3.8 Client Change Cipher Spec (Client → Server)
在这一点上,客户端准备切换到安全的加密环境。更改密码规范协议(Change Cipher Spec protocol)用于更改加密方式。从现在开始,客户端发送的任何数据将使用对称共享密钥(前面提到的 session keys)进行加密。
3.3.9 Client Handshake Finished (Client → Server)
客户端在握手过程中的最后一条消息表示握手已经完成。这也是安全连接中的第一条加密消息。
3.3.10 Server Handshake Finished (Server → Client)
来自服务器的握手过程的最后一条消息(已加密发送)表示握手已经完成。
3.4 总结
从上面看到 TSL/SSL 握手过程中,涉及到协商的算法,身份认证(数字签名,不可否认性),消息认证码(Hash计算,数字摘要,完整性),数据加密(对称加密,私密性),数字证书(源认证)。
从客户端的角度来说:
服务端可以用私钥生成数字签名,客户端可以用服务端的公钥验证签名,满足不可否认性和源认证。
对于服务端和客户端,双方可以利用协商好的密钥(session keys)进行对称加密通信。满足私密性。
同时客户端和服务端,双方可以利用在握手阶段,密码套件中协商好的消息认证码算法(或者 hash 算法)验证数据是否被篡改,满足完整性。
所以从以上描述来说,HTTPS 是一个安全的通信协议。在建立连接的过程以及后续加密通信的过程中涉及到许多加密算法以及密钥交换算法。
4.引用