消息认证
消息认证是指接收方对消息来源与完整性进行验证的全过程,其核心任务可归纳为三点:
- 真实性,确认消息确实来自真正的发送者,而非伪造者。
- 完整性,确认消息内容未被篡改,同时验证其顺序与时间戳的正确性。
- 消息认证机制需要产生认证符,作为校验依据。
实现消息认证的函数主要分为两类:信息加密函数与消息摘要算法。信息加密函数利用完整信息的密文对信息进行认证,包括对称密钥加密函数和公钥加密函数。
消息摘要算法的主要特征是:加密过程不需要密钥,并且经过加密的数据无法被解密,只有输入相同的明文数据并经过相同的消息摘要算法才能得到相同的密文。常见的消息摘要算法有R.Rivest提出的消息摘要标准(Standard For MessageDigest, MD)算法、NIST设计的安全哈希算法(SecureHash Algorithm, SHA),以及我国发布的SM3哈希函数标准和哈希式报文认证码(Hashed MessageAuthentication Code, HMAC)。消息摘要算法采用单向哈希函数H(M)从明文生成摘要密文,该摘要密文又称为数字指纹。
1、哈希函数
在网络安全目标中,要求信息在生成、存储或传输过程中不得被偶然或蓄意删除、修改、伪造、乱序、重放或插入。为此,需借助安全可靠的哈希函数来确保数据完整性。
1.1、哈希函数的概念
哈希函数(Hash Function),又称杂凑函数或散列函数,是实现数据完整性和身份认证的重要技术。哈希函数是一个从明文到密文的不可逆映射,它可以将任意长度的消息M映射成为一个长度较短且固定的输出。单向哈希函数是指在一个方向上工作的哈希函数,可以表示为:

式中,H表示单向哈希函数,M表示任意长度的数据(可以是文件、通信消息或其他数据块),h为哈希函数计算得到的结果,称为哈希值、散列值或散列码。
1.2、哈希函数的安全特性
理想哈希函数必须满足以下安全特性。
1)单向性
对给定哈希值h,寻找到x,使h=H(x)在计算上不可行。具备此性质的函数称为单向哈希函数H(M)。
单向哈希函数H(M)作用于一个任意长度的数据M,返回一个固定长度的哈希值h,称h为数据M的摘要密文。从摘要密文h不可能推导出明文,也很难通过伪造明文来生成相同的摘要密文。单向哈希函数H(M)还具有以下特性:
- 快速性:给定M,很容易计算h。
- 单向性:给定h,无法根据H(M)=h有效反推出M。
单向性确保哈希值能够安全地代表原数据,从而阻止攻击者依据哈希值伪造期望的数据。
2)抗碰撞性
抗碰撞性是指,对于给定消息M,很难找到另一个消息N,使它们满足H(M)=H(N)。根据哈希函数的安全水平,哈希函数的抗碰撞性可分为弱抗碰撞性和强抗碰撞性两种。弱抗碰撞性是指对任何给定的M,寻找到不等于M的N,使H(N)=H(M)在计算上是不可行的。强抗碰撞性是指寻找任何的(M, N)对,M≠N,使H(N)=H(M)在计算上是不可行的。
抗碰撞性(弱抗碰撞性和强抗碰撞性)在不同的前提下,防止了(N, H(M))或(M, H(N))成为有效对。"生日攻击"问题可形象地描述解决碰撞的重要性。
1.3、哈希函数的应用
哈希函数也称为哈希算法(Hash Algorithm),虽然被称为算法,但实际上更像是一种思想。因为哈希算法没有一个固定的公式,只要符合哈希思想的算法就可以称为哈希算法。目前,哈希函数已被广泛应用于互联网的各种安全场景,主要包括消息认证、数字签名等,还常用于产生单向口令文件、入侵检测和恶意代码检测等。
1)消息认证
消息认证是用来验证消息完整性的一种机制或服务。在具有实用安全性的公钥密码系统中,哈希函数被广泛用于密文正确性验证,以保障消息的真实性。发信人将原始消息与哈希值一起发送,收信人通过相同的哈希函数来校验原始数据是否真实。
2)数字签名
哈希函数的另一个重要应用是数字签名。在数字签名中,哈希函数一般用来产生"消息摘要"或"消息指纹"。这种用法是为将要签署的消息增加一个可以验证的冗余,以便这个哈希消息包含可以识别的信息。
1.4、哈希函数的安全性
对哈希函数的攻击就是寻找一对碰撞消息的过程。其攻击方法主要有两种:一种是穷举攻击,典型的方式为"生日攻击",即产生若干明文消息,并计算出消息摘要,再进行比对,找到碰撞。另一种是利用哈希函数的代数结构,攻击其函数的弱抗碰撞性。通常有中间相遇攻击、修正分组攻击和差分分析攻击等。
2、消息摘要算法(MD)
消息摘要算法(MD)由麻省理工学院教授罗纳德·里维斯特(R.Rivest)于20世纪90年代初开发,是一种用于验证数据完整性的密码哈希函数。MD5(Message-DigestAlgorithm 5)作为该系列最著名的算法,由MD2、MD3和MD4演进而来,其核心功能是将任意长度的输入数据压 缩为128bit定长哈希值,为数字签名等应用提供数据完整性保障。
2.1、MD5算法描述
MD5以512bit为处理单位对输入文本进行分组,每个分组又划分为16个32bit的子分组。算法的输出由4个分组组成,将它们级联成一个128bit哈希值。MD5算法的工作原理如图所示。

