【笔记】密码技术

《图解密码技术》一书的个人笔记

密钥空间 (keyspace),所有可用密钥的总数就是密钥空间的大小。密钥空间越大,暴力破解就越困难 使用被称为频率分析的密码破译方法,就能够破译简单替换密码

将密码算法和密钥分开的意义:密码算法是需要重复使用的,但在重复使用同一种算法的过程中,该算法被破译的可能性也在逐渐增大 ,我们就在密码算法中准备了一些可变部分,并在每次通信时都对这部分内容进行改变,而这一可变部分就是密钥。将密码算法和密钥分开考虑,就解决了希望重复使用,但重复使用会增加风险这个难题

即便经过标准化,密文的机密性也丝毫没有降低,这是因为密码算法和密钥是分开的。密钥才是秘密的精华。因此,在密码技术中,如何管理密钥是一个重要的课题

密码技术就是压缩技术

密码的作用

在这里插入图片描述

伪装:比如中间人攻击

第一部分 密码

对称密码

对同一比特序列进行两次XOR之后就会回到最初的状态

一次性密码本

原理:将明文与一串随机的比特序列进行XOR运算

一次性密码本绝对无法被破译:指即便拥有一种运算能力无穷大的计算机,可以在瞬间遍历任意大小的密钥空间(暴力破解),也依然无法破译

暴力破解,就是按顺序将所有的密钥都尝试一遍,并判断所得到的是不是正确的明文的方法。然而,在一次性密码本中,我们无法判断得到的是不是正确的明文,因此一次性密码本是无法破译的

无条件安全 (unconditionally secure)

几乎没有实用性。只是将“保管/配送明文”这一命题换成了“保管/配送和明文一样长的密钥”而已

