SSL and TLS (Part 2): Cryptography

SSL and TLS (Part 1): Brief Intro中简单介绍了一下SSL/TLS,并以需要解决的三个问题结尾。这三个问题是:

  1. 保密性(Confidentiality)
  2. 真实性(Authenticity)
  3. 完整性(Integrity)

这篇文章中,我们主要在密码学的角度,来看看如果通过密码学来解决上面的三个问题。

1. 角色登场

在解决问题之前,先看看在一个简单的场景中,都会有哪些角色。

首先是通信的双方。Alice和Bob通过互联网愉快地沟通。

由于通信链路的不安全,任何中间节点的人都可以监听Alice和Bob之间的对话,这也是SSL/TLS需要避免的问题。这里,链路中间多了一个中间人(Man in the Middle),我们把他叫做Mallory。

这样,一个简单的场景包含两个角色三个参与者:两个通信人Alice和Bob,一个中间人Mallory:

2. 对称加密(私钥加密)

就像钥匙和锁一样,一个简单的加密思路就是一把钥匙(secret key,秘钥)既可以将需要加密的文本(plaintext,明文)加密成别人看不出来的文本(ciphertext,密文);同时也可以使用密钥将密文解密成明文。就像下面的过程:

这就是对称加密算法(symmetric encryption),也叫私钥加密(private-key cryptography)。对称的意思是说一个秘钥即可以加密又可以解密;而私钥意味着,这个秘钥是需要保密的,不能让别人知道。

这样,如果Alice和Bob之间有一个只有他们两个人才知道的密钥并通过这个密钥进行加密,那么不知道密钥的Mallory是不知道他俩之间的通信内容的。

对称加密算法历史悠久,著名的就是凯撒密码。这是一种替换加密算法(substitution cipher),即使用字母表后三位的字母来替换明文中的字母。比如将明文中的a替换为d,以此类推。在这种加密算法中,没有密钥(其实也可以说3就是密钥),算法的安全性依赖于加密方法的保密性。如果敌人知道加密算法了,那么也就会解密了。

随着密码学的发展,一个加密算法需要满足下面的特征才能算是安全的:

一个攻击者即使知道关于加密算法的所有细节,但是不知道密钥,算法仍是安全的。

这时,密文的安全性依赖于密钥。如果密钥是从一个非常大的可选空间中选择的,并且破解这个密钥需要巨大的计算能力,那么这个加密算法就是计算安全的。

这样,如果我们有一个计算安全的加密算法,我们就解决了第一个问题:保密性,只要我们保证密钥的安全即可。

加密算法可以分为两种:流密码(stream cipher)和分组密码(block cipher)。

2.1 流密码

流密码(stream cipher),从名字就可以想象出这种加密算法的加密方式。把加密算法当做一个机器,每来一个字节明文经过这个机器,就输出一个字节的密文,直到所有的明文都经过加密。对于解密,就是过程反过来。

RC4是一种比较知名的流密码,它的加密过程如下:

算法的核心是一个有限长度的随机密钥流(keystream),然后用这个keystream对明文进行异或操作得到密文。解密的时候使用密文亦或keystream就可以得到明文了。

这个算法的一个特点是每个keystream只能使用一次,重复使用会增大被破解的概率。

RC4算法现在已经是不安全的了。

2.2 分组密码

分组密码(block cipher),就是对一块一块的明文进行加密得到一块一块的密文。现代的分组密码的分组大小一般是128位(16字节)。分组密码也可以看做是一个机器,输入一个分组的明文,机器一顿操作得到一个分组的密文。如果key一致,那么对于不同的明文,都会有唯一对应的密文。

分组密码有一些缺点:

  1. 只能加密一定长度的明文。使用分组密码需要对变长明文进行一定操作来满足要求(就是下面的padding填充);
  2. 分组密码是确定的,明文相同,那么对应的密文也相同。这个特性增大了被攻击的概率。

同时,分组密码也是好多加密方法的基础,比如哈希函数,消息验证码,伪随机数生成器,甚至流密码。

比较著名的分组密码是AES(Advanced Encryption Standard),分组的大小有128位,192位和256位可供选择。

在实际应用中,分组密码通常通过分组密码模式(block cipher mode)的方式来使用。模式就是在分组密码的基础上扩展的加密方式,使之方便使用。这里只介绍两个模式:ECB和CBC模式。

