深入理解密码学技术
发布日期:2021-06-29 12:34:07 浏览次数:4 分类:技术文章

本文共 16224 字,大约阅读时间需要 54 分钟。

序言

密码技术的目的很明确,就是为了解决信息安全问题。

信息安全可分为四类特性:

1、机密性:为了防止信息被窃听,对应的密码技术有对称密码和公钥密码。2、完整性:为了防止信息被篡改,对应的密码技术有单向散列函数、消息认证码、数字签名。3、认证:为了防止攻击者伪装成真正的发送者,对应的密码技术有消息认证码和数字签名。4、不可否认性:为了防止发送者事后否认自己没有做过,对应的密码技术为数字签名。

信息安全和密码技术之间的关系可以用下图来表示:

这里写图片描述


1、对称加密

对称密码使用相同的密钥进行加密和解密,作为标准的对称密码主要有DES、三重DES和AES,它们都属于分组密码,即以分组为单位进行处理的密码算法。DES和三重DES的分组长度都是64比特,而AES的分组长度可以为128比特、192比特和256比特中的一种。那么,如果要加密的明文比较长,就需要对密码算法进行迭代,而迭代的方法就称为分组密码的模式(具体有哪些模式,后面再说)。

(1) DES

DES是1977年美国联邦信息处理标准中使用的一种对称密码技术,曾今被美国和其他国家政府银行使用。不过现在已被暴力破解,不再安全可靠了,我们除了用它解密以前的密文外,已不再使用DES了。不过这里我们可以用它来了解下什么是对称加密。

DES(Data Encryption Standard)是一种将64比特的明文加密成64比特的密文的对称密码算法,它的密钥长度是56比特,即7个字节。DES的结构采用的是Feistel网络。Feistel网络中,加密的各个步骤称为轮(round),整个加密过程就是进行若干次轮的循环。下图是Feistel网络中一轮的计算流程。DES是一种16轮循环的Feistel网络。

这里写图片描述
一轮的具体计算步骤如下:

1、将输入的数据等分为左右两部分;

2、将输入的右侧直接发送到输出的右侧;
3、将输入的右侧发送到轮函数;
4、轮函数根据右侧数据和子密钥,计算出一串看上去是随机的比特序列;
5、将上一步得到的比特序列与左侧数据进行XOR运算,并将结果作为加密后的左侧。

其中,子密钥指的是本轮加密使用的密钥。每一轮的子密钥都是不同的。轮函数的作用则是根据“右侧”和子密钥生成对“左侧”进行加密的比特序列,它是密码系统的核心。

但是,这样一来“右侧”根据没有被加密,因此需要用不同子密钥对一轮的处理重复若干次,并在没两轮之间将左侧和右侧的数据对调。下图展示了一个3轮的Feistel网络:

这里写图片描述
那么,Feistel如何解密呢?很简单,只要按照相同的顺序来使用子密钥就可以完成解密了。即将上图中的子密钥1换成了子密钥3,而子密钥3则换成子密钥1,输入的为密文,输出的则为明文了。

无论是任何轮数、任何轮函数,Feistel网络都可以用相同的结构实现加密和解密,且加密的结果必定能够正确解密。因为Feistel网络具有如此方便的特性,因此,被许多分组密码算法使用,包括5个AES最终候选算法中的其中3个算法:MARS、RC6、Twofish。

(2) 三重DES

三重DES只是将DES重复3次,为了增加DES强度。

这里写图片描述
明文经过三次DES处理才能变成最后的密文,而由于DES的密钥长度为56比特,因此三重DES的密钥长度则为56*3=128比特。另外,从图中也可以发现,三重DES并不是进行3次DES加密,而是加密->解密->加密的过程。这是为了向下兼容,即使用DES加密的密文,也可以通过三重DES进行解密。

三重DES的解密过程和加密相反,是以密钥3、密钥2、密钥1的顺序执行解密->加密->解密的操作。即将上图从明文到密文的箭头反过来就是解密的流程了。

(3) AES

AES(Advanced Encryption Standard)是取代其前任标准(DES)而成为新标准的一种对称密码算法。AES最终候选算法名单中,总共有5种算法,分为为:MARS、RC6、Rijndael、Serpent、Twofish。但最终被选定为AES的是Rijndael算法。

Rijndael使用的并不是Feistel网络,而是SPN结构。Rijndael加密中的一轮如下图所示,其分组为128比特,即16字节,加密过程经过4个步骤:SubBytes、ShiftRows、MixColumns、AddRoundKey。

这里写图片描述
SubBytes就是根据一张替换表(S-Box),将输入中每个字节的值替换成另一个字节的值。ShiftRows即将SubBytes的输出以字节为单位进行打乱出路,当然,这种打乱处理也是有规律的。MixColumns即对一个4字节的值进行比特运算,将其变成另外一个4字节的值。AddRoundKey就是将MixColumns的输出与轮密钥进行XOR处理。至此,一轮就结束了。实际上,在Rijndael中需要重复进行10~14轮计算。

而下图则是一轮解密的流程图,基本也是反向操作,加密时的SubBytes、ShiftRows、MixColumns,解密时分别为反向运算的InvSubBytes、InvShiftRows、InvMixColumns。这是因为Rijndael不像Feistel网络一样能够用同一种结构实现加密和解密。