1)对消息M进行填充
MD5算法以512bit为一组对消息进行运算,因此第一步是对消息M进行数据填充,使其成为512bit的整数倍。具体步骤如下:先计算原始消息长度(以bit计)对512求余的结果,若结果不等于448,则需填充数据,使得数据长度对512求余的结果为448。填充规则为:第1位填1,其余位填0,填充后,数据长度为512×N+448为止。
2)添加消息长度
用64bit来存储填充前消息的长度,将这64bit添加在填充数据的后面,最终的消息长度为512×N+448+64=(N+1)×512。如果消息长度大于264,则只使用其低64bit的值,即用消息长度对264取模。完成此步骤后,消息最终长度为512的整数倍。
可将以上两步操作表示为:"消息尾+填充字节(100...0)+64bit消息长度"。这样操作的目的是确保对于不同长度的明文消息,分组不相同。
3)为4个寄存器A、B、C、D赋初始值
MD5算法使用128bit的缓冲区来存储中间结果和最终哈希值,该缓冲区用4个32bit寄存器(A、B、C、D)表示,称之为链接变量。这4个32bit寄存器初始值(以十六进制表示)为:A=0x01234567, B=0x89ABCDEF,C=0xFEDCBA98, D=0x76543210。这些初始值以大端字节序表示,用于第一轮的运算,并形成最终的哈希结果。(注:大端字节序是指高位字节在前,低位字节在后。也就是说,每一个变量给出的数值是按大端字节序存储的,即高位字节存于内存低地址,低位字节存于内存高地址。因此,在程序中变量A、B、C、D的值分别为0x67452301, 0xEFCDAB89, 0x98BADCFE,0x10325476)。设置好这4个链接变量后,就开始进行算法的四轮循环运算,并将4个链接变量复制到4个中间变量a、b、c、d中(a=A, b=B, c=C, d=D)。
4)执行MD5的哈希运算,即对512bit(16Byte)组进行
经过步骤1与步骤2处理后,消息长度将是(N+1)/512。算法以每512bit(64Byte)为一个消息分组,并将其视为16个32bit字进行处理。用Yq表示输入的第q组的512bit数据,在各轮中参加运算。T1, 2,...,64为64个元素表,分4组参与4轮运算。MD5共进行4轮循环,每轮16步迭代,总计64步,每轮使用不同的逻辑函数f。MD5的哈希函数如下:

式中,a、b、c、d为寄存器中的4个中间变量,按特定次序变化。f为非线性逻辑函数F、G、H、I之一,每轮用其中一个;其中比特运算符为&(与)、|(或)、~(非)、⊕(异或):
- F(X, Y, Z)=(X&Y)|((~X)&Z);
- G(X, Y, Z)=(X&Z)|(Y&(~Z));
- H(X, Y, Z)=X⊕Y⊕Z;
- I(X, Y, Z)=X⊕(Y|(~Z))。
注:在这4个函数中,如果X、Y和Z的对应位是独立和均匀的,那么结果的每一位也应是独立和均匀的。
- CLSs=32bit寄存器初始值循环左移sbit,不同轮移位数不同。
- Xk=Mq×16+k=消息的第q个512bit组的第k个32bit字。
- Ti是232×abs(sin(i))的整数部分,i=1,...,64。这样做目的是通过正弦函数和幂函数来进一步消除变换中的线性特征。
- ⊕表示模232加法。
5)输出结果
当MD5的所有512bit分组都运算完毕,A、B、C、D的级联(128bit哈希值)作为MD5哈希的结果输出,其中低字节始于A,高字节终于D。至此,整个MD5算法处理结束。
MD5的整体效率较高,因为其所有操作(或、与、非、异或和移位)都比较容易实现。由MD5的基本操作过程可知,如何选择哈希函数H十分重要,算法的每一次迭代都将128bit 128bit当前摘要与512bit消息块映射为新的128bit摘要。MD5以32bit寄存器为单位进行运算,所以可以将当前的摘要当成4个32bit的寄存器A、B、C、D,并将当前的消息分成16个32bit的字。完成MD5转换后,原来的值A、B、C、D被完全打乱,被打乱的摘要加上前一轮的摘要就成为新的摘要。重复此过程直至处理完所有消息块,最后的输出就是消息摘要。
2.2、MD5的安全性
MD5的安全性依赖于"在计算上寻找两个不同消息具有相同哈希值"的不可行性。长期以来,MD5加密验证的安全性都是非常高的。MD5的输出为128bit,若采用纯穷举攻击寻找一个具有给定哈希值的消息,计算困难性在于对2128个消息计算出具有相同哈希值的两个消息。若用每秒可试验109个消息的计算机计算,需耗时1.07×1022年。若采用生日攻击法,寻找具有相同哈希值的两个消息需要试验264个消息,用每秒可试验109个消息的计算机计算,需耗时585年。但是,对单轮MD5的攻击已有结果。对MD4与MD5的攻击可参阅相关文献。2004年8月17日,山东大学的王小云教授在国际密码学会议(Crypto 2004)上宣布,只需1小时就可找出MD5碰撞,提出了密码哈希函数的碰撞攻击理论,即差分比特分析法。2005年其团队又提出SHA-1的破译方法。自此,包括MD5、SHA-1在内的5个国际通用哈希函数被认定不再安全。不过,在一些安全性要求不高的场景下,MD5仍然是一种可用的哈希算法。
2.3、MD5的应用
依据MD5的基本过程,消息摘要(MD)的典型使用方式如下:通信双方共享一个密钥K,发送端先将报文M输入给哈希函数H,得到H(M),再用密钥K对MD加密;然后将加密后的MD追加到报文M后面并发送到接收端。接收端收到此报文后,首先去除报文M后面加密的MD,然后用已知的哈希算法计算H(M),再用自己拥有的密钥K对加密的MD进行解密,得到MD。比较计算得到的H(M)与MD是否一致,如一致,则可以判定收到的报文M是真实的。MD5的典型应用场景包括:
1)一致性验证
MD5的典型应用是对一段文本信息产生消息摘要,以防止被篡改。软件下载站点通常附带MD5值,用户在下载后可用专用工具(如Windows MD5 Check)重新计算MD5值,并与站点公布值比对,确认文件未被篡改。
2)数字证书
由第三方认证机构签发数字证书时,可先用MD5对文件生成摘要,再对摘要进行签名。此举可防止文件作者事后抵赖,实现数字签名功能。
3)安全访问认证
在UNIX系统中用户的密码是经MD5等哈希运算后存储在文件系统中的。当用户登录时,系统把用户输入的密码进行MD5运算,然后再与存储在文件系统中的MD5值进行比较,确定输入的密码是否正确。通过这样的步骤,系统在不知道用户密码明文的情况下就可以确定用户登录系统的合法性。
3、安全哈希算法(SHA)与SM3
安全哈希算法(Secure Hash Algorithm, SHA)是目前应用最广泛的消息摘要函数,主要用于数字签名标准里面定义的数字签名算法(Digital Signature Algorithm,DSA)。SHA系列包含SHA-1、SHA-224、SHA-256、SHA-384和SHA-512等,分别输出160bit、224bit、256bit、384bit、512bit摘要。后4个SHA算法通常合称SHA-2。SHA-1已广泛应用于TLS、SSL、PGP、SSH、S/MIME和IPsec等协议。SHA的基本思想是接收一段明文,然后以一种不可逆的方式将它转换成一段更小的密文,也可以简单地理解为取一串输入码,把它们转化为长度较短、位数固定的输出序列(即哈希值)的过程。哈希函数值可以说是对明文的一种"指纹"或"摘要",所以对哈希值的数字签名就可以视为对明文的数字签名。
SHA算法建立在MD4算法之上,其基本框架与MD4类似。SHA-1算法产生160bit的哈希值(比MD5多32bit),因此它有5个参与运算的32bit寄存器,消息分组和填充方式与MD5相同,主循环也同样是4轮,但每轮进行20次操作,非线性运算、移位和加法运算也与MD5类似,但非线性函数、加法常数和循环左移操作的设计有一些区别。SHA-2与SHA-1类似,都使用了同样的迭代结构、模算法运算与二元逻辑操作。
不同版本SHA算法参数的比较如下表所示,其中所有长度均以二进制位为单位。