2.2.1 Electronic Codebook Mode

ECB,电子密码本模式,是最简单的加密模式。只对满足一定条件长度的明文进行加密,不满足的需要先使用padding方式填充。

加密时将明文分成一定长度的块,然后分别加密。

简单是它的缺点。

2.2.2 Cipher Block Chaining Mode

CBC,密码块链模式,通过引入初始向量值(initialization vector,IV)的方式来解决分组密码的确定性,这样,即使明文相同,不同时间加密后的密文也不一样:

初始向量IV的值是随机生成的(这里,又引出一个问题,怎么生成一个随机值呢?)。从上图可以看出Chaining是怎么形成的。

2.3 Padding

使用分组密码时,如果明文长度不满足条件,需要对明文进行padding操作。比如,AES需要的输入是128位,同时生成128位的密文。如果明文不是128位的倍数,那么就需要对最后一个不足128位的分组进行填充。

为了能让Bob知道Alice对最后一个分组填充了多少数据,填充的内容不能是随机的。在TLS中,最后一个字节标识填充字节的长度(除了最后一个字节),然后填充字节的内容和长度一致。比如:

Bob收到密文解密后查看最后一个分组的最后一个字节,内容是3,表示还需要去掉三个字节。这样就得到了明文。

3. 哈希函数

哈希函数(hash function)是一个将任意长的输入转换成固定长度输出的函数,结果也可以简单的叫哈希值(hash)。在编程语言中哈希函数很常用,但是这些都不适合在加密中使用。密码学中的哈希函数应该满足下面的要求:

  1. Preimage Resistance:就是说,给定一个哈希值,很难找到一个输入可以生成这个哈希值;
  2. Second Preimage Resistance:给定一个输入和对应的哈希值,很难找到一个不同的输入可以生成同样的哈希值;
  3. Collision Resistance:很难找到两个不同的输入可以得到相同的哈希值。

哈希函数对于比较大文件来说很有用。不用直接比较两个大文件,比较两个文件的哈希值就可以了。哈希函数也可以叫做指纹(fingerprints)、消息摘要(message digests)或摘要(digests)。

现在常用的哈希函数有SHA1,生成160位的结果,推荐使用更强的版本SHA256。

4. 消息验证码

哈希函数可以用于验证数据的完整性,因为对原始数据的一点点修改都会导致哈希值发生很大的变化。但是这需要数据和哈希值分开传输,否则Mallory就可以同时修改数据和对应的哈希值。

消息验证码(message authentication codes,MAC)在哈希函数的基础上增加了认证,也就是需要有一个hashing key,只有拥有hashing key的人才可以生成一个有效的MAC。

这样,当一个MAC和数据一起传输的时候,接收者Bob就可以通过hashing key和收到的MAC来检查数据是否被修改过。

使用哈希函数的消息验证码叫做HMAC(hash-based message authentication code)。实际上,HMAC通过安全的方式将hashing key和数据组合在一起。

这样,我们就解决了第三个问题:完整性

5. 非对称加密(公钥加密)

对称加密的一个优点是加密速度快。但是当参与通信的人越来越多的时候,对称加密就会有如下的缺点:

  1. 如果同一个群体成员使用相同的秘钥的话,那么随着成员的增加,密钥泄漏的风险也在增加;
  2. 如果不使用同一个密钥,每两个人使用一个密钥,那么随着成员的增加,秘钥将爆炸增长;
  3. 对于无人值守系统不能使用对称加密来保护数据。因为同一个秘钥既可以加密也可以解密。

非对称加密(asymmetric encryption,public-key cryptography)使用两个秘钥来进行加密和解密,一个秘钥是私有的,叫做私钥(private key),只能由私钥的所有者知道;另一个是公钥(public key),所有人都可以知道。

如果使用公钥加密,那么只有对应的私钥所有者才能解密;如果使用私钥加密,那么所有人都可以解密,因为私钥对应的公钥是公开的,所有人都可以知道。后一个加密方式可以当做一个数字签名,因为只有私钥持有人才可以用私钥加密。

非对称加密过程如下:

使用非对称加密可以解决大规模群体间的加密问题。任何人都可以使用公钥对私钥持有人发送加密消息;如果对方使用私钥加密,那么你也可以确切地知道对方是谁。

不过,非对称加密也有缺点:加密很慢,不适合大量数据。