这里写图片描述

三种对称密码算法目前的使用状况

1、DES因为已经很容易被暴力破解,因此不建议再使用;
2、三重DES目前还被银行等机构使用,但其处理速度不高,而且在安全性方面也逐渐显现出了一些问题;
3、AES作为最新标准,安全、快速,而且可以在各种平台上工作,可以算是目前最佳的选择;另外,其他AES最终候选算法也可以作为AES的备份。和Rijndael一样,这些密码算法也都经过了严格的测试,且没有发现任何弱点。

(4) 分组密码

DES、AES都属于分组密码,它们只能加密固定长度的明文。如果需要加密任意长度的明文,就需要对分组密码进行迭代,而迭代方法就称为分组密码的“模式”。

分组密码有很多种模式,主要有:ECB、CBC、CFB、OFB、CTR。如果模式选择不恰当,就无法保证机密性。

ECB模式

ECB全称为Electronic CodeBook,电子密码本模式,是最简单的一种模式,它直接将明文分割成多个分组并逐个加密,如下图,其中,加密和解密是指用分组密码算法加密和解密,其中也省略了密钥的描述。

这里写图片描述
当最后一个明文分组的内容小于分组长度时,需要用一些特定的数据进行填充。

这种模式的优点就是简单、快速,加密和解密都支持并行计算。而缺点也比较明显,因为每个明文分组都各自独立地进行加密和解密,如果明文中存在多个相同的明文分组,则这些分组最终会被转换为相同的密文分组。这样一来,只要观察一下密文,就可以知道明文中存在怎样的重复组合,并可以以此为线索来破译密码。另外,攻击者可以通过改变密文分组的顺序,或删除密文分组,或替换掉密文分组,就可以达到对明文操纵的目的,而无需破译密码。

CBC模式

CBC全称为Cipher Block Channing,密文分组链接模式,是将前一个密文分组与当前明文分组的内容混合起来进行加密的。在CBC模式中,首先将明文分组与前一个密文分组进行XOR运算,然后再进行加密。加密第一个明文分组时,由于不存在“前一个密文分组”,因此需要事先准备一个长度为一个分组的比特序列来代替“前一个密文分组”,这个比特序列称为初始化向量(initialization vector),通常缩写为IV。一般来说,每次加密时都会随机产生一个不同的比特序列来作为初始化向量。CBC模式的加解密流程如下图:

这里写图片描述
CBC模式避免了ECB模式的弱点,明文的重复排列不会反映在密文中。这是推荐使用的一种模式。

CFB模式

CFB全称为Cipher FeedBack,密文反馈模式,前一个密文分组会被送回到密码算法的输入端,如下图:

这里写图片描述
CFB模式中,由密码算法所生成的比特序列称为密钥流(key stream)。需要注意的是,CFB模式解密时,密码算法执行的是加密操作,因为密钥流是通过加密操作来生成的。

CFB模式无法抵御重放攻击。因此,一般不建议使用了,推荐用CTR模式代替。

OFB模式

OFB全称为Output-FeedBack,输出反馈模式,密码算法的输出会反馈到密码算法的输入中,如下图:

这里写图片描述
OFB模式有个缺陷,如果对密钥流的一个分组进行加密后其结果碰巧和加密前是相同的,那么这一分组之后的密钥流就会变成同一值的不断反复。因此,一般不建议使用了,推荐用CTR模式代替。

CTR模式

CTR全称为CountTeR,计数器模式,是一种通过逐次累加的计数器进行加密来生成密钥流的流密码,如下图:

这里写图片描述

CTR模式中,每个分组对应一个逐次累加的计数器,并通过对计数器进行加密来生成密钥流。计数器分为两部分,前部分为nonce,这和初始化向量一样,也是一个随机比特序列;后部分为分组序号。

从图中还可以知道,CTR模式对每个分组的处理是相对独立的,这就意味着加密和解密都能够实现并行计算。

CTR模式在错误和机密性方面都具有不错的性质,也没有上面提到的CFB和OFB的弱点,因此,现在都推荐使用CTR了。

关于初始化向量问题

前面讲到的几种模式中,CBC、CFB、OFB都用到了初始化向量IV,而CTR则使用了计数器,计数器的nonce部分和初始化向量IV是一样的,只是叫法不同而已。关于初始化向量IV,是一个随机比特序列,为了提高安全性,建议每次加密时都使用不同的值,这样的话,即使有两条相同的明文信息,加密后的密文也是不同的。但是,每一次发送端使用IV对明文加密后,接收端也需要使用同样的IV才能够解密,那么,发送端和接收端如何同步这个IV呢?关于这个问题,书中没有提到。于是,只好自己寻找解决方案。

最简单的方式可能就是,发送端每次发送信息时,将IV和加密后的密文一起发送给接收端。接收端收到信息后,就可以将收到的IV用于解密收到的密文了。而这种方式最明显的缺陷就是IV直接暴露给攻击者了,攻击者就可以利用IV发起攻击,比如使用CBC模式时,攻击者将IV进行比特反转,就可达到操纵明文的目的。攻击者将IV中的任意比特进行反转(1变0,0变1),则解密后的明文分组中相应的比特也会被反转。