以SHA-512为例,SHA算法的基本操作过程如下。
SHA-512算法输入报文的最大长度不超过2128bit,按1024bit分组处理,最终输出512bit的消息摘要。SHA-512算法的主要操作步骤如图所示。

3.1、附加填充位
对消息进行填充,使其报文长度与1024模896同余,即长度≡896 mod 1024。填充的比特数范围是1~1024,填充比特串的最高位为1,其余位为0。就是先在消息后面加一个1,再加很多个0,直到长度满足模1024为896。为什么是896,因为896+128=1024(下一步会加上一个1024bit的原始消息的长度信息)。
3.2、附加长度
在填充后的消息末尾附加一个128bit的块,将其视为128bit的无符号整数(最高3BCC908字节在前),用于记录原始消息的长度信息。
前两步完成后,消息长度变为1024bit的整数倍。在图3.2中,扩展的消息被表示为一串长度为1024bit的消息分组M1, M2,...,MN,因此扩展消息总长度为N×1024bit。
3.3、初始化哈希缓冲区
哈希函数的中间结果和最终结果保存于512bit的缓冲区中,缓冲区用8个64bit的寄存器(a、b、c、d、e、f、g、h)表示,并将这些寄存器初始化为下列64bit的整数(十六进制值):
bash
a=0x6A09E667F3BCC908,b=0xBB67AE8584CAA73B,c=0x3C6EF372FE94F82B,
d=0xA54FF53A5F1D36F1, e=0x510E527FADE682D1,f=0x9B05688C2B3E6C1F,
g=0x1F83D9ABFB41BD6B, h=0x5BE0CD19137E2179。
这些值以高位在前的格式存储。也就是说,字的最高有效字节存于地址字节位置(最左边)。这些字的获取方式为:前8个素数取平方根,取小数部分的前64bit。
3.4、以1024bit的分组(128Byte)为单位处理消息
SHA-512算法的核心是具有80轮运算的模块,在图中该模块标记为F,即轮函数。每一轮都把512bit缓冲区的值a、b、c、d、e、f、g、h作为输入,并更新缓冲区的值。每一轮如第i轮,使用一个64bit的值Wi,该值由当前被处理的1024bit消息分组Mi导出(使用消息扩展算法)。每一轮还将使用附加的常数Ki(0≤i≤79),用来使每轮的运算不同。Ki的获取方法为:对前80个素数开立方根,取小数部分的前64bit。这些常数提供了64bit随机串集合,可以初步消除输入数据中的统计规律。第80轮的输出和第1轮的输入Hi-1中对应的字分别进行模264的加法运算。注意,SHA-512轮函数F比较复杂,具体应用时请参阅相关文献。
3.5、输出结果
所有N个1024bit分组都处理完毕后,从第N轮输出的即为512bit的消息摘要。
综合以上各运算步骤,可将SHA-512算法描述如下:

其中,IV为第3步中定义的缓冲区(a、b、c、d、e、f、g、h)的初始值;abcdefghi=第i个消息分组处理后的最后一轮的输出。N表示消息(包括填充和长度域)中的分组数;SUM64表示对输入中的每个字进行独立的模264加法运算;MD表示最后的消息摘要输出值。
3.6、SM3
SM3是我国国家密码管理局于2010年发布的商用密码哈希算法标准,适用于数字签名与验证、消息认证码的生成与验证以及随机数生成等场景。算法采用512 bit消息分组,输出256 bit哈希值。SM3的设计比较复杂,比如压缩函数的每一轮使用2个消息字,消息扩展过程的每一轮使用5个消息字等。
SM3的安全性及效率与SHA-256相当。目前,对SM3的攻击还比较少。
4、消息认证码(MAC)
消息认证码(Message Authentication Code, MAC)也称为密码校验和,是一种不依赖加密技术即可验证报文内容完整性的方法。所有需要进行完整性验证的消息,都会以消息本身为基础,生成称为消息认证码的固定大小的数据块。这种消息认证码是对消息完整性进行验证的关键。
MAC是一种针对信源消息的编码函数,具体指消息在密钥控制的公开哈希函数作用下生成的、用作认证符的、固定长度的数值。采用消息认证码的通信双方需要共享一个密钥,以K来表示。同时,需要用于生成消息认证码的函数F。对于输入消息M,其消息认证码MAC与M和K相关,可以表示为:

发送方将MAC和输入消息M一起发送给接收方。接收方收到消息后,使用相同的密钥K进行相同的计算,得出新的MAC,并将接收到的MAC与新计算出的MAC进行比较,消息认证过程如图所示。如果假定只有收发双方知道该密钥,当接收到的MAC与计算得出的MAC一致时,可得出以下结论:

- 接收方可以相信消息未被修改。若攻击者改动消息,却无法生成对应的新MAC,则接收方算出的MAC必与收到的MAC不符;因攻击者未知密钥,故无法构造正确MAC。
- 接收方可以相信消息来自真正的发送方。因为其他各方均不掌握密钥,不能产生具有正确MAC的消息。
- 如果消息中含有序列号(如HDLC、X.25或TCP中使用的序列号),那么接收方可以相信消息顺序是正确的,因为攻击者无法成功修改序列号。
一般而言,MAC函数是多对一函数,其定义域由任意长度的消息组成,而值域由所有可能的MAC和密钥组成。若MAC长度为nbit,则有2n个可能的MAC和N条可能的消息,其中N>>2n。若密钥长度为kbit,则有2k种可能的密钥。
例如,假设使用100bit的消息和10bit的MAC,那么共有2100条不同的消息,但仅有210个不同的MAC。所以平均而言,同一MAC可以由插图条不同的消息产生。若使用的密钥长度为5bit,则从消息集合到MAC值的集合有25=32种不同的映射。可以证明,认证函数的数学性质使其比加密更难破译。

除验证内容完整性外,MAC亦可实现报文源认证与报文顺序认证。MAC的生成涉及一个保密的密钥,只要在发送消息时增加发送方的标识号,将发送方的身份标识号ID与消息M拼接,并在生成MAC时包含此信息:MACM=F(M‖ID, K),则MAC也能够准确判断发送方的身份。如果在生成MAC时包含能够表示报文先后顺序的信息(如时间戳、序列号等),而攻击者不能正确地修改认证码中所包含的顺序信息,则接收者就可以确认消息的序列正确,避免重放攻击。
MAC函数与加密算法虽均以共享密钥为基础,但二者存在显著差异。一个区别是,虽然两者都要求通信双方共享密钥,但是MAC所使用的密钥与密码系统中使用的密钥不同,MAC密钥用于生成认证标签,而非控制加解密过程。另一个区别是,用于产生MAC的函数不需要具有可逆性,即生成MAC后,不要求通过MAC来恢复原始消息。而加密过程要求具有可逆性,对于加密得到的密文,必须可以通过解密来恢复明文。因此,MAC函数在设计上相对简单一些。