RSA是现在最出名的非对称加密算法,推荐的秘钥长度是2048位。

6. 数字签名

数字签名(digital signature)是一种密码学方案,用来验证消息的真实性。MAC也可以用来验证消息的真实性,不过需要一个事先准备好私有的hashing key,这就是它的一个缺点。

通过非对称加密可以达到数字签名的作用。比如,使用RSA的私钥加密,那么只有对应的公钥才能解密:

  1. 计算一个需要签名的文件或数据的哈希值,不管文件或数据多大,哈希值总是固定长度的。比如SHA256的值就是256位;
  2. 将一些基本信息和哈希值放在一起,比如生成这个哈希值的算法;
  3. 将上面的数据使用私钥加密,结果就可以用来验证原始数据的真实性了。

接收者使用公钥解密,得到使用的哈希函数,用这个函数对文件或数据计算哈希值,如果这个值和接收到的哈希值一致,说明文件没有问题。

有了数字签名,我们就解决了第二个问题:真实性

7. 生成随机数

密码学中秘钥是一个重要的数据,需要随机生成。这就需要有一个随机数生成器。但是计算机生成的随机数有一定的可预测性,不能生成真随机数(true of random number),只能生成伪随机数(pseudorandom number)。通过seeding来生成伪随机数的过程就是伪随机数生成器(pseudorandom number generator,PRNG)。密码学中对随机数要求更高,需要使用密码学伪随机数生成器(cryptographic pseudorandom number generator,CPRNG)。

8. 混合在一起

前面介绍的内容都可以叫做密码原语(cryptographic primitive)。比如对称加密、哈希函数和非对称加密等。这些加密原语只做一件事情,单独使用不能保证通信的安全。因此,可以将一些密码原语组合在一起使用,形成加密方案或加密协议。

这里通过一个简单的例子,组合上面的密码原语构成一个加密协议,来保证Alice和Bob之间的通信安全。

首先Alice和Bob使用对称加密算法对数据进行加密,比如使用AES。这样,Mallory就不能通过观察的方式直接查看内容了。

但是Mallory可以劫持Alice和Bob之间的通信,篡改通信的内容而不会被Alice和Bob发现。不行,需要改进。

为了保证数据的完整性,Alice和Bob可以使用只有他们两人知道的hashing key对消息生成一个MAC,将MAC和加密后的密文一起传输,这样Mallory就不能篡改了,不然Alice和Bob就会发现。

不过Mallory还可以将劫持到的消息丢弃或重放,这时我们可以使用一个序列号,在计算MAC的时候把序列号放进去。这样当我们发现序列号缺失的时候,就知道了数据有丢失;序列号重复的时候,就检测到了一个重放攻击。最后,Alice和Bob使用一个特殊的消息标识会话结束。

到现在为止都还好,但是Alice和Bob怎么交换秘钥呢?首先可以在对话开始前使用公钥加密的方法传输一些信息,并验证对方是否是想要对话的人。这样就保证了真实性。

然后就可以通过秘钥交换协议来构造对称加密的秘钥了。常用的秘钥交换协议有RSA和Diffie-Hellman (DH)。

这样,我们就有了一个安全通信协议:

  1. 第一次握手验证真实性并构造一个加密的秘钥;
  2. 使用秘钥加密数据并构造MAC,保证保密性和完整性;
  3. 会话结束时使用特殊的会话终止消息标识。

这其实就和SSL/TLS的做法差不多了。

这篇文章从密码学的角度讨论了一些基本的密码学知识,并讨论如何使用这些基本的密码学方法构造一个可用的安全通信协议。对相应的密码学细节没有深入讨论,只是简单叙述。

To Be Continued…


 Previous
SSL and TLS (Part 3): Protocol SSL and TLS (Part 3): Protocol
在前面的文章中,我们从密码学的角度讨论了一些主要的密码原语(cryptographic primitive),最后通过组合这些密码原语构成一个可用的安全通信协议。 这篇文章更进一步,看看TLS是怎么做的。不过TLS的细节太多了也有点难,这里
2020-01-20
Next 
SSL and TLS (Part 1): Brief Intro SSL and TLS (Part 1): Brief Intro
在万物互联的时代,We don’t connect to the Internet, we are the Internet. 如此重要的互联网,需要一种协议来保护传输中的信息安全,那就是SSL(Secure Socket Layer)和T
2020-01-15
  You Will See...