为了避免将IV直接暴露,那将IV进行加密后再发送呢?因为IV的长度和一个分组的长度是等长的,这就不需要考虑分组迭代的问题,即不需要考虑使用什么模式了,直接用密码算法进行加密即可。加密后,攻击者再想通过比特反转IV来操纵明文就困难多了。


2、非对称加密

(1) 公钥密码

在对称密码中,由于加密解密的密钥是相同的,因此密钥配送就成了问题。如过使用公钥密码,就解决了配送问题。

以下描述“密钥配送问题”问题:

这里写图片描述

对称密码中,由于加密和解密都使用同一个密钥,因此就必须向接收者配送密钥,这个问题就称为密钥配送问题

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

1、通过事先共享密钥来解决2、通过密钥分配中心来解决3、通过Diffie-Hellman密钥交换来解决4、通过公钥密码来解决

(1) 通过事先共享密钥来解决

事先用安全的方式将密钥交给对方,就称为密钥的事先共享。双方可以事先共享密钥,如果双方离得很近自然好说。但如果离得很远就不能在消息里传播密钥,因为可能会被窃听。邮寄存储卡也可能会被窃取。假如一个公司有1000人需要彼此加密通信,那密钥数可能会达到50万个,这个不现实

如果是开放性平台,像微博开放平台、微信开放平台等,要做到事先共享密钥就很有难度了。开发者在开放平台注册的应用,其密钥都是通过平台的管理端给到开发者的,也就是通过了网络,那就存在被窃听的风险了。

(2)通过密钥分配中心来解决

如果有个密钥分配中心存储密钥,那1000人的数据库会有1000个密钥。当使用密钥分配中心时,需要通信的双方可以事先在密钥分配中心注册,然后密钥分配中心给每个注册方发送一个密钥,不同注册方的密钥是不同的。但如果员工增加,密钥也要增加,数据库负荷会加大,如果数据库瘫痪,全公司的通信就会瘫痪。密钥分配中心也可能会遭到攻击。

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

在Diffie-Hellman密钥交换中,进行加密通信的双方需要交换一些信息,而这些信息即便被窃听者窃听到也没有问题。根据所交换的信息,双方可以各自生成相同的密钥,而窃听者却无法生成相同的密钥。

虽然这种方法叫“密钥交换”,但实际上双方并没有真正交换密钥,而是通过计算生成出了一个相同的共享密钥。因此,这种方法也称为Diffie-Hellman密钥协商。支撑Diffie-Hellman密钥交换算法的是有限群的离散对数问题的复杂度。

(4) 通过公钥密码来解决

公钥密码类似于投币寄物柜。首先,将物品放入寄物柜中。然后,投入硬币并拔出钥匙,就可以将寄物柜关闭了。关闭后的寄物柜,没有钥匙是无法打开的。只要有硬币,任何人都可以关闭寄物柜,但寄物柜一旦被关闭,再怎么投币也无法打开。要打开寄物柜只能使用钥匙,而不是硬币。因此可以说,硬币是关闭寄物柜的密钥,而钥匙是打开寄物柜的密钥。

接下来,咱们就使用公钥密码解决配送问题:

不废话了,直接上图:

这里写图片描述

但是,公钥密码的使用存在以下两个问题:1、公钥是否是正确合法的.假如中间人给你换了个公钥呢?2、处理速度要比对称加密慢很多,大约只有百分之一。我们后面再详细讨论这两个问题的解决方案。

(2) RSA

RSA加密:密文 = 明文 E mod N (mod是取模的意思)E和N的组合就是公钥 简称 “公钥是(E,N)”RSA解密:明文 = 密文 D mod ND和N的组合就是私钥

RSA是现在使用最广泛的公钥密码算法,但RSA不只用于公钥密码,也用于数字签名。关于数字签名下一篇文章再讲。

在RSA中,明文、密钥和密文都是数字。RSA的加密过程可以用下列公式来表达,其中,Plaintext 指明文,Cipher 指密文:

Cipher = Plaintext^E mod N (RSA加密)

RSA的密文是对明文的数字的 E 次方求 mod N 的结果。换句话说,就是将明文和自己做 E 次乘法,然后将其结果除以 N 求余数,这个余数就是密文。因此,只要知道 E 和 N 这两个数,任何人都可以完成加密的运算。所以说,E 和 N 是RSA加密的密钥,也就是说,E 和 N 的组合就是密钥。另外,E 是加密(Encryption)的首字母,N 是数字(Number)的首字母。

RSA的解密和加密一样简单,可以用下面的公式来表达,其中,Plaintext 指明文,Cipher 指密文:

Plaintext = Cipher^D mod N (RSA解密)

对表示密文的数字的 D 次方求 mod N 就可以得到明文。换句话说,将密文和自己做 D 次乘法,再对其结果除以 N 求余数,就可以得到明文。这里的数字 N 和加密时的 N 是相同的。D 和 N 组合起来就是RSA的解密密钥,因此,D 和 N 的组合就是私钥。另外,D 是解密(Decryption)的首字母。