密码的意义不在于密文让人看不懂,因为如论如何我们需要面对保管/配送秘密部分的问题,我们能做的只是把秘密部分[[#密码技术就是压缩技术|压缩]]。把隐藏明文变成隐藏密钥就是一种压缩,但一次性密码本没有有效压缩

DES

DES ( Data Encryption Standard)是1977年美国联邦信息处理标准 (FIPS) 所采用的对称密码

随着计算机的进步,现在DES可以在现实的时间内被暴力破解,因此不要使用DES

将64位明文加密为64位密文的对称密码算法。长于64位的明文需要分组迭代,64比特为一组密钥长度64位,其中8位用于校验,所以实质上密钥长度为56位

加密过程

DES使用16轮循环的Feistel网络。在Feistel网络里加密需要进行若干次“轮”的循环,其中一轮的计算流程:

在这里插入图片描述

  1. 首先,56位的主密钥会通过密钥调度算法被转换为16个48位子密钥,分别用于各轮
  2. 一轮开始后,一组64位的数据被分为左右部分(各32位),R部分与本轮子密钥通过轮函数f(R, k)得到中间结果,再与L部分进行异或运算,最终得到加密的左侧;右侧则不进行任何运算
  3. 每两轮处理之间,左右部分需要进行对调(否则右侧始终都不会被加密)。最后一轮结束后则不需要再左右对调

在这里插入图片描述
L1=F(R0, k0)⊕L0,R1=R0 L2=F(L1, k1)⊕R1,R2=L1

L16=F(L15, k15)⊕R15,R16=L15

解密过程

Feistel网络本身的结构在加密和解密时都是完全相同的。解密时算法和步骤都不变,只需要按逆序使用子密钥即可 在这里插入图片描述

证明一轮后的可解性:

L1=F(R0, k0)⊕L0,R1=R0
解密:L明文=F(R1, k0)⊕L1=F(R0, k0)⊕(F(R0, k0)⊕L0)=L0,R明文=R1=R0

在这里插入图片描述

DES特性(优势)

  1. 可以使用任意轮数
  2. 加密时选择任意轮函数都可以正确解密(解密和加密步骤一致,因此轮函数不需要存在反函数)
  3. 加密和解密可以用完全相同的结构来实现

选择明文攻击

选择明文攻击(Chosen Plaintext Attack,CPA):假设密码破译者可以选择任意明文并得到其加密的结果

  • 差分分析:针对分组密码的分析方法,思路是“改变一部分明文并分析密文如何随之改变”
  • 线性分析:思路是“将明文和密文的一些对应比特进行XOR并计算其结果为零的概率”

三重DES

3DES:将DES重复3次,增加了DES的强度(比DES能更好的应对差分分析和线性分析)

密钥长度:56×3=168位

加密

以密钥1、2、3的顺序执行加密→解密→加密

中间一步是DES解密(其实与DES加密步骤无异,只是逆序使用子密钥),这是为了兼容普通的DES

在这里插入图片描述

3DES使用3个不同密钥时称为DES-EDE3,密钥1和3相同、2不同时称为DES-EDE2。只使用1个密钥,即三次DES密钥相同时,3DES就等价于普通DES

解密

相反顺序:以密钥3、2、1的顺序执行解密→加密→解密

在这里插入图片描述

AES

AES(Advanced Encryption Standard):新标准的一种对称密码算法,使用Rijndael算法

完全公开免费,杜绝了隐蔽式安全性

Rijndael算法

输入分组为128位,即16字节

在AES规格中,分组长度固定为128位,密钥长度只有128、182、256位三种

加密

使用SPN结构:同样由多轮构成,每一轮分为SubBytes → ShiftRows → MixColumns → AddRoundKey 4个步骤

SubBytes:

在这里插入图片描述

ShiftRows:

在这里插入图片描述

MixColumns:

在这里插入图片描述

AddRoundKey:

与16字节 轮密钥 进行XOR 在这里插入图片描述

优势:

  • 输入的所有比特在一轮中都会被加密。和每轮都只加密一半输入的比特的 Feistel 网络相比,这种方式所需的轮数更少
  • SubBytes、ShiftRows 和 MixColumns可以分别以字节、行和列为单位进行并行计算
解密

AddRoundKey → InvMixColumns → InvShiftRows → InvSubBytes

除了AddRoundKey一步完全相同(异或),其它三步需要进行逆运算

使用哪种对称密码?

使用AES

分组密码的模式

  • 分组密码(block cipher):每次只能处理特定长度的一块数据的一类密码算法。一块即分组block,一个分组的位数即分组长度
    • DES和三重DES的分组长度为64位,一次性只能加密64位明文,生成64位密文
    • AES的分组长度为128位
  • 流密码(stream cipher):需要保持内部状态。一次性密码本属于流密码

模式:明文长度超过分组长度时需要对分组密码算法进行迭代,迭代的方法即模式 (mode)

主动攻击者 Mallory:可以主动介入发送者和接收者之间的通信过程,进行阻碍通信或者是篡改密文等活动

ECB模式

ECB (Electronic CodeBook):明文分组加密后直接成为密文分组

最后一个明文分组的内容小于分组长度时, 需要用一些特定的数据进行填充 (padding)

在这里插入图片描述

特点

明文分组与密文分组是一一对应的关系,只要观察一下密文就可以知道明文中存在怎样的重复组合,并以此为线索破译密码,因此ECB 存在风险

对ECB的攻击

攻击者无需破译密码就能够操纵明文(比如调换、删除、复制密文分组的顺序),他只要知道哪个分组记录了什么样的数据 (即电文的格式)就可以了

CBC模式

CBC (Cipher Block Chaining):密文分组链接。先将明文分组与前一个密文分组进行 XOR 运算,然后再进行加密

在这里插入图片描述

初始化向量IV

加密第一个明文分组时需要与初始化向量(Initialization Vector,IV )做XOR运算。一般来说,每次加密时都应随机产生一个不同的比特序列来作为初始化向量

每次加密时都改变初始化向量的值,那么即便是用同一密钥对同一明文进行加密,也可以确保每次所得到的密文都不相同

IV必须使用不可预测的随机数

AES-CBC模式

理论上来说,AES算法中密钥、IV、明文一致的情况下密文应该也一致

如果不一致可能是因为使用的库额外给密钥加了盐(或者使用了自动生成的随机IV)

为什么AES加密算法在同密钥加密时每次结果都不一样,并且还能解密成功?

[[java中使用AES-CBC模式+IV]]

特点

明文分组和密文分组不再是一一对应的关系,解决了ECB 模式的缺陷

密文分组中有一个分组损坏时,只要密文分组的长度没有变化,则解密时最多只会有2个分组受到影响;有比特缺失时,缺失比特之后的密文分组就全部无法解密了

对CBC的攻击

对初始化向量进行攻击:假设主动攻击者的目的是通过修改密文来操纵解密后的明文。反转初始化向量中任意比特,则解密后得到的明文分组中相应的比特也会被反转

填充提示攻击

填充提示攻击 (Padding Oracle Attack) 是一种利用分组密码中填充部分来进行攻击的方法。在分组密码中,当明文长度不为分组长度整数倍时,需要填充数据使最后一个分组凑满长度。在填充提示攻击中,攻击者会反复发送一段密文,每次发送时都对填充的数据进行少许改变。由于接收者在无法正确解密时会返回特殊的错误消息,攻击者通过错误消息就可以获得与明文相关的信息

这一攻击方式并不仅限于CBC模式,而是适用于所有需要进行分组填充的模式

要防御这种攻击,需要对密文进行认证,确保这段密文的确是由合法的发送者在知道明文内容的前提下生成的

shiro 721 反序列化漏洞复现与原理以及Padding Oracle Attack攻击加解密原理

Padding Oracle Attack(填充提示攻击)详解及验证

应用

SSL/TLS中使用

CFB模式

CFB(Cipher FeedBack):密文反馈模式。前一个密文分组会被送回到密码算法的输入端。对应的明文分组和密文分组之间只有 XOR

注意,CFB解密时,分组密码算法依然执行加密操作(因为密钥流是通过加密操作来生成的)

在这里插入图片描述

与CBC的对比

在CFB模式中,对应的明文分组和密文分组之间并没有“加密”这一步,只有 XOR
在这里插入图片描述

与流密码

CFB 模式中由分组密码算法所生成的比特序列称为 密钥流 (key stream)。分组密码算法相当于用来生成密钥流的伪随机数生成器(并非用于直接加密明文),而IV相当于伪随机数生成器的种子

这类似于一次性密码本,但是分组密码算法生成的比特序列(密钥流)并不是真随机,所以不具备一次性密码本的不可破译性

明文数据可以被逐比特加密,因此我们可以将 CFB 模式看作是一种使用分组密码来实现流密码的方式

对CFB的攻击

重放攻击 (replay attack):Mallory用之前保存的3个密文分组将今天发送的后3个替换。解密时,4个分组中就只有第1个可以正确解密,第2个会出错,第3第4个则变成了被替换的内容。Mallory没有破解密码,就成功地将以前的电文混入了新电文中。而第2个分组出错到底是通信错误呢,还是被人攻击所造成的呢?接收方无法判断。要做出判断,需要使用[[#重放攻击|消息认证码]]

在这里插入图片描述

OFB模式

OFB(Output-Feedback): 输出反馈模式。密码算法的输出会反馈到密码算法的输入中的流密码

在这里插入图片描述
在这里插入图片描述

和CFB的区别

密码算法的输入:

  • CFB 模式中,密码算法的输入是前一个密文分组,也就是将密文分组反馈到密码算法中
  • OFB 模式中,密码算法的输入则是密码算法的前一个输出,也就是将输出反馈给密码算法

加密顺序:

  • CFB加密时,无法跳过明文分组1而先对明文分组2进行加密
  • OFB模式中,XOR所需要的比特序列(密钥流)可以事先通过密码算法生成,和明文分组无关。可以提前准备好所需的密钥流,后续从明文生成密文的过程中就不需要用密码算法了。和AES等密码算法相比,XOR运算的速度是非常快的。生成密钥流的操作和进行XOR运算的操作可以并行

在这里插入图片描述

CTR模式

CTR(CounTeR):计数器模式。一种通过将逐次累加的计数器进行加密来生成密钥流的流密码

每个分组对应一个逐次累加的计数器,并通过对计数器进行加密来生成密钥流。也就是说,最终的密文分组是通过将计数器加密得到的比特序列,与明文分组进行XOR而得到的

在这里插入图片描述

计数器的生成方法

每次加密时都会生成一个不同的值(nonce)来作为计数器的初始值。当分组长度为16字节时,其中前8个字节为nonce,这个值在每次加密时必须都是不同的。后8个字节为分组序号,这个部分是会逐次累加的 在这里插入图片描述
用将计数器进行加密所得到的密钥流来模拟生成随机的比特序列

和OFB的区别

在这里插入图片描述

主动攻击者可以通过反转密文分组中的某些比特,引起解密后明文中的相应比特也发生反转。这一弱点和OFB模式相同。不过CTR模式具备一个比OFB模式要好的性质:在OFB模式中,如果对密钥流的一个分组进行加密后其结果碰巧和加密前是相同的,那么这一分组之后的密钥流就会变成同一值的不断反复。在CTR模式中不存在这一问题

特点
  • 可以以任意顺序对分组进行加密和解密,能够实现并行计算
  • 加密和解密使用完全相同的结构,这和同为流密码的OFB是一样的
GCM模式

在CTR模式的基础上增加“认证”功能的模式称为GCM模式(Galois/Counter Mode)。这一模式能够在CTR模式生成密文的同时生成用于认证的信息,从而判断“密文是否通过合法的加密过程生成”。通过这一机制,即便主动攻击者发送伪造的密文,我们也能够识别出“这段密文是伪造的”

应该使用哪种模式呢

模式名称优点缺点备注
ECBElectronic CodeBook 电子密码本- 简单
- 快速
- 支持并行计算(加、解密)
- 明文中的重复排列会反映在密文中
- 可以通过删除、替换密文分组对明文进行操作
- 对包含某些比特错误的密文进行解密时,对应的分组会出错
- 不能抵御重放攻击
不应使用
CBCCipher Block Chaining 密文分组链接模式- 明文的重复排列不会反映在密文中
- 支持并行计算(仅解密)
- 能够解密任意密文分组
- 对包含某些错误比特的密文进行解密时,第一个分组的全部比特以及后一个分组的相应比特会出错
- 加密不支持并行计算
CRYPTREC 推荐 《实用密码学》推荐
CFBCipher-FeedBack 密文反馈模式- 不需要填充
- 支持并行计算(仅解密)
- 能够解密任意密文分组
- 加密不支持并行计算
- 对包含某些错误比特的密文进行解密时,第一个分组的全部比特以及后一个分组的相应比特会出错
- 不能抵御重放攻击
CRYPTREC 推荐
OFBOutput-FeedBack 输出反馈模式- 不需要填充
- 可事先进行加、解密的准备
- 加、解密使用相同结构
- 对包含某些错误比特的密文进行解密时,只有明文中相对应的比特会出错
- 不支持并行计算
- 主动攻击者反转密文分组中的某些比特时,明文分组中相对应的比特也会被反转
CRYPTREC 推荐
CTRCounTeR 计数器模式- 不需要填充
- 可事先进行加、解密的准备
- 加、解密使用相同结构
- 对包含某些错误比特的密文进行解密时,只有明文中相对应的比特会出错
- 支持并行计算(加、解密)
- 主动攻击者反转密文分组中的某些比特时,明文分组中相对应的比特也会被反转CRYPTREC 推荐 《实用密码学》推荐

公钥密码

投币寄物柜:硬币是 关闭寄物柜的密钥 ,而钥匙则是打开寄物柜 的密钥

密钥配送问题

密钥配送问题(key distribution problem):在对称密码中,由于加密和解密的密钥是相同的,因此必须向接收者配送密钥

在这里插入图片描述

解决密钥配送问题的方法有以下几种:

通过事先共享密钥来解决

局限:如果所有参与加密通信的人都需要事先共享密钥,则密钥的数量会变得巨大,生产大量密钥可能不现实

通过密钥分配中心来解决

密钥分配中心 (Key Distribution Center, KDC):密钥分配中心会为每个人生成一个新密钥,这样一来,密钥分配中心拥有所有人密钥,而每个人拥有自己的密钥

Alice 再向 Bob 发送加密邮件时,就需要进行以下步骤 :

  1. Alice 向密钥分配中心发出希望与 Bob 进行通信的请求
  2. 密钥分配中心通过伪随机数生成器生成 一 个会话密钥,这个密钥是供 Alice 与 Bob 在 本次通信中使用的临时密钥
  3. 密钥分配中心从数据库中取出 Alice 的密钥和 Bob 的密钥
  4. 密钥分配中心用 Alice 的密钥对会话密钥进行加密,并发送给 Alice
  5. 密钥分配中心用 Bob 的密钥对会话密钥进行加密,并发送给 Bob
  6. Alice 对来自密钥分配中心的会话密钥(已使用 Alice 的密钥加密)进行解密,得到会话密钥
  7. Alice 用会话密钥对邮件进行加密,并将邮件发送给 Bob
  8. Bob 对来自密钥分配中心的会话密钥(已使用 Bob 的密钥加密)进行解密,得到会话密钥
  9. Bob 用会话密钥对来自 Alice 的密文进行解密
  10. Alice 和 Bob 删除会话密钥

局限:密钥分配中心负荷大;主动攻击者可能会对密钥分配中心下手

通过 Diffie-Hellman 密钥交换来解决

进行加密通信的双方需要交换一些可公开的信息,根据所交换的信息,双方可以各自生成相同的密钥,而窃听者却无法生成相同的密钥

通过公钥密码来解决

发送者使用公钥对通信内容进行加密并发送给接收者,而只有拥有私钥的人(即接收者本人)才能够进行解密。这样一来,就用不着将私钥配送给接收者了

公钥密码

公钥密码(public-key cryptography)/非对称密码 中,密钥分为加密密钥(公钥,public key)和解密密钥(私钥,private key)两种

  • 发送者用公钥对消息进行加密,接收者用私钥对密文进行解密
  • 发送者只需要公钥,接收者只需要私钥
  • 私钥没有机会被窃听者获取;公钥被窃听者获取也没问题,可以随意公开
  • 任何人都能发送用公钥加密的信息,而特定的拥有私钥的人才能解密

密钥对(key pair):由公钥进行加密的密文必须使用与该公钥配对的私钥才能够解密。密钥对中的两个密钥之间具有密切关系(数学上的关系),因此公钥和私钥是不能分别单独生成的

公钥密码的使用者需要生成一个包括公钥和私钥的密钥对,其中公钥会被发送给别人,而私钥则仅供自己使用 → 由接收者分配公钥并发启通信

公钥通信的流程

在公钥密码通信中,通信过程是由接收者 Bob 来启动的:

  1. Bob 生成一个包含公钥和私钥的密钥对。私钥由 Bob 自行妥善保管

  2. Bob 将自己的公钥发送给 Alice。Bob的公钥被窃听者 Eve 截获也没关系。将公钥发送给 Alice,表示 Bob 请 Alice 用这个公钥对消息进行加密并发送给他

  3. Alice 用 Bob 的公钥对消息进行加密。加密后的消息只有用 Bob 的私钥才能够解密。虽然 Alice 拥 有 Bob 的公钥,但用 Bob 的公钥是无法对密文进行解密的

  4. Alice 将密文发送给 Bob。密文被窃听者 Eve 截获也没关系。Eve 可能拥有 Bob 的公钥,但是用 Bob 的公钥是无法进行解密的

  5. Bob 用自己的私钥对密文进行解密

在这里插入图片描述

无法解决的问题
  • [[#中间人攻击|公钥认证问题]]:需要判断得到的公钥是否正确合法
  • 一般来说,在采用具备同等机密性的密钥长度的情况下,公钥密码的处理速度只有对称密码的几百分之一。因此,公钥密码并不适合用来对很长的消息内容进行加密

另外,公钥密码中发送方和接收方的角色是固定的(一次密钥配送后),且接收方不能确定发送方是谁,这意味着攻击者可以进行伪装。在这个过程中,接收者只是单向接受任意多的发送者发来的信息 在这里插入图片描述

时钟运算

某个数X是否存在关于模N的模逆元/模倒数(x * y mod N = 1),可以通过它是否与N互质(与N的最大公约数为1/与N的公约数只有1),即是否满足 gcd(X, N) = 1 判断

离散对数:能快速求出离散对数的算法到现在还没有被发现

RSA

RSA:可以被用于公钥密码和数字签名。密钥长度(指模数N的长度)可选,但推荐2048比特,即256字节(更短则可能不再足够安全,更长则会增加计算复杂性)

密钥长度=模数N的长度=密文长度,RSA的特点是密文长度固定

可加密的明文长度限制:密钥字节数 - 填充字节数。假设使用PKCS#1填充(常用)+ 2048位RSA密钥,则最大可加密数据长度为 2048 / 8 - 11 = 245 字节

数据再长则不建议使用公钥密码(处理速度低)

数学特性:密文 = 明文^E mod N,明文=密文^D mod N,可以看出公钥指数D和E互为关于模N的模逆元(即模倒数)

加密

在 RSA 中,明文、密钥和密文都是数字

RSA加密:密文 = 明文^E mod N。E是公钥指数,E 和 N 的组合是公钥,表示为:公钥是(E, N)

因此只要知道 E 和 N 这两个数,任何人都可以完成加密运算

解密

RSA 解密:明文=密文^D mod N。D是私钥指数,D 和 N 的组合是私钥,其中N与公钥中的N一致,可以公开,所以也可以单独称D为私钥

在这里插入图片描述

生成密钥对的步骤

公钥指数D和E互为关于模N的模逆元,所以在有E的情况下,我们需达成一定条件使D存在

(1)求N

首先准备两个很大的质数 p和q,假设大小都是512比特。要求出这样大的质数,需要通过伪随机数生成器不断生成512比特大小的数,直到这个数是质数

N = p * q (p、q 为质数)

N 必须大于要加密的明文:由于解密运算时要求 mod N,而 mod N 的结果必定小于N,因此如果明文本身大于N,则解密后无法得到正确明文

这里的“大于”比的不是长度,是数字大小

(2)求L

L是仅在生成密钥对的过程中使用的数,是 p-1 和 q-1 的最小公倍数

L = lcm(p - 1, q - 1)

(3)求E

E 是一个比1大、比L小的数。此外,E 和 L 的最大公约数 gcd 必须为1(这样才能保证一定存在E的模逆元D):

1 < E < L, gcd(E, L) = 1

需要使用伪随机数生成器在 1 < E < L 的范围内生成 E 的候选数,然后再判断其是否满足 gcd(E, L) = 1

(4)求D

1 < D < L, E * D mod L = 1

在这里插入图片描述

对 RSA 的攻击

破译者知道的:密文、E 和 N 破译者不知道的:明文、D、生成密钥对时使用的 p、q 和 L

通过密文来求得明文

通过 密文=明文^E mod N 倒推明文,本质就是求密文的离散对数,但是求离散对数没有高效算法

通过暴力破解来找出D

现在,RSA中所使用的p和q的长度都在1024比特以上,N的长度为2048比特以上。由于E和D的长度可以和N差不多,因此要找出D,就需要进行2048比特以上的暴力破解,这极其困难

通过 E 和 N 求出 D

E * D mod L = 1 倒推:破译者不知道质数p和q,所以也不知道L

对 N 进行质因数分解攻击

对 N 进行质因数分解求出 p 和 q:一旦发现了对大整数进行质因数分解的高效算法,RSA就能够被破译,但目前还没有这样的高效算法

通过推测 p 和 q 进行攻击

如果伪随机数生成器的算法很差,破译者就有可能推测出来 p 和 q,因此使用能够被推测出来的随机数非常危险

中间人攻击

中间人攻击 (man-in-the-middle attack):一种伪装性的攻击。虽然不能破译 RSA,但却是一种针对机密性的有效攻击。主动攻击者 Mallory 混入发送者和接收者的中间,对发送者伪装成接收者,对接收者伪装成发送者

在这里插入图片描述

这种攻击不仅针对 RSA,而是可以针对任何公钥密码。要防御中间人攻击,还需要一种手段来确认所收到的公钥是否真的属于 Bob,这种手段称为认证。在这种情况下,我们可以使用公钥的证书

选择密文攻击

选择密文攻击 (Chosen Ciphertext Attack):利用解密提示 (Decryption Oracle),“发送任意数据,服务器都会将其当作密文来解密并返回解密的结果”。通过选择密文攻击并不能破译 RSA。但是研究者发现,通过选择密文攻击,攻击者能够获得关于密文所对应的明文的少量信息(原理类似于填充提示攻击)

RSA-OAEP (Optimal Asymmetric Encryption Padding,最优非对称加密填充):对密文进行“认证”的一种RSA改良算法,能够抵御选择密文攻击。在加密时会在明文前填充认证信息,包括明文的散列值以及一定数量的0,然后再对填充后的明文用 RSA 加密。在解密时,如果解密后的数据的开头没有正确的认证信息,则可以断定“密文不是由知道明文的人生成的”,并返回固定的错误消息 decryption error (重点:不能将具体的错误内容告知发送者)。在实际运用中,RSA-OAEP 还会通过随机数使每次生成的密文呈现不同的排列方式

RSA-OAEP不能解决中间人攻击问题,因为在中间人问题中,明文本身也可能是被伪造的

其他公钥密码

  • RSA:利用质因数分解的困难度
  • EIGamal 方式:利用求离散对数的困难度。缺点是经过加密的密文长度会变为明文的两倍
  • Rabin 方式:利用了 mod N 下求平方根的困难度
  • 椭圆曲线密码 (Elliptic Curve Cryptography, ECC) :特点是所需的密钥长度比 RSA 短。通过将椭圆曲线上的特定点进行特殊的乘法运算来实现的,利用了这种乘法运算的逆运算非常困难这一特性

一定程度上公钥密码都是利用了某种数学运算的逆运算的困难度

其他

在这里插入图片描述

别人生成的质数组合和自己生成的质数组合偶然撞车的可能性,事实上可以认为是没有的。512比特能够容纳的质数的数量大约为10的150次方,这个数量比整个宇宙中原子的数量还要多

对称密码通过将明文转换为复杂的形式来保证其机密性,相对地,公钥密码则是基于数学上困难的问题来保证机密性的。两者源于两种根本不同的思路

混合密码系统

混合密码系统 (hybrid cryptosystem):在一般的通信过程中,往往会配合使用对称和非对称密码

用对称密码提高处理速度,用公钥密码解决密钥配送问题。主要解决了公钥密码处理速度低的问题,而解决中间人攻击问题需要对公钥进行认证

用接收者提供的公钥密码加密会话密钥,用会话密钥作为对称密码的密钥加密消息。最终发送的是 公钥密码加密的会话密钥 和 对称密码加密的消息 的组合

加密

在这里插入图片描述

解密

在这里插入图片描述

其他组合技术

  • 数字签名:由单向散列函数和公钥密码组合而成
  • 证书:由公钥和数字签名组合而成
  • 消息认证码:由单向散列函数和密钥组合而成,也可以通过对称密码生成
  • 伪随机数生成:可以使用对称密码、单向散列函数或者公钥密码构建

第二部分 认证

单向散列函数(哈希函数)

单向散列函数 (one-way hash function):即哈希函数、消息摘要函数 (message digest function)

用于保证消息的完整性,防御篡改

散列值的长度和消息的长度无关。无论消息多长,单向散列函数都会计算出固定长度的散列值

性质

  1. 根据任意长度的消息计算出固定长度的散列值,且散列值越短越好

  2. 能够快速计算出散列值

  3. 具备 抗碰撞性 (collision resistance),即很难产生碰撞(指两个不同的消息产生同一个散列值)

    • 弱抗碰撞性:当给定某条消息的散列值时,单向散列函数必须确保要找到和该条消息具有相同散列值的另外一条消息是非常困难的
    • 强抗碰撞性:要找到散列值相同的两条不同的消息是非常困难的(防御生日攻击)
    • 密码技术中所使用的单向散列函数, 不仅要具备弱抗碰撞性,还必须具备强抗碰撞性
    • (只能做到“很难碰撞”,无法做到“不存在碰撞”)
  4. 具备单向性(one-way),无法通过散列值反算出消息的性质

    • 根据消息计算散列值可以很容易,但这条单行路是无法反过来走的。这点在基于口令的加密和伪随机数生成器等技术中大有运用
    • 所以单向散列函数不是密码

实际应用

  • 检测软件是否被篡改

    • 对比散列值可知
  • 用于[[#基于口令的密码 (PBE)|基于口令的加密]]

    • 将口令和盐混合后计算其散列值,然后将这个散列值用作加密的密钥。能够防御针对口令的字典攻击
  • 构造消息认证码

    • 消息认证码是将“发送者和接收者之间的共享密钥”和“消息”进行混合后计算出的散列值。可以检测并防止通信过程中的错误、篡改以及伪装
  • 用于数字签名

    • 数字签名的处理过程非常耗时,因此先通过单向散列函数计算出消息的散列值,再对这个散列值施加数字签名
  • 构造一次性口令 (one-time password)

    • 一次性口令经常被用于服务器对客户端的合法性认证。通过使用单向散列函数可以保证口令只在通信链路上传送一次 (one-time),因此即使窃听者窃取了口令也无法使用

具体例子

MD4、MD5

MD (Message Digest),都已经不安全了

SHA-1

不推荐使用

SHA-2 (SHA-256 、 SHA-384 和 SHA512)

在这里插入图片描述

RIPEMD-160

比特币中使用的是 RIPEMD-160

SHA-3

公开竞争选拔出了 Keccak 算法

Keccak

Keccak 是一种被选定为 SHA-3 标准的单向散列函数算法

可以生成任意长度的散列值,但为了配合 SHA-2 的散列值长度,SHA-3 标准中共规定了 SHA3-224、 SHA-3-256、SHA3-384、SHA3-512 这4种版本。在输入数据的长度上限方面 SHA-3 没有长度限制

海绵结构

采用了与 SHA-1、SHA-2 完全不同的海绵结构 (sponge construction)

在这里插入图片描述

吸收阶段:

函数 f 的作用是将输入的数据进行复杂的搅拌操作并输出结果(输入和输出的长度均为 b =r+c 个比特),其操作对象是长度为 b=r+c 个比特的内部状态,内部状态的初始值为 0。也就是说,通过反复将输入分组的内容搅拌进来,整个消息就会被一点一点地“吸收”到海绵结构的内部状态中,就好像水分被一点一点地吸进海绵内部一样。每次被吸收的输入分组长度为 r 个比特,因此 r 被称为 比特率 (bit rate)

内部状态中有 c 个比特是不受输入分组内容的直接影响的(但会通过函数 f 受到间接影响)。c 被称为 容量 (capacity)

挤出阶段:

挤出阶段中实际上执行的是“对内部状态进行搅拌并产生输出分组 (r 个比特)”的操作,也就是以比特率 (r 个比特) 为单位,将海绵结构的内部状态中的数据一点一点地挤出来。在挤出阶段中,内部状态的容量 (c个比特) 部分是不会直接进入输出分组的,这部分数据只会通过函数 f 间接影响输出的内容。因此,容量 c 的意义在于防止将输入消息中的一些特征泄漏出去

双工结构

海绵结构的变形

在这里插入图片描述

在海绵结构中,只有将输入的消息全部吸收完毕之后才能开始输出,但在双工结构中,输入和输出是以相同的速率进行的。通过采用双工结构,Keccak 不仅可用于计算散列值,还可以覆盖密码学家的工具箱中的其他多种用途,如伪随机数生成器、 流密码、认证加密、消息认证码等

Keccak 的内部状态

内部状态是一个三维的比特数组,如下图。图中的每个小方块代表 1 比特,b个小方块按照 5 * 5 * z 的方式组合成一个沿 z 轴延伸的立方体。将具备 x、y、z 三个维度的内部状态整体称为 state,state 共有 b 个比特。将 xz 平面称为 plane,将 xy 平面称为 slice,将 yz 平面称为 sheet。将 x 轴称为 row,将 y 轴称为 column,将 z 轴称为 lane 在这里插入图片描述

Keccak 的本质就是实现一个能够将上述结构的 state 进行有效搅拌的函数 f,这与分组密码设计中的搅拌过程非常相似。此外,由于内部状态可以代表整个处理过程中的全部中间状态,因此有利于节约内存。Keccak 用到了很多比特单位的运算,因此被认为可以有效抵御针对字节单位的攻击

函数 Keccak-f[b]

负责对内部状态进行搅拌的函数 f,参数b即内部状态的比特长度,此处称为宽度 (width)

根据 Keccak 的设计规格,宽度 b 可以取 25、50、100、200、400、800、1600 共 7 种值。SHA-3 采用的是最大宽度,即 b = 1600,内部状态 state = 5 * 5 * 64

Keccak-f[b] 中的每一轮包含 5 个步骤: θ、ρ、π、χ、ι。SHA-3 中所使用的 Keccak-f[1600] 函数,其循环轮数为 24

具体步骤请另查

对Keccak的攻击

Keccak 之前的单向散列函数都是通过循环执行压缩函数的方式来生成散列值的,这种方式称为 MD 结构。MD4、MD5、RIPEMD、RIPEMD-160、SHA-1、SHA-2 等几乎所有的传统单向散列函数算法都基于 MD 结构

目前为止,还没出现能够对实际运用中的 Keccak 算法形成威胁的攻击方法

应该使用哪种单向散列函数

  • MD5 是不安全的,不应该使用
  • SHA-1 不应该被用于新的用途,而是应该迁移到 SHA-2
  • SHA-2 有效应对了针对 SHA-l 的攻击方法,因此是安全的,可以使用 √
  • SHA-3 是安全的,可以使用 √

对单向散列函数的攻击

暴力破解

由于尝试次数纯粹是由散列值长度决定的,因此散列值长度越长的单向散列函数,其抵御暴力破解的能力也就越强。暴力破解需要尝试的次数在现实中是不可能完成的

生日攻击

原本的合同也由主动攻击者提供,在接收方确认后将其替换为事先准备的散列值相同的假合同

不是寻找生成特定散列值的消息,而是要事先找到散列值相同的两条消息(散列值则可以是任意值),最后达成两条消息可以互相替换而不被单向散列函数检查出的效果。这样的攻击称为生日攻击 (birthday attack) 或者冲突攻击 (collision attack),是一种试图破解强抗碰撞性的攻击

生日悖论 (birthday paradox)

在这 N 个人中,如果要保证至少有两个人生日一样的概率大于二分之一,那么 N 至少是多少? 在这里插入图片描述
N=23 时,这个值约等于 0.507297。N=100 时,这个值接近1。两个人的生日都是某特定日期(针对弱抗碰撞性) 的可能性确实不高,但如果是 只要有两个人生日相同,不管哪天都可以(针对强碰撞性) 的话,可能性却是出乎意料的高的。这种与直觉相违背的现象就是生日悖论

将生日问题一 般化,即:“假设 一 年Y 天,那么N人的集合中至少有两个 人生日一样的概率大于二分之一时,N 至少是多少?”。当 Y 非常大时,近似的计算结果为: N ≈ 根号Y,即一年天数的平方根

在生日攻击种,主动攻击者可以生成N个含义是a的消息和N个含义是b的消息,对比寻找是否有散列值一样的情况。需要的N越大,攻击难度越高,N与散列值长度相关

假设散列值长度为 M 比特,则 M 比特所能产生的全部散列值的个数为2^M个。所以 N ≈ 根号(2^M) ≈ 2^(M/2)。当 N= 2^(M/2) 时,生日攻击就会有二分之一的概率能够成功,比暴力破解所需尝试次数少得多

但依然困难,单向散列函数需要保证这一点

局限

无法辨别伪装:有些情况下即便能够检查完整性也是没有意义的。单向散列函数能够辨别出“篡改”,但无法辨别出“伪装”,为此我们需要认证技术(消息验证码、数字签名)

消息认证码

消息认证码 (Message Authentication Code, MAC):输入包括 任意长度的消息共享密钥,可以输出固定长度的数据,这个数据称为 MAC 值。mac = MAC(key, text)

防止了功能利用什么性质实现
篡改确认了消息完整性和单向散列函数的散列值一样,哪怕消息中发生1比特的变化,MAC值 也会产生变化
伪装可以进行认证要计算MAC必须持有共享密钥,没有共享密钥的人就无法计算MAC值

为避免误会需要说明,对称密码本身就能防止伪装,为什么呢? 因为使用对称密码的前提是双方有绝对安全的方式共享同一密码。只要隐含的“密钥配送”是安全的,对称密码就能防止伪装。只要只有两个人共享密钥,那接收者必然能确定发送者是谁。然而,绝对安全的共享密钥配送不容易实现,或者说不是每种场景都能保证安全配送共享密钥,这就是我们需要公钥密码的原因。而伪装,实际上是公钥密码要面对的问题,为什么呢?因为发送者使用不保密的公钥加密,接收者就不清楚发送者究竟是谁,别说伪装了,这种场景下其实是确定的一方(接收者)+完全不能确定的一/多方(发送者)。虽然接收者是确定的,但是“伪装”自然是伪装提供信息的一方。况且更进一步,在中间人攻击中连接收者的身份都不一定能够保证。 那么为什么使用了公钥密码技术的数字签名却能防止“伪装”呢? 那是因为在数字签名里公钥密码是被反向利用的,我们其实是保证了签名(提供信息)的一方无法被伪装,至于验证签名的一/多方,我签名就是为了让任何人都能验证的,你是谁我干嘛要在乎呢?(不过依然解决不了中间人攻击问题,这需要社会性基础设施,即认证机构颁发证书) 简而言之,这纯粹是一个不同场景不同应用的问题: 消息验证码/对称密码保证的是双方间双向提供的认证(防止伪装),保证不了多方间的认证/防止否认,适用于双方互相提供信息的场景; 数字签名保证的是一方向多方(单向)提供的认证和防止否认,适用于一方向一/多方提供信息的场景 (考虑这种问题时可以想象下通信过程中每一方如何认知其他方,能否确定对面是谁)

消息认证码是一种与密钥相关联的单向散列函数

在这里插入图片描述

密钥配送问题在消息认证码中也会发生。要解决密钥配送问题,我们需要使用一些共享密钥的方法,例如公钥密码、Diffie-Hellman密钥交换、密钥分配中心,或者使用其他安全的方式发送密钥等

为什么不直接使用对称密码防止篡改、伪装呢?

要判断用对称密码解密之后得到的明文是“正确”的,就需要明文具备某种特定的结构。如果明文本身是无特定结构的随机比特序列,那么解密后无法分辨是否被篡改。所以需要消息认证码

使用步骤

在这里插入图片描述

应用实例

  • SWIFT:银行和银行之间
  • IPsec
  • SSL/TLS

实现方法(MAC算法)

使用单向散列函数实现

使用 SHA-2 之类的单向散列函数可以实现消息认证码,其中一种实现方法称为 HMAC

使用分组密码实现

使用 AES 之类的分组密码可以实现消息认证码。将分组密码的密钥作为消息认证码的共享密钥来使用,并用 CBC 模式将消息全部加密。此时,初始化向量 (IV) 是固定的。由于消息认证码中不需要解密,因此将密文的最后一个分组用作 MAC 值。CBC 模式的最后一个分组会受到整个消息以及密钥的双重影响,因此可以将它用作消息认证码

其他

使用流密码和公钥密码等也可以实现消息认证码

认证加密

认证加密 (AEAD) 是一种将对称密码与消息认证码相结合同时满足机密性、完整性和认证三大功能的机制

Encrypt-then-MAC

先用对称密码将明文加密,然后计算密文的MAC值。消息认证码的输入消息是密文,通过MAC值就可以判断“这段密文的确是由知道明文和密钥的人生成的”。使用这一机制可以防止攻击者通过发送任意伪造的密文,并让服务器解密来套取信息的攻击(选择密文攻击)。c1 = E(key1, clearText), mac = MAC(key2, C1), chiperText = c1 || mac

Encrypt-and-MAC

将明文用对称密码加密,并对明文计算MAC值。chiperText = E(key1, ClearText) || MAC(key2, clearText)

MAC-then-Encrypt

先计算明文的 MAC 值,然后将明文和MAC值同时用对称密码加密)。chiperText = E(key1, clearText || MAC(key2, clearText))

被SSL/TLS使用

Hash-then-Encrypt

先对明文进行hash运算,添加在明文末尾,然后用对称密码加密。chiperText = E(key, clearText || Hash(clearText))

Hash-then-Encrypt类似于RSA-OAEP?

GCM (Galois/Counter Mode)

使用AES等128比特分组密码的CTR模式加密,并使用一个反复进行加法和乘法运算的散列函数来计算MAC值。CTR模式下可通过对若干分组进行并行处理来提高运行速度。此外,CTR 模式加密与MAC值的计算使用相同密钥,因此在密钥管理方面也更加容易。专门用于消息认证码的 GCM 称为 GMAC

HMAC

使用单向散列函数来构造消息认证码的方法,H就是Hash的意思。任何高强度的单向散列函数都可以被用于HMAC,没有其他限制。例如,使用SHA-256构造的HMAC称为HMAC-SHA-256

计算MAC值的步骤

在这里插入图片描述

  1. 密钥填充:如果密钥比单向散列函数的分组长度(散列值长度)短,就在末尾填充0。如果密钥比分组长度要长,则用单向散列函数求出密钥的散列值,然后将散列值用作HMAC的密钥

  2. 将填充后的密钥与ipad进行XOR运算:ipad是将00110110这一比特序列(即16进制的36)不断循环反复直到达到分组长度所形成的比特序列,其中i是inner的意思。XOR运算所得到的值称为ipadkey,它与单向散列函数的分组长度相同,且和密钥相关

  3. 与消息组合:ipadkey + 消息

  4. 计算散列值:将组合后的结果输入单向散列函数计算散列值

  5. 将填充后的密钥与opad进行XOR运算:opad是将01011100这一比特序列(即16进制的5c)不断循环反复直到达到分组长度所形成的比特序列,其中o是outer的意思。XOR 运算所得到的结果称为opadkey

  6. 与散列值组合:opadkey + (4)中的散列值

  7. 计算散列值:将 (6) 的结果输入单向散列函数,并计算出散列值,即最终的 MAC 值。它一定是一个和输入的消息以及密钥都相关的长度固定的比特序列

对消息认证码的攻击

重放攻击

重放攻击 (replay attack):Mallory并没有破解消息认证码,而只是将发送方的正确MAC值保存下来重复利用而已

在这里插入图片描述

防御重放攻击的方法
  • 序号

    • 约定每次都对发送的消息赋予递增的编号,并且在计算 MAC 值时将序号也包含在消息中。这样一来,Mallory 无法计算序号递增之后的 MAC 值
    • 缺点:对每个通信对象都需要记录最后一个消息的序号
  • 时间戳

    • 约定在发送消息时包含当前的时间,如果收到以前的消息,即便 MAC 值正确也将其当做错误的消息来处理,这样就能够防御重放攻击
    • 缺点:发送者和接收者的时钟必须一致,而且考虑到通信的延迟,必须在时间的判断上留下缓冲,所以多多少少存在可以进行重放攻击的空间
  • nonce

    • 通信之前接收者先向发送者发送一个一次性随机数 (nonce)。发送者在消息中包含 nonce 并计算 MAC 值
    • 缺点:通信的数据量会有所增加
密钥推测攻击

对消息认证码也可以进行暴力破解以及生日攻击。对于消息认证码来说,应保证不能根据 MAC 值推测出通信双方所使用的密钥。例如 HMAC 中就是利用单向散列函数的单向性和抗碰撞性来保证无法根据 MAC 值推测出密钥的。此外,在生成消息认证码所使用的密钥时,必须使用密码学安全的、高强度的伪随机数生成器

无法解决的问题

对第三方证明

第三方Victor没有共享密钥,因此无法校验MAC值。即使接收方Bob把密钥告知Victor,Victor确认了MAC值正确,他也无法判断消息是由Alice发送的还是Bob发送的

能够计算出正确 MAC 值的人只有 Alice 和 Bob,在两方通信时,可以断定是对方计算了 MAC 值。 然而,对于第三方 Victor,Alice 或 Bob 却无法证明是对方计算了 MAC 值,而不是自己

可以用 数字签名 解决

防止否认 (nonrepudiation)

发送者Alice可以向第三方Victor否认 (repudiation)自己向Bob发送过某消息,而Bob无法向Victor证明Alice发送过

消息认证码之所以无法防止否认,是因为消息认证码需要在Alice和Bob之间共享同一个密钥,Alice和Bob都可以计算出正确的MAC值

可以用 数字签名 解决

数字签名

使用数字签名(digital signature)可以识别篡改伪装,还可以防止否认

消息认证码之所以无法防止否认,是因为消息认证码需要在Alice和Bob之间共享同一个密钥。那么如果他们各自使用自己才有的私钥?

数字签名

数字签名中出现了下面两种行为:

  • 生成消息签名:

    • 由消息的发送者Alice来完成的。生成签名就是根据消息内容计算数字签名的值,这个行为意味着“我认可该消息的内容”。特定的签名者(私钥)与特定的消息绑定在了一起
  • 验证数字签名:

    • 一般是由消息的接收者Bob完成,但也可以由需要验证消息的第三方Victor完成

在数字签名中,生成签名和验证签名这两个行为需要使用各自专用的密钥来完成:使用“签名密钥”来生成消息的签名,使用“验证密钥”来验证消息的签名。签名密钥只能由签名的人持有,而验证密钥则是任何需要验证签名的人都可以持有

数字签名如何防止否认?只有持有私钥的人才能对该条消息签名,反过来说,被正确签名了的消息只能是持有私钥的人发的。用私钥作为签名者身份证明

公钥密码与数字签名

简而言之,数字签名就是通过将公钥密码“反过来用”而实现的:

私钥公钥
谁持有密钥?个人持有只要需要,任何人都可以持有
公钥密码接收者解密时使用发送者加密时使用
数字签名签名者生成签名时使用验证者验证签名时使用

如果用某个公钥成功解密了密文,那么就能够证明这段密文是用与该公钥配对的私钥进行加密所得到的。用私钥进行加密这一行为只能由持有私钥的人完成,正是基于这一事实,我们才可以将用私钥加密的密文作为签名来对待

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

数字签名的方法

直接对消息签名的方法

在这里插入图片描述

对消息的散列值签名的方法

公钥密码算法慢,不适合直接对消息加密

在这里插入图片描述

应用实例

安全信息公告

信息发布的目的是尽量让更多的人知道,因此我们没有必要对消息进行加密,但是必须排除有人恶意伪装成该组织来发布假消息的风险。对明文消息所施加的签名,一般称为明文签名 (clearsign)

软件下载

软件作者可以对软件加上数字签名,只要在下载后验证数字签名就可以识别出软件是否遭到篡改

一种名为带签名的Applet的软件就是具体的例子。这种软件用Java编写(一种浏览器进行下载并执行的软件),并加上了作者的签名,浏览器会在下载之后对签名进行验证

此外,在 Android 系统中是无法安装没有数字签名的应用软件的。在签署数字签名时,为了识别应用开发者的身份,需要使用证书。证书包含开发者的信息,例如名称、组织等。但是,这个证书并不一定是由认证机构 (Certificate Authority) 签名的

不过,数字签名只是能够检测软件是否被篡改过,并不能保证软件本身不会做出恶意的行为

公钥证书

在验证数字签名时需要保证公钥是合法的(属于自己的通信对象),所以我们可以将公钥当作消息,对它加上数字签名。像这样对公钥施加数字签名所得到的就是公钥证书

那给公钥施加数字签名时使用的公钥又怎么判断合不合法? 让认证机构介入

SSL/TLS

SSL/TLS在认证服务器身份是否合法时会使用服务器证书,它就是加上了数字签名的服务器公钥。相对地,服务器为了对客户端进行认证也会使用客户端证书

通过RSA实现数字签名

在这里插入图片描述

其他的数字签名

除了 RSA 外的数字签名算法:

  • EIGamal:可以被用于公钥密码和数字签名
  • DSA:Schnorr 算法与 ElGammal 方式的变体,只能被用于数字签名
  • ECDSA:利用椭圆曲线密码来实现的数字 签名算法
  • Rabin:可以被用于公钥密码和数字签名

对数字签名的攻击

中间人攻击

针对公钥密码的中间人攻击 (man-in-the-middle attack) 对于数字签名来说也颇具威胁。要防止中间人攻击,就需要确认自己所得到的公钥是否真的属于自己的通信对象。需要使用公钥证书

利用数字签名攻击公钥密码

可以将“请对消息签名”这一请求理解为 “请解密消息”。利用这一点,攻击者可以利用数字签名来破译公钥密码的密文

攻击者可以窃听Alice发送的密文(使用Bob的公钥加密),然后假装请求Bob为其施加数字签名(使用Bob的私钥生成签名),最后获得的信息正好就是Alice发送的明文

签名 = 消息^D mod N(生成签名),消息 = 签名^E mod N(验证签名)
明文 = 密文^D mod N(私钥解密),密文 = 明文^E mod N(公钥加密)
对明文公钥加密的结果生成签名,得到的就是明文

因此,不要对意思不清楚的消息进行签名。其次,公钥密码和数字签名最好分别使用不同的密钥对

潜在伪造

即使签名的对象是无意义的消息(例如随机比特序列),如果攻击者能够生成合法的数字签名(即攻击者生成的签名能够正常通过校验),我们也应该将其当成是对这种签名算法的一种潜在威胁。 这种情况称为对数字签名的潜在伪造

在用 RSA 来解密消息的数字签名算法中,潜在伪造是可能的。因为我们只要将随机比特序列 S 用 RSA 的公钥加密生成密文 M,那么 S 就是 M 的合法数字签名。由于攻击者有公钥,因此对数字签名进行潜在伪造可以实现

签名 = 消息^D mod N(生成签名),消息 = 签名^E mod N(验证签名)
明文 = 密文^D mod N(私钥解密),密文 = 明文^E mod N(公钥加密)
可以看到,签名=公钥加密中的明文,消息=密文

为了应对潜在伪造,人们在改良 RSA 的基础上开发出了一种签名算法,叫作 RSA-PSS (Probabilistic Signature Scheme)。RSA-PSS 并不是对消息本身进行签名,而是对其散列值进行签名。另外,为了提高安全性,在计算散列值的时候还要对消息加[[#盐的作用|盐 (salt)]]

利用数字签名攻击公钥密码 和 潜在伪造 的问题都是因为数字签名采用了和公钥密码相同的步骤,可以通过加一步计算散列值来避免。因为:
签名 = Hash(消息)^D mod N(生成签名),Hash(消息) = 签名^E mod N(验证签名)
就算将 S 用公钥加密生成密文 M,S是M的数字签名,M也只能被当作一个散列值

其他攻击

针对公钥密码的攻击方法大部分都能够被用于攻击数字签名

各种密码技术的对比

对称密码公钥密码
发送者用共享密钥加密用公钥加密
接收者用共享密钥解密用私钥解密
密钥配送问题存在不存在,但公钥需要认证
机密性
消息认证码数字签名
发送者用共享密钥计算MAC值用私钥生成签名
接收者用共享密钥计算MAC值用公钥验证签名
密钥配送问题存在不存在,但公钥需要认证
完整性
认证√(仅限于通信双方)√(适用于任何第三方)
防止否认×

消息认证码适合已安全共享密钥的双方通信,并适用于快速验证的场景。但涉及多方时,用消息认证码就不合适了,因为会面临严重的密钥配送问题。数字签名适用于多接收方的场合,并且可以防止否认,但其处理速度不如消息认证码

简单来说,消息认证码和数字签名的优势分别就是对称密码和公钥密码的优势

无法解决的问题

即便数字签名算法再强大,如果得到的公钥是伪造的,那么数字签名也会失效。为了能确认公钥是否合法,我们需要使用证书。所谓证书,就是由可信的第三方对公钥签名后所得到的公钥

为了对证书上施加的数字签名进行验证,我们必定需要另一个公钥,那么如何才能构筑一个可信的数字签名链条呢?又由谁来颁发可信的证书呢?到这一步,我们就已经踏入了社会学的领域。我们需要让公钥以及数字签名技术成为一种社会性的基础设施,即公钥基础设施 (Public Key Infrastructure, PKI)

证书

公钥证书 (Public-Key Certificate, PKC) 和驾照很相似,里面记有姓名、组织 、邮箱地址等个人信息,以及属于此人的公钥,并由认证机构 (Certification Authority, CA) 施加数字签名。只要看到公钥证书,我们就可以知道认证机构认定该公钥的确属于此人。也简称为证书 (certificate)

认证机构就是能够认定“公钥确实属于此人”并能够生成数字签名的个人或者组织。是可信第三方

为了解决中间人问题,我们对公钥进行数字签名,可是验证该签名用到的公钥也可能遭到中间人攻击。这种不信任的数字签名链条会无限延续下去,对此我们不得不引入可信第三方(认证机构)。相反,如果我们已经能够取得可信的公钥,则不需要认证机构

证书 = 公钥 + 认证机构对公钥的数字签名 + 公钥持有者的信息

应用场景

在这里插入图片描述

在这里插入图片描述

公钥基础设施 (PKI)

仅制定证书的规范还不足以支持公钥的实际运用,我们还需要很多其他的规范,例如证书应该由谁来颁发,如何颁发,私钥泄露时应该如何作废证书,计算机之间的数据交换应采用怎样的格式等

公钥基础设施 (Public-Key lnfrastructure, PKI) 是为了能够更有效地运用公钥而制定的一系列规范和规格的总称。例如,RSA 公司所制定的 PKCS (Public-Key Cryptography Standards, 公钥密码标准)系列规范也是 PKI 的一种,而互联网规格 RFC (Request for Comments) 中也有很多与 PKI 相关的文档

PKI 的组成要素
  • 用户:使用 PKI 的人
    • 包括:希望注册公钥的人;使用已注册公钥的人
  • 认证机构 (CA):对证书进行管理的人
    • 行为:生成密钥对(也可由用户生成);在注册公钥时对本人身份进行认证;生成并颁发证书;作废证书
    • 公钥注册和本人身份认证这一部分可以由注册机构 (Registration Authority, RA) 来分担,这样一来,认证机构就可以将精力集中到颁发证书上
  • 仓库 (repository):保存证书的数据库
    • 作用有点像打电话时用的电话本,也叫作证书目录

用户和认证机构不仅限于“人”(也有可能是计算机),因此可以给他们起一个特殊的名字,叫作实体 (entitiy)。实体就是进行证书和密钥相关处理的行为主体

在这里插入图片描述

认证机构的工作
生成密钥对

如果由认证机构生成密钥对,认证机构需要将私钥发送给用户

注册证书

认证机构根据其认证业务准则 (Certification Practice Statement, CPS) 对用户的身份进行认证,并生成证书

作废证书与 CRL

有时认证机构需要对证书进行作废 (revoke):

  • 当用户的私钥丢失、被盗时
  • 其他:用户从公司离职导致其失去私钥的使用权限,或者名称变更导致和证书中记载的内容不一致等情况

要作废证书 ,认证机构需要制作一张证书作废清单 (Certificate Revocation List, CRL)。CRL 是认证机构宣布作废的证书一览表,并由认证机构加上数字签名。证书序列号是认证机构在颁发证书时所赋予的编号,在证书中都会记载

证书有合法的认证机构签名且在有效期内还不能说明它一定有效,PKI 用户还需要查询认证机构最新的 CRL,确认该证书是否有效。一般来说,这个检查不由用户来完成,而应该由处理该证书的软件来完成

证书的层级结构

用户需要使用认证机构的公钥,对证书上的数字签名进行验证。而认证机构的公钥又需要由其他的认证机构施加数字签名,从而对认证机构的公钥进行验证。一个认证机构来验证另一个认证机构的公钥,这形成了一个层级关系。最高级的认证机构称为根CA (Root CA),它自己给自己颁发证书,这种对自己的公钥进行数字签名的行为称为自签名 (self-signature)

验证数字签名时,需要顺着认证机构的层级从顶到底依次获取各级的公钥

对证书的攻击

由于证书使用的就是数字签名技术,所有针对数字签名的攻击方法对证书都有效。下面主要介绍针对 PKI 的攻击

在公钥注册之前进行攻击

假设 Bob 生成了密钥对,并准备在认证机构注册自己的公钥。在认证机构进行数字签名之前,主动攻击者 Mallory 将公钥替换成了自己的。 这样一来,认证机构就会对“Bob的个人信息”和“Mallory的公钥”这个组合进行数字签名

要防止这种攻击,我们可以采用下面的做法。例如 Bob 可以在将公钥发送给认证机构进行注册时,使用认证机构的公钥对 Bob 的公钥进行加密。此外,认证机构在确认 Bob 的身份时, 也可以将公钥的指纹一并发送给 Bob 请他进行确认

注册相似人名进行攻击

要防止这种攻击,认证机构必须确认证书中所包含的信息是否真的是其持有者的个人信息, 当本人身份确认失败时则不向其颁发证书

窃取认证机构的私钥进行攻击

如果认证机构的私钥被窃取(泄露),认证机构就需要将私钥泄露一事通过 CRL 通知用户

攻击者伪装成认证机构进行攻击

如果认证机构本身不可信,即便证书合法,其中的公钥也不能使用

要防范这种攻击需要多加留心自己得到的证书是哪个认证机构颁发的,这个认证机构是否可信

钻 CRL 的空子进行攻击

从公钥失效到 Alice 收到证书作废清单 (CRL) 需要经过一段时间,主动攻击者 Mallory 可以利用 CAL 发布的时间差来发动攻击

对于这种攻击的对策是:公钥失效时尽快通知认证机构 ( Bob );尽快发布 CRL (Trent);及时更新 CRL ( Alice)

虽然数字签名能够防止否认,但通过钻 CRL 的空子,就有可能实现否认

第三部分

密钥

密钥的数字本身的大小并不重要,重要的是密钥空间的大小。密钥空间的大小由密钥长度决定

信息的机密性不应该依赖于密码算法本身,而是应该依赖于妥善保管的密钥

密钥和明文是等价的

不同种类的密钥

  • 用途:
    • 用于确保机密性的密钥:对称密码和公钥密码的密钥
    • 用于认证的密钥:消息认证码和数字签名所使用的密钥
  • 被使用的次数:
    • 会话密钥 (session key):每次通信只能使用一次
    • 主密钥 (master key):一直被重复使用
  • 加密的对象:
    • 内容加密密钥 (Contents Encrypting Key, CEK):用于加密内容的密钥
    • 密钥加密密钥 (Key Encrypting Key, KEK):用于加密密钥的密钥
    • 在很多情况下,会话密钥被作为 CEK 使用,而主密钥被作为 KEK 使用

在这里插入图片描述

密钥的管理

生成密钥
用随机数生成密钥

尽管生成伪随机数的算法有很多种,但密码学用途的伪随机数生成器必须是专门针对密码学用途而设计的

用口令生成密钥

使用人类可以记住的口令 (passphrase)。一般是将口令输入单向散列函数,然后将得到的散列值作为密钥使用

基于口令的密码 (Password Based Encryption, PBE):为防止字典攻击,需要在口令上面附加一串称为盐的随机数,然后再将其输入单向散列函数

配送密钥

事先共享密钥、使用密钥分配中心、使用公钥密码、Diffie-Hellman密钥交换等

更新密钥

密钥更新 (key updating):提高通信机密性。使用共享密钥进行通信过程中,定期(例如每发送 1000 个字)改变密钥。发送者和接收者同时用同样的方法来改变密钥

在更新密钥时,用当前密钥的散列值作为下一个密钥。这样,即使当前密钥被窃听者取得,窃听者也无法破译之前的信息。这种防止破译过去的通信内容的机制,称为后向安全 (backward security)

保存密钥

KEK可以减少需要保管的密钥数量:可以用一个密钥 (KEK) 将多个密钥进行加密,就只需要保管这一个 KEK 了。不过不要忘记,这一个 KEK 的价值相当于前面所有密钥的价值的总和

作废密钥

不再需要的密钥必须妥善删除,因为如果被窃听者获取,之前发送的加密邮件就会被解密

要完全删除密钥,不但要用到密码软件,还需要在设计计算机系统时对信息安全进行充分的考虑

Diffie-Hellman 密钥交换

实际上双方并没有真正交换密钥,而是通过计算生成出了一个相同的共享秘钥。 因此也称为 Diffie-Hellman 密钥协商 (key agreement)

中间人攻击是有效的

步骤
  1. Alice 向 Bob 发送两个质数 P 和 G(公开)
    • P 必须是一个非常大的质数,而 G 则是一个和 P 相关的数,称为生成元 (generator)
  2. Alice 生成随机数 A,Bob 生成随机数B(各自保密)
    • 1至P-2 之间的整数
  3. Alice 将 G^A mod P 发送给 Bob,Bob 将 G^B mod P 发送给 Alice(公开)
  4. Alice 用 Bob 发过来的数计算 A 次方再 mod P,Bob 用 Alice 发过来的数计算 B 次方再 mod P,即两人都算出 G^(A * B) mod P,这就是共享密钥
    • 密钥 = (G^A mod P)^B mod P = (G^B mod P)^A mod P = G^(A * B) mod P

在这里插入图片描述

Eve能计算出密钥吗

窃听者 Eve 知道的数字: P、G、G^A mod P 和 G^B mod P。根据这些计算出共享密钥 G^(A * B) mod P 是非常困难的。通过 G^A mod P 难以计算出 A,这是有限域的离散对数问题。有限域的离散对数问题的复杂度正是支撑 Diffie-Hellman 密钥交换算法的基础

生成元G的意义

G需要满足条件,使其乘方结果与 1 至 P-1 中的数字是一一对应的。正是因为具有这样一一对应的关系, Alice 和 Bob 才能够从 l至P-2 的范围中随机选择一个数字

在这里插入图片描述

椭圆曲线 Diffie-Hellman 密钥交换

将“离散对数问题”改为“椭圆曲线上的离散对数问题 ”,这样的算法就是椭圆曲线 Diffie Hellman 密钥交换。能够用较短的密钥长度实现较高的安全性

基于口令的密码 (PBE)

保管密钥很困难,所以不如记住口令,用口令生成密钥

PBE 加密解密

会话密钥加密之后,KEK就会被丢弃,因为KEK只要通过盐和口令就可以重建。其中加密后的会话密钥CEK和盐需要通过物理方法妥善保管,口令则只记在脑子里即可
在这里插入图片描述

在这里插入图片描述

盐的作用

盐是由伪随机数生成器生成的随机数,用来防御字典攻击

字典攻击 (dictionary attack):事先进行计算并准备好候选密钥列表的方法。主动攻击者可以在窃取到加密的会话密钥之前,就准备好大量候选 KEK。当主动攻击者窃取加密的会话密钥后, 就能够大幅缩短尝试的时间

如果在生成 KEK 时加盐,则盐的长度越大,候选 KEK 的数量也会随之增大,事先生成候选 KEK 就会变得非常困难。只要主动攻击者还没有得到盐,就无法生成候选 KEK

在这里插入图片描述

通过拉伸来改良 PBE

将单向散列函数进行多次迭代的方法称为 拉伸 (stretching)

随机数

性质

  • 随机性:不存在统计学偏差,是完全杂乱的数列。杂乱不代表不可预测
  • 不可预测性:不能从过去的数列推测出下一个出现的数
    • 伪随机数生成器的算法是公开的,但伪随机数的种子是保密的
    • 不可预测性是通过使用其他的密码技术来实现的
  • 不可重现性:除非将数列本身保存下来,否则不能重现相同的数列
    • 仅靠软件是无法生成出具备不可重现性的随机数列的。因为运行软件的计算机本身仅具备有限的内部状态,在内部状态相同的条件下,软件必然只能生成相同的数,因此软件所生成的数列在某个时刻一定会出现重复。首次出现重复之前的数列长度称为周期。凡是具有周期的数列,都不具备不可重现性
    • 要生成具备不可重现性的随机数列,需要从不可重现的物理现象中获取信息

不是所有伪随机数生成器都具备不可预测性,不具备不可预测性的伪随机数生成器不能被用于安全相关用途,例如线性同余法、Java的Random类

在这里插入图片描述

伪随机数生成器

通过硬件生成的随机数列,是根据传感器收集的热量、声音的变化等事实上无法预测和重现的自然现象信息来生成的。像这样的硬件设备就称为随机数生成器 (Random Number Generator, RNG)

而可以生成随机数的软件则称为伪随机数生成器 (Pseudo Random Number Generator, PRNG)

我们使用伪随机数生成器只是因为软件可复用。如果我们只需要生成一个随机数,那完全可以自己抛硬币来生成真随机数
而伪随机数生成器不具备不可重现性的弱点也是因为它是软件

结构

伪随机数生成器具有“内部状态”,并根据外部输入的“种子”来生成伪随机数列

在这里插入图片描述

将根据内部状态计算伪随机数的方法和改变内部状态的方法组合起来,就是伪随机数生成的算法

为了生成伪随机数,伪随机数生成器需要被称为种子 (seed) 的信息。种子是用来对伪随机数生成器的内部状态进行初始化的,是一串随机的比特序列,需要自己保密。由于种子不可以被攻击者知道,因此不可以使用容易被预测的值,例如不可以用当前时间作为种子(类似于密钥)

种子一样,生成的伪随机数一样。伪随机数生成器相当于把伪随机数[[#密码技术就是压缩技术|压缩成了种子]]

具体的伪随机数生成器

线性同余法

线性同余法 (linear congruential method) 是一种使用很广泛的伪随机数生成器算法。然而,它并不能用于密码技术

线性同余法就是将当前的伪随机数值乘以 A 再加上 C,然后将除以 M 得到的余数作为下一个伪随机数

内部状态:最近一次生成的伪随机数。种子被用来对内部状态进行初始化(A、C、M ≠ 种子)

在这里插入图片描述

假设攻击者已知 A、C、M(可以反推),那么只要得到所生成的伪随机数中的任意一个,就可以预测出下一个伪随机数。在这个过程中,攻击者没有必要知道种子。因此,线性同余法不具备不可预测性

单向散列函数法

使用单向散列函数(如 SHA-1)可以编写出能够生成具备不可预测性的伪随机数列的伪随机数生成器

在这里插入图片描述

内部状态:计数器的值
种子:计数器初始值

输出的伪随机数列实际上是单向散列函数的散列值,要想知道计数器的值,就需要破解单向散列函数的单向性,因此攻击者无法预测下一个伪随机数。单向散列函数的单向性是支撑这种伪随机数生成器不可预测性的基础

密码法

可以使用密码来编写具备不可预测性的伪随机数生成器。既可以使用 AES 等对称密码,也可以使用 RSA 等公钥密码

在这里插入图片描述

内部状态:计数器的值
种子:计数器初始值 + 密钥

输出的伪随机数列相当于密文,因此要知道计数器的值,就需要破译密码,因此攻击者无法预测出下一个伪随机数 。因此,密码的机密性是支撑这种伪随机数生成器不可预测性的基础

例如 [[#CFB模式|CFB 模式]]

其他算法

Java 中有一个用于生成随机数列的类,名叫 java.util.Random,然而这个类也不能用于安全相关用途。如果要用于安全相关用途,可以使用 java. security. SecureRandom 类

对伪随机数生成器的攻击

对种子进行攻击

伪随机数的种子类似于密码的密钥。如果攻击者知道了伪随机数的种子,那么他就能够知道这个伪随机数生成器所生成的全部伪随机数列

因此,伪随机数的种子不可以被攻击者知道。我们需要使用具备不可重现性的真随机数作为种子

对随机数池进行攻击

我们一般不会到了需要的时候才当场生成真随机数,而是会事先在一个名为随机数池 (random pool) 的文件中积累随机比特序列。随机数池的内容不可以被攻击者知道

PGP—密码技术的完美组合

加密解密

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

生成和验证数字签名

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

生成数字签名井加密以及解密并验证数字签名

签名和明文一起加密
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

信任网

如何确认得到的公钥属于正确的人(公钥合法性):PGP 中没有使用认证机构,而是采用了一种叫作信任网 (web of trust) 的方法。在这种方法中,PGP 用户会互相对对方的公钥进行数字签名

信任网的要点是“不依赖认证机构,而是建立每个人之间的信任关系”。换言之,就是能够自己决定要信任哪些公钥

通过下列 3 个场景,来介绍一下 PGP 的信任网是如何建立起来的:

  • 场景 1:通过自己的数字签名进行确认
  • 场景 2:通过自已完全信任的人的数字签名进行确认
  • 场景 3:通过自己有限信任的多个人的数字签名进行确认
场景 1:通过自己的数字签名进行确认

由于 Alice 确信刚刚导入的公钥确实是属于 Bob 本人的,因此 Alice 对这个公钥加上了自己的数字签名。对 Bob 的公钥加上数字签名,就相当于 Alice 声明“这个公钥属于 Bob 本人(即这个公钥是合法的)”

随后,Alice 收到了来自 Bob 的邮件,由于这封邮件带有 Bob 的数字签名,因此 Alice 想用 GPG 来验证 Bob 的数字签名。PGP 将执行下面这些操作:

  • 为了验证 Bob 的数字签名, PGP 需要从 Alice 的公钥串中寻找 Bob 的公钥
  • PGP 发现 Bob 的公钥带有 Alice 的数字签名,因为 Alice 对 Bob 的公钥加了数字签名
  • 为了验证 Alice 的数字签名,PGP 需要从 Alice 的公钥串中寻找 Alice 自己的公钥
  • PGP 使用 Alice 的公钥对 Bob 的公钥上的 Alice 的数字签名进行验证。如果验证成功,则可以确认这就是 Bob 的公钥
  • PGP 使用合法的 Bob 的公钥对邮件上附带的 Bob 的数字签名进行验证
场景 2:通过自已完全信任的人的数字签名进行确认

Alice 非常信任 Trent,认为经过他签名的公钥一定是合法的。在 Alice 的公钥串中,也包含带有 Alice 的数字签名的 Trent 的公钥

使用 PGP 可以表现 Alice 对 Trent 的信任程度,也就是说,Alice 可以对 Trent 的公钥设置“我完全信任 Trent 的数字签名”这一状态,并加上自己的数字签名。在 PGP 中,用户可以设置对每个公钥所有者的所有者信任 (owner trust) 级别,Alice 将对 Trent 的所有者信任级别设置为“完全信任” (Fully trusted )

Trent 对于 Alice 来说是可信的“介绍人”。Trent 对 Carrol 的公钥加上数字签名,就相当于 Trent 写了一封“介绍信”

在这里插入图片描述

场景 3:通过自己有限信任的多个人的数字签名进行确认

通过多个所有者信任的总和来确认公钥合法性

Alice 一定程度上信任 Dave 和 Fred,她认为他们没有 Trent 那样可信,但只要是 Dave 和 Fred 两个人都签过名的公钥,就一定是合法的。在这样的场景中,Alice 可以将对 Dave 和 Fred 的所有者信任级别设置为“有限信任” (Marginally trusted)

SSL/TLS—为了更安全的通信

SSL/TLS 是世界上应用最广泛的密码通信方法,是在 Web 服务器中广泛使用的协议

SSL(Secure Socket Layer)安全套接层是Netscape公司率先采用的网络安全协议

HTTPS 协议是由 HTTP 加上 SSL/TLS 协议构建的可进行加密传输、身份认证的网络协议

HTTPS 主要由两部分组成:HTTP + SSL/TLS,也就是在 HTTP 上又加了一层处理加密信息的模块。服务端和客户端的信息传输都会通过 TLS 进行加密,所以传输的数据都是加密后的数据

什么是SSL/TLS

客户端与服务器

在这里插入图片描述

Web 浏览器是 Alice 的计算机上运行的一个程序,而 Web 服务器则是在 Bob 书店的计算机上运行的一个程序,它们都遵循 HTTP (HyperText Transfer Protocol, 超文本传输协议) 的协议来进行通信。其中,Web 浏览器称为 HTTP 客户端,Web 服务器称为 HTTP 服务器

用 SSL/TLS 承载 HTTP

用 SSL (Secure Socket Layer) 或者 TLS (Transport Layer Security) 作为对通信进行加密的协议,然后在此之上承载 HTTP。通过将两种协议进行叠加,就可以对 HTTP 的通信(请求和响应)进行加密,从而防止窃听。通过 SSL/TLS 进行通信时,URL 不是以 http:// 开头,而是以 https:// 开头

在这里插入图片描述在这里插入图片描述

SSL/TLS 的工作
  • 要确保机密性,可以使用对称密码。若要将对称密码的密钥发送给通信对象,可以使用公钥密码或者 Diffie-Hellman 密钥交换
  • 要识别篡改,对数据进行认证,可以使用消息认证码。消息认证码使用单向散列函数实现
  • 要对通信对象进行认证,可以使用对公钥加上数字签名所生成的证书
SSL/TLS 也可以保护其他的协议

在这里插入图片描述

密码套件

SSL/TLS 提供了一种密码通信的框架,这意味着 SSL/TLS 中使用的对称密码、公钥密码、数字签名、单向散列函数等技术,都是可以像零件一样进行替换的。SSL/TLS 规定了一些密码技术的“推荐套餐”,这种推荐套餐称为密码套件 (cipher suite)

SSL 与 TLS 的区别

SSL ( Secure Socket Layer, 安全套接层):SSL 3.0 已经不安全了

TLS (Transport Layer Security, 传输层安全):IETF 在 SSL 3.0 的基础上设计的协议,实际上相当于 SSL 3.1

TLS 1.1 增加了针对 CBC 攻击的对策,并加入了 AES 对称密码算法。TLS 1.2 中新增了对 GCM、CCM 认证加密的支持,此外还新增了 HMAC-SHA256,并删除了 IDEA 和 DES,将伪随机函数 (PRF) 改为基于 SHA-256 实现

使用 SSL/TLS 进行通信

以下内容基于 TLS 1.2 (RFC5246) 编写

层次化的协议

TLS 协议由 TLS 记录协议 (TLS record protocol) 和 TLS 握手协议 (TLS handshake protocol) 这两层协议叠加。位于底层的 TLS 记录协议负责进行加密,而位于上层的 TLS 握手协议则负责除加密以外的其他各种操作

在这里插入图片描述

TLS 记录协议

负责消息的压缩、加密以及数据的认证。其中使用的具体算法和共享密钥通过握手协议在服务器和客户端之间协商决定

在这里插入图片描述

  • 首先,消息被分割成多个较短的片段 (fragment),然后分别对每个片段进行压缩(压缩算法需要与通信对象协商决定)
  • 接下来,经过压缩的片段会被加上消息认证码 MAC,这是为了保证完整性,并进行数据的认证。另外,为了防止重放攻击,在计算消息认证码时,还加上了片段的编号。消息认证码中使用的单向散列函数算法以及共享密钥都需要与通信对象协商决定(即使用[[#HMAC|HMAC]])
  • 再接下来,经过压缩的片段再加上消息认证码会一起通过对称密码进行加密(即使用认证加密 [[#MAC-then-Encrypt|MAC-then-Encrypt]])。加密使用 CBC 模式,初始化向量IV 通过主密码 (master secret) 生成,对称密码的算法以及共享密钥通过与通信对象协商决定
  • 最后,经过加密的数据再加上由数据类型、版本号、压缩后的长度组成的报头 (header) 就是最终的报文数据。其中,数据类型为 TLS 记录协议所承载的 4 个子协议(握手协议、密码规格变更协议、警告协议、应用数据协议)的其中之一
TLS 握手协议

又可以分为 4 个子协议

握手协议

负责:

  • 生成共享密钥、决定密码算法:为了进行密码通信
  • 交换证书:为了通信双方相互进行认证

握手协议中的信息交换是在没有加密的情况下进行的(即使用“不加密”这一密码套件)。也就是说,在这一协议中所收发的所有数据都可能被窃听,因此必须使用公钥密码或者 Diffie-Hellman 密钥交换

在这里插入图片描述

(1) ClientHello (客户端→服务器)

发送:可用的版本号,当前时间,客户端随机数(后面要用到),会话 ID,可用的密码套件清单,可用的压缩方式清单

(2) ServerHello (客户端←服务器)

发送:使用的版本号,当前时间,服务器随机数,会话 ID,使用的密码套件清单,使用的压缩方式清单

(3) (Certificate) (客户端←服务器)

发送证书清单:证书清单是一组 X.509v3 证书序列,首先发送的是服务器的证书,然后会按顺序发送对服务器证书签名的认证机构的证书。客户端会对服务器发送的证书进行验证
以匿名方式通信时,不发送 Certificate 消息

服务器的公钥包含在服务器证书内,只在握手过程中为了交换预备主密码而使用(ClientKeyExchange消息)

(4) (ServerKeyExchange) (客户端←服务器)

当 Certificate 消息不足以满足需求时,服务器发送交换密码的必要信息。具体所发送的信息内容会根据所使用的密码套件而有所不同(RSA:服务器的公钥,Diffie-Hellman:公开值)

(5) (CertificateRequest) (客户端←服务器)

这一步是为了进行客户端认证。服务器会发送:服务器能够理解的证书类型清单、服务器能够理解的认证机构名称清单。当不使用客户端认证时,不会发送 CertificateRequest 消息

(6) ServerHelloDone (客户端←服务器)

表示从 ServerHello 消息开始的一系列消息的结束

(7) (Certificate) (客户端→服务器)

客户端发送自己的证书。当服务器没有发送 CertificateRequest 消息时,客户端不会发送 Certificate 消息

(8) ClientKeyExchange (客户端→服务器)

密码套件中包含 RSA 时,随消息发送经过公钥加密的预备主密码(客户端生成的随机数);密码套件中包含 Diffie-Hellman 密钥交换时,随消息发送其公开值,用于生成预备主密码
把预备主密码当作种子,服务器和客户端会[[#计算主密码|计算出相同的主密码]],然后再[[#用主密码计算出|根据主密码生成]]密钥素材(比特序列):对称密码的密钥、消息认证码的密钥、对称密码 CBC 模式中使用的初始化向量

(9) (CertificateVerify) (客户端→服务器)

目的是向服务器证明自己的确持有客户端证书的私钥。客户端会计算“主密码”和“握手协议中传送的消息”的散列值,并加上自己的数字签名后发送给服务器(并不是发证书)。只在服务器发送 CertificateRequest 消息时才会发送 CertificateVerify 消息(需要客户端认证)

(10) {ChangeCipherSpec} (客户端→服务器)

并不是握手协议的消息,而是密码规格变更协议的消息。在这一消息之前,客户端和服务器之间已经交换了所有关于密码套件的信息,因此在收到这一消息时,客户端和服务器会同时切换密码。在这一消息之后,TLS 记录协议就开始使用双方协商决定的密码通信方式了

(11) Finished (客户端→服务器)

客户端表示握手协议到此结束。这条消息是使用切换后的密码套件来发送的,负责加密操作的是 TLS 记录协议。服务器将收到的密文解密,确认收到的 Finished 消息是否正确,以此确认握手协议是否正常结束,密码套件的切换是否正确

(12) {ChangeCipherSpec} (客户端←服务器)
(13) Finished (客户端←服务器)
(14) 切换至应用数据协议

在此之后,客户端和服务器会使用 应用数据协议 和 TLS 记录协议 进行密码通信。从结果来看,握手协议完成了下列操作:

  • 客户端获得了服务器的合法公钥,完成了服务器认证;
  • 服务器获得了客户端的合法公钥,完成了客户端认证(当需要客户端认证时);
  • 双方确认了密码算法
  • 双方生成了密码通信中使用的共享密钥、初始化向量IV;
  • 双方生成了消息认证码中使用的共享密钥
密码规格变更协议

负责向通信对象传达变更密码方式的信号。即便在密码通信开始之后,客户端和服务器也可以通过重新握手来再次改变密码套件

警告协议

负责在发生错误时通知通信对象。当握手协议的过程中产生异常,或者发生消息认证码错误、压缩数据无法解压缩等问题时,会使用该协议。如果没有发生错误,则会使用应用数据协议来进行通信

应用数据协议

用于和通信对象之间传送应用数据。当 TLS 承载 HTTP 时, HTTP 的请求和响应就会通过 TLS 的 应用数据协议 和 TLS 记录协议 来进行传送应用数据

主密码

TLS 密码通信的机密性和数据的认证全部依靠主密码。主密码是一个 48 字节 (384比特) 的数值

计算主密码

首先,客户端和服务器通过 ClientKeyExchange 消息得到相同的预备主密码:

  • 密码套件中包含 RSA 时,客户端会在发送 经过服务端公钥加密的预备主密码
  • 密码套件中包含 Diffie-Hellman 密钥交换时,客户端会在发送 Diffie-Hellman 的公开值。根据这个值,客户端和服务器会各自生成预备主密码

然后,客户端和服务器双方使用 预备主密码 + 客户端随机数 + 服务器随机数 计算主密码:

  • 把预备主密码作为种子通过伪随机函数 (PRF) 生成主密码,伪随机函数使用基于密码套件中定义的单项散列函数来实现。客户端随机数和服务器随机数是盐
用主密码计算出
  • 对称密码的密钥
  • 消息认证码的密钥
  • 对称密码的CBC模式所使用的初始化向量IV

在这里插入图片描述

TLS 中使用的密码技术小结
TLS 握手协议中:
密码技术作用
公钥密码加密预备主密码
单向散列函数构成伪随机数生成器
数字签名验证服务器和客户端的证书
伪随机数生成器生成预备主密码
TLS 记录协议中:
密码技术作用
对称密码+CBC模式确保片段的机密性
消息认证码确保片段的完整性
认证加密 AEAD确保片段的完整性和机密性并认证

对 SSL/TLS 的攻击

针对 SSL/TLS 中使用的各个密码技术的攻击,会直接成为对 SSL/TLS 的攻击。然而,SSL/TLS 作为框架的特性也正得以体现:SSL/TLS 并不依赖于某种特定的密码技术,当发现某种对称密码存在弱点时,今后只要选择不包含该对称密码的密码套件就可以了

OpenSSL 的心脏出血漏洞

要应对这一漏洞,可以将 OpenSSL 更新到已消除心脏出血漏洞的版本,或者加上禁用心跳扩展的选项重新编译 OpenSSL

SSL 3.0 的漏洞与 POODLE 攻击

[[#填充提示攻击|填充提示攻击]]。要有效抵御 POODLE 攻击,必须禁用 SSL 3.0

FREAK 攻击与密码产品出口管制
对伪随机数生成器的攻击

这个 bug 存在于伪随机数生成器中。由于 SSL 中使用的伪随机数生成器的种子都在时间和进程编号等可预测的范围内,因此所得到的密钥范围实际上非常小

[[#钻 CRL 的空子进行攻击|利用证书的时间差进行攻击]]

注意事项

认证,只是确认了通信对象是经过认证机构确认的服务器,而并不能确认是否可以和该通信对象进行安全的在线购物交易

密码通信之前的数据是不受保护的

密码通信之后的数据是不受保护的

END

在这里插入图片描述

密码技术就是压缩技术

在这里插入图片描述

压缩前压缩后
对称密码明文密钥机密性的压缩密钥是机密性的精华
公钥密码明文密钥机密性的压缩
单向散列函数消息散列值完整性的压缩散列值是完整性的精华
消息认证码消息认证符号 (MAC值)认证的压缩认证符号是认证的精华
数字认证消息认证符号 (签名)认证的压缩
伪随机数生成器伪随机数列种子不可预测性的压缩种子是不可预测性的精华
  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值