整理一下,RSA的加密和解密如下图:

这里写图片描述
由于 E 和 N 是公钥,D 和 N 是私钥,因此求 E、D 和 N 这三个数就是生成密钥对。

密钥对的生成步骤如下:

1、求N:N = p * q其中,p、q 是需要事先准备的两个很大的质数。p 和 q 太小的话,密码会变得容易破译,但太大的话计算时间又会变得很长。一般来说,p 和 q 的长度都是512比特以上,N 的长度为1024以上。2、求L:L = lcm(p-1, q-1)L 是仅在生成密钥对的过程中使用的数,它是 p-1 和 q-1 的最小公倍数。3、 求E:1

(3) 中间人攻击

这个逻辑很简单,中间人替换掉了接受者得公钥,向对方提供了自己的公钥。结果发送者用的中间人的公钥加密消息发送出去,中间人接受到消息并用自己私钥解密得到明文。再伪造一个假消息用接受者的公钥加密还给接受者。

具体流程如图:

这里写图片描述

(4) 混合密码技术

组成机制:

1、用对称密码加密消息2、通过伪随机数生成器生成对称密码加密中使用的会话密钥3、用公钥加密会话密钥4、从混合密码系统外部赋予公钥密码时使用的密钥

混合密码系统加密解密过程

加密

这里写图片描述

1、使用伪随机生成器生成会话密钥,会话密钥加密明文生成密文;    2、用接受者的公钥加密会话密钥;    3、两个密文组合后发送出去。

解密

这里写图片描述

1、收到消息先解密会话密钥:接受者用自己的私钥解密,得到会话密钥   2、用会话密钥解密加密过得密文,即可得到明文消息。

3、认证技术

前面总结了密码部分的内容,包括对称密码、公钥密码、混合密码系统等。这些密码在一定程度上能够保证消息的机密性,即可以防止被窃听导致秘密泄露。但却无法防御信息被篡改,也无法确定消息的来源是否就是真实的发送者而不是来自伪装者,也防止不了发送者事后否认自己先前做过的行为。关于这些问题,在下面总结的密码技术中就可以找到解决方案。

(1) 单向散列函数

单项散列函数又称为消息摘要函数哈希函数或者杂凑函数,它可以根据消息的内容计算出散列值,而散列值就可以被用来检查消息的完整性。输入称为消息,输出称为散列值。单向散列函数有很多种,MD4、MD5、SHA-1、SHA-256、SHA-384、SHA-512、SHA-3等等。

A、单向散列函数的性质

1、根据任意长度的消息计算出固定长度的散列值   (无论输入多长的消息,必须都能够生成很短的散列值。比如,SHA-1计算出的散列值固定为160比特)2、能够快速计算出散列值3、消息不同散列值也不同   (1)为了能够确认完整性,消息中哪怕只有 1 比特的改变,也必须有很高的概率产生不同的散列值。   (2)两个不同消息产生同一个散列值的情况称为碰撞。   (3)要找到和该消息具有相同散列值的另外一条消息是非常困难的,这一性质称为弱抗碰撞性。   (4)要找到散列值相同的两条不同消息是非常困难的,称为强抗碰撞性。4、具备单向性:根据消息计算出散列值很容易,但根据散列值却无法反算出消息。

B、对单向散列函数的攻击

对单向散列函数的攻击主要就是对单向散列函数的”抗碰撞性“的攻击。

1、对“弱抗碰撞性”的攻击主要是利用消息的冗余性生成具有相同散列值的另一个消息,这种攻击也是暴力破解,每次都稍微改变一下消息的值,然后对这些消息求散列值。在这种情况下,暴力破解需要尝试的次数可以根据散列值的长度计算出来。以SHA-1为例,由于它的散列值长度为160比特,因此最多只要尝试2^160次就能够找到目标消息。由于尝试次数纯粹是由散列值长度决定的,因此散列值长度越长的单向散列函数,其抵御暴力破解的能力也就越强。
2、对“强抗碰撞性”的攻击一般称为 生日攻击 。生日攻击不是寻找生成特定散列值的消息,而是要找到相同散列值的两条消息,而散列值则可以是任何值。生日攻击的原理来自生日悖论,也就是利用了“任意散列值一致的概率比想象中高”这样的特性。相对于暴力破解,生日攻击所需尝试的次数要少得多,一般只需要是暴力破解的一般。

C、单向散列函数无法解决的问题

单向散列函数可以实现完整性的检查,但却识别不了“伪装”,即无法解决认证问题。认证问题需要使用消息认证码和数字签名来解决。

D、单项散列函数的实际应用

1、检测软件是否篡改2、基于口令的加密(PBE):原理是将口令和盐(伪随机数)混合后计算其散列值,然后将这个散列值用作加密密钥3、消息认证码:检测并防止通信过程中得错误,篡改和伪装4、数字签名5、伪随机数生成器6、一次性口令

单向散列函数在实际应用中很少单独使用,而是和其他密码技术结合使用。后面要讲的消息认证码和数字签名都使用了单向散列函数,以及后面要讲的密钥、伪随机数和应用技术也都使用了单向散列函数。

 

这里写图片描述

E、单向散列函数SHA-1

SHA-1作为一个具有代表性的单向散列函数,让我们看看它的算法流程是怎样的。整体流程如下图:

这里写图片描述
可以分为四个步骤:

填充

对消息进行填充处理,使其长度为512比特的整数。这里的512比特称为一个输入分组。具体填充的步骤也分为三步:第一步在消息末尾添加一个1比特的数值“1”;第二步在添加了“1”之后的消息末尾不断添加0,直到消息的长度达到512比特的整数倍,但最后一个分组的最后64比特需要空出来;第三步将消息的长度换成二进制后添加到上一步空出来的最后一个分组的最后64比特中。

计算 W0 ~ W79

对每一个输入分组分别计算80个32比特的值,这80个值将用于“单步处理“中。计算流程如下图:

这里写图片描述
首先,将输入分组的512比特分成16组,每组32比特。然后,剩下的 W16 ~ W79 使用如下的公式进行计算:
这里写图片描述
分组处理

接下来,对输入分组进行80个步骤的处理,目的是根据输入分组的信息来改变内部状态。流程如下图,其中,160比特的内部状态是通过名为A~E的5个32比特的缓冲区来表示的:

这里写图片描述
将5个缓冲区的值与输入分组的信息进行混合,然后再执行80个步骤的处理。从结果来看,这80个步骤所完成的操作,就是将输入分组的512比特的数据,也SHA-1所保持的160比特的内部状态(5个缓冲区)进行混合。通过80个步骤的反复执行,SHA-1就能够将已经过填充的消息全部混入这160比特的内部状态中,而SHA-1所输出的散列值,就是所有处理结束之后最终的内部状态(160比特)。

单步处理

单步处理是指上面的80个步骤中的每一步的处理,处理过程如下图:

这里写图片描述
在一个步骤完成之后,缓冲区A、B、C、D的内容会被分别复制到B、C、D、E中(其中B要循环左移30比特之后再复制),而缓冲区 E 的内容则会与其他缓冲区的内容以及Wt、Kt相加之后再被复制到缓冲区A中。

由于上述处理要循环80个步骤,因此输入分组中 1 比特的变化,就会影响到散列值中几乎所有的比特,通过这样的方式,就能够实现单向散列函数所应具备的性质。

(2) 消息认证码

1、消息认证码(message authentication code)是一种确认完整性进行认证的技术,简称为 MAC码。

2、消息认证码的输入包括任意长度的 消息 和一个发送者与接受者之间 共享的密钥 ,它可以输出固定长度的数据,这个数据称为 MAC 值 。

消息认证码与单向散列函数很类似,都是根据任意长度的消息输出固定长度的数据,不同的是,消息认证码比单向散列函数多了一个共享密钥。没有共享密钥的人就无法计算出 MAC 值,消息认证码正是利用这一性质来完成认证的。此外,和单向散列函数一样,哪怕消息中发生 1 比特的变化,MAC 值也会发生变化,消息认证码正是利用这一性质来确认完整性的。

A、消息认证码的使用步骤

如图:

这里写图片描述
使用步骤如图:
这里写图片描述
发送者与接收者需要事先共享密钥,然后发送者使用共享密钥对消息计算 MAC 值,接着将消息和 MAC值一起发送给接收者。接收者收到消息和 MAC 值后,使用同一个共享密钥对消息计算 MAC 值,当计算出来的 MAC 值和接收到的 MAC 值一致的,就证明认证成功了。

而既然是使用共享密钥,那就和对称密码一样,存在密钥配送问题。要解决密钥配送问题,同样可以使用事先共享密钥、密钥配送中心、Diffie-Hellman密钥交换、公钥密码等方法。具体请看前一篇文章的 密钥配送问题 部分。

B、消息认证码无法解决的问题

使用消息认证码可以对消息进行认证并确认完整性,即能够识别出消息的篡改和伪装。但却解决不了“对第三方证明”和“防止否认”

假如接收者在收到发送者的消息之后,想要向第三方证明这条消息的确是发送者发送的,但是用消息认证码无法进行这样的证明,为什么呢?首先,第三方要校验 MAC 值,就需要知道发送者与接收者之间共享的密钥。但知道密钥后,也校验出 MAC 值是正确的,依然无法证明消息就是发送者发的,因为也有可能是接收者发的。

既然第三方无法做出证明,那么,如果发送者事后否认自己发送过消息,而谎称是接收者自己发送给自己的消息,对于这种情况也是无法证明,即无法防止否认。

后面要讲的数字签名就可以解决这两个问题。

C、消息认证码的实现

消息认证码有很多种实现方法。可以使用SHA-1、MD5之类的 单向散列函数 来实现,其中有一种实现方法叫 HMAC 。

HMAC 是按照下列步骤来计算 MAC 值的:

这里写图片描述
密钥填充如果密钥比单向散列函数的分组长度要短,就需要在末尾填充0,直到其长度达到单向散列函数的分组长度为止。如果密钥比分组长度要长,则要用单向散列函数求出密钥的散列值,然后将这个散列值用作 HMAC 的密钥。

填充后的密钥与 ipad 的 XOR

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

与消息组合随后,将 ipadkey 与消息进行组合,ipadkey 一般附加在消息开头。

计算散列值将上一步组合的结果输入单向散列函数,计算出散列值。

填充后的密钥与 opad 的 XOR

将填充后的密钥与被称为 opad 的比特序列进行 XOR 运算。 opad 是将 01011100 这一比特序列(即16进制的5C)不断循环反复直到达到分组长度所形成的比特序列,其中 opad 的 o 是 outer 的意思。XOR 运算后得到的值,也是一个和单向散列函数分组长度相同,且和密钥相关的比特序列。这里将这个比特序列称为 opadkey 。

与散列值组合将第4步计算出来的散列值拼在 opadkey 的后面。

计算散列值将上一步的结果输入单向散列函数,计算出散列值。这个散列值就是 MAC 值。

D、对消息认证码的攻击

对消息认证码可以发起 重放攻击 ,即攻击者可以通过将事先拦截保存的正确 MAC 值不断重放来发动攻击。有几种方法可以防御重放攻击:

序号每次发送消息时都赋予一个递增的序号,并在计算 MAC 值时将序号也包含在消息中。这样,由于攻击者无法计算序号递增之后的 MAC 值,因此就可以防御重放攻击。这种方法虽然有效,但对每个通信对象都需要记录最后一个消息的序号。

时间戳发送消息时可以包含进当前时间,如果收到以前的消息,即便 MAC 值正确也将其视为错误的消息来处理,这样就可以防御重放攻击。这种方法虽然也有效,但发送者与接收者的时钟必须一致,而且考虑到通信的延迟,必须在时间的判断上留下缓冲,于是多多少少还是会存在可以进行重放攻击的控件。

E、nonce

在通信之前,接收者先向发送者发送一个一次性的随机数,这个随机数一般称为 nonce 。发送者在消息中包含这个 nonce 并计算 MAC 值。由于每次通信时 nonce 的值都会发生变化,因此无法进行重放攻击。这种方法虽然有效,但通信的数据量会有所增加。

另外,除了重放攻击,对消息认证码也可以进行暴力破解和生日攻击,这和对单向散列函数的攻击一样。对消息认证码来说,应保证不能根据 MAC 值推测出通信双方所使用的密钥。例如 HMAC 就是利用单向散列函数的单向性和抗碰撞性来保证无法根据 MAC 值推测出密钥的。


4、数字签名技术

数字签名就是将公钥加密反过来用实现的。公钥加密就是用公钥加密消息,用私钥解密密文。而数字签名是用私钥对消息(摘要)生成签名,传输数字签名的密文,最后用公钥解密验证签名。从而验证发信者的身份信息的完整性

下图是使用公钥加密(即公钥密码)的简单流程图:

这里写图片描述
而下图则是使用私钥加密(即数字签名)的简单流程图:
这里写图片描述
解释一下:用私钥加密所得的密文,只能用公钥才能解密。这就是说,如果某个公钥成功解密了密文,那就证明这段密文是由与他配对的私钥进行加密所得的。

(1) 数字签名方法

1、直接对消息进行签名  (1)直接对消息签名的方法很容易理解,但实际上很少使用,因为我们知道,公钥密码算法本来就非常慢。  (2)用这种方法需要对整个消息进行加密,就会非常耗时。因此,在实际应用中,基本不会使用直接对消息签名的方法。2、对消息的散列值进行签名(因为散列值比较短,因此对其进行加密签名就会快很多)。

直接对消息签名,如图:

这里写图片描述
对消息的散列值签名,如图:
这里写图片描述

(2) 通过RSA实现数字签名

数字签名的实现也有很多种,基本也是使用单向散列函数和公钥密码技术相结合。而公钥密码部分常用的就是使用RSA,另外也有使用EIGamal、Rabin。还有一种数字签名算法叫DSA(Digital Signature Algorithm)。而使用最广泛的应该就是使用RSA的数字签名了。

使用RSA实现数字签名很简单。而为了更加简单起见,这里不使用单向散列函数,而是直接对消息进行签名。首先,需要将文本的消息先编码为数字,因为在RSA中,被签名的消息、密钥以及最终生成的签名都是以数字形式表示的。接着,使用下列公式生成签名:

签名 = 消息^D mod N (用RSA生成签名)

D 和 N 就是签名者的私钥。生成签名后,发送者就可以将消息和签名一起发送给接收者了。

而验证签名时则使用下列公式:

由签名求得的消息 = 签名^E mod N (用RSA验证签名)

E 和 N 就是签名者的公钥。接收者计算出“由签名求得的消息”后,与发送者直接发送过来的“消息”内容进行对比(如果使用了单向散列函数那就是对比消息的散列值)。如果两者一致则签名验证成功,否则签名验证失败。

(3) 对数字签名的攻击

因为数字签名结合了单向散列函数和公钥密码,因此,对单向散列函数和公钥密码的攻击也同样对数字签名有效。比如,针对公钥密码的中间人攻击对数字签名来说就颇具威胁。要防止中间人攻击,就需要确认自己所得到的公钥是否真的属于自己的通信对象。而解决此问题的方案也和公钥密码一样,一般可以使用公钥证书。

对单向散列函数的攻击也是对“抗碰撞性”的攻击,使用高强度的单向散列函数就可以增大被破解的难度。

另外,还可以利用数字签名攻击公钥密码。因为对消息签名,从另一方面来说,也是对消息解密。利用这一点,攻击者就可以发动一种巧妙的攻击,即利用数字签名来破译密文。

假设攻击者拦截到发送者发给接收者的密文后将其保存了下来,并给接收者写了一封邮件,谎称自己是密码学研究者,正在进行关于数字签名的实验,请求接收者对附件中的数据进行签名并回复,说附件中的数据只是随机数据,不会造成任何问题。而实际上,附件的数据就是刚才保存下来的密文。如果接收者中计而对附近进行了签名并回复给了攻击者,那攻击者不费吹灰之力就可以破译密文了。

对于这种攻击,应该采取怎样的对策呢?首先,不要直接对消息进行签名,对散列值进行签名比较安全;其次,公钥密码和数字签名最好分别使用不同的密钥对。然而,最重要的就是绝对不要对意思不清楚的消息进行签名,尤其是不要对看起来只是随机数据的消息进行签名。

(4) 数字签名无法解决的问题

用数字签名既可以识别出篡改和伪装,还可以防止否认。即是说,数字签名同时实现了确认消息的完整性、进行认证以及否认防止。

然而,数字签名存在和公钥密码一样的问题,那就是公钥问题。公钥必须属于真正的发送者。即使数字签名算法再强大,如果你得到的公钥是伪造的,那么数字签名也会完全失败。我们需要使用一种社会性的基础设施,即公钥基础设施。简称PKI。见下文。


5、证书技术

认证机构就是能够认定“公钥确实属于此人”并能够生成数字签名的个人或组织。认证机构中有国际性组织和政府所设立的组织,也有通过提供认证服务来盈利的一般企业,此外个人也可以成立认证机构哦。世界上最有名的认证机构当属VeriSign公司。

公钥证书和身份证,驾照很相似,里面有姓名,证件号,地址等个人信息,以及属于此人的公钥,由认证机构施加数字签名。只要看到公钥证书,我们就可以知道认证机构认定该公钥的确属于此人。公钥证书简称证书。

(1) 证书应用场景

通过认证机构使用证书的过程如下图所示:

这里写图片描述

(2) 公钥基础设施(PKI)

公钥基础设施是为了能够更有效地运用公钥而制定的一系列规范和规格的总称。

PKI的组成要素

1、用户———使用PKI的人2、认证机构————颁发证书的人3、仓库————保存证书的数据库

PKI组成要素如下图:

这里写图片描述

(3) 认证机构(CA)

认证机构接受对证书进行管理的人。认证机构具体行为如下:

1、生成密钥对2、在注册公钥时对本人进行身份认证3、生成并颁发证书4、作废证书

认证机构会有层级的关系,处于最顶层的认证机构一般就称为 根CA (Root CA)。上层认证机构可以验证下层认证机构的证书,即是说,下层认证机构的证书是经过上层认证机构签名的。而根CA则会对自己的证书进行签名,这叫 自签名 。

认证机构的层级关系如下图:

这里写图片描述
当发送者需要对最底层的Bob的数字签名进行验证时,首先从最顶层的根CA开始,然后获得下层的公钥证书,这个证书上面会带有上层的数字签名,因此需要用上层的公钥对数字签名进行验证。这样逐层向下验证,一直验证到最底层的Bob。

(4) 仓库

保管证书的数据库,也叫证书目录。

(5) 对证书的攻击

由于证书使用的就是数字签名技术,因此针对数字签名的所有攻击方法对证书都有效。

另外,在公钥注册之前也可以进行攻击。用户准备在认证机构注册自己的公钥时,攻击者可以把消息拦截,然后将公钥替换成自己的。这样一来,认证机构就会对“接收者的个人信息”和“攻击者的公钥”这个组合进行数字签名。要防止这种攻击,接收者可以在将自己的公钥发送给认证机构进行注册时,使用认证机构的公钥对自己的公钥进行加密。此外,认证机构在确认接收者的身份时,也可以将公钥的指纹(即散列值)一并发送给接收者请他进行确认。

攻击者还可以利用注册相似人名进行攻击。证书是认证机构对公钥及其持有者的信息加上数字签名的产物,对于一些相似的身份信息,计算机可以进行区别,但人类往往很容易认错,而这就可以被用来进行攻击。

比如,假设用户信息中名字的部分是:

Name = Bob (首字母大写)而攻击者用另一个类似的用户信息注册了另一个不同的公钥:Name = BOB (所有字母大写)随后,攻击者伪装成Bob,将 Name = BOB 的公钥发送给通信对象Alice,Alice看到证书中的用户信息,很可能会将BOB误认为是自己要发送消息的对象Bob。

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

攻击者也可以窃取认证机构的私钥,不过认证机构对私钥的保护是非常严密的,所以一般比较难窃取。如果认证机构的私钥泄露了,认证机构就需要将私钥泄露一事通过 CRL 通知用户。CRL(Certificate Revocation List)为证书作废清单,是认证机构宣布作废的证书一览表,具体来说,是一张已作废的证书序列号的清单,并由认证机构加上了数字签名。

利用钻上面提到的 CRL 的空子也可以进行攻击。因为从公钥失效到发送者收到 CRL 需要经过一段时间,攻击者就可以利用这段时间差来发动攻击。

(6) 为什么需要证书

如果从认证机构获取公钥,就可以降低遭到中间人攻击的风险。因为带有证书的公钥是经过认证机构进行数字签名的,事实上无法被篡改。

其实,如果能够取得可信的公钥,比如通信双方在同一个办公室,很容易取得可信的公钥,这种情况下则不需要认证机构。否则,认证机构和证书的存在就有意义了。当持有可信的认证机构公钥,并相信认证机构所进行的身份确认的情况下,则可以信任该认证机构颁发的证书以及通过该途径取得的公钥。

通过自己的方法进行认证是不是更安全 有些人对使用公开的技术总觉得不放心,使用公开的技术等于为攻击者提供了用于攻击的信息,相比之下,还是使用公司自己开发的保密的认证方法更安全吧?

其实这是错误的。自己开发保密的方法是犯了典型的 隐蔽式安全 (security by obscurity)错误。私下开发安全相关的技术其实是危险的,仅靠一家公司的力量无法开发出足以抵御攻击的安全技术。这也是为什么 AES 和 RSA 算法要采用公开竞赛的方式,让全世界的安全专家一起来验证这些技术的安全性。

(7) 为什么要相信认证机构

其实,这个问题关系到“信任是如何产生的”这一本质性问题。为什么我们要把钱存进银行呢?认证机构是否让人感到可信,和银行是一样的。

也有不依赖于认证机构的,PGP 软件就是。PGP 是通过 信任网 的方法来建立每个人之间的信任关系的。


6、密钥应用技术

(1) 什么是密钥

密钥本身就是一个巨大的数字,数字大小不重要,重要的是密钥空间的大小,也就是说可能出现密钥的总数量。因为密钥空间越大,暴力破解就越困难。密钥空间大小有密钥长度决定。

密钥与明文是等价的,假如明文具有100万的价值,那么这段密钥也具有100万的价值;假如明文值1亿,密钥也值1亿。

不要使用自己开发的密码算法进行加密,而是使用一个经过全世界密码学家共同验证的密码算法。如果你使用了自己的密钥,可能会出现你的密钥被长时间破解了,你依然无法知晓。 信息的机密性不应该依赖密码算法本身,而是依赖于妥善保管的密钥

(2) Diffie-Hellman 密钥交换

Diffie-Hellman 密钥交换算法,通信双方仅通过交换一些可以公开的信息就能够生产出共享密钥。

这里写图片描述

(3) 基于口令的密码(PBE)

基于口令的密码就是一种根据口令生成的密钥并用该密钥进行加密的方法。

PBE加密的3个步骤:

1、生成KEK 2、生成会话密钥并加密 3、加密消息

其中加密和解密使用同一种密钥PBE 加密过程如图:

这里写图片描述

PBE解密过程:

个人觉得是不是箭头反了?
这里写图片描述

7、随机数应用

(1) 随机数的用途

生成密钥用于对称密码和消息认证码生成密钥对用于公钥密码和数字签名生成初始化向量(IV)用于分组密码的CBC,CFB和OFB模式生成nonce用于防御重放攻击以及分组密码的CTR模式等生成盐用于基于口令的密码(PBE)等

其中生成密钥和生成密钥对是最重要的,即使密码强度再高,只要攻击者知道了密钥,就会立刻变得形同虚设。因此我们需要用随机数来生成密钥,使之无法被攻击者看穿。

随机数的性质

随机性不可预测性不可重现性

如图:

这里写图片描述

(2) 伪随机数生成器

通过硬件生成的随机数列是根据传感器收集的热量,声音的变化等事实上是无法预测的。像这样的设备就称为随机数生成器。

而可以生成随机数的软件则称为伪随机数生成器。因为软件无法生成真随机数。

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

这里写图片描述
伪随机数生成器的内部状态

伪随机数生成器的内部状态,是指伪随机数生成器岁管理的内存中的数值。

当有一条伪随机数的请求时,伪随机数生成器会根据内存中的数值进行技术,并将结果输出。随后改变自己的内部状态。因此,根据内部状态计算伪随机数的方法和改变内部状态的方法组合起来,就是伪随机数生成的算法。

伪随机数生成器的种子

伪随机数的种子是用来对伪随机数生成器的内部状态进行初始化。伪随机数生成器是公开的,但种子是需要自己保密的。由于种子不可以被攻击者知道,因此不可以使用容易被预测的值。


8、密码技术的完美组合PGP

用PGP加密:

这里写图片描述
用PGP解密:
这里写图片描述
用PGP生成数字签名:
这里写图片描述
PGP验证数字签名:
这里写图片描述
PGP生成数字签名并加密:
这里写图片描述
PGP解密并验证数字签名:
这里写图片描述

参考网址:


转载地址:https://bwshen.blog.csdn.net/article/details/82229887 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:Java-基础语法合集
下一篇:图解-密码学核心思想

发表评论

最新留言

做的很好,不错不错
[***.243.131.199]2024年04月10日 17时28分44秒