SM4是一种由中国国家标准委员会发布的分组密码算法,主要用于加密和解密数据。SM4算法使用128位的密钥,并且其分组长度也是128位。在实现消息认证码(Message Authentication Code, MAC)时,通常会使用一种称为CMAC(Cipher-based Message Authentication Code)的方式,这是一种基于分组密码的MAC算法。
SM4 CBC-MAC是指基于SM4算法使用CBC(Cipher Block Chaining)模式来构建MAC的一种方法。下面简要介绍SM4 CBC-MAC的生成过程:
-
初始化:
- 首先选择一个密钥KK,该密钥用于SM4加密。
- 初始化一个与分组大小相同(即128位)的初始向量IV,对于CBC-MAC来说,通常这个IV是全零向量。
-
消息分组:
- 将消息MM分割成多个128位的块M1,M2,...,MnM1,M2,...,Mn。如果最后一个块不是完整的128位,则需要进行填充(Padding)。常用的填充方法是PKCS#7填充,即在最后一个块后面添加若干个等于填充字节数量的字节。
-
CBC链式加密:
- 对于第一个消息块M1M1,使用密钥KK和初始向量IV作为输入,通过SM4算法加密得到C1=SM4(K,M1⊕IV)C1=SM4(K,M1⊕IV)。
- 对于后续的消息块Mi(i>1)Mi(i>1),每个块的加密都依赖于前一个块的输出:Ci=SM4(K,Mi⊕Ci−1)Ci=SM4(K,Mi⊕Ci−1)。
-
生成MAC值:
- 最后一个加密块CnCn即为CBC-MAC的输出,也就是整个消息MM的MAC值。
需要注意的是,由于CBC-MAC在安全性上存在一些已知的问题,例如它可能受到重放攻击或中间人攻击,所以在实际应用中,有时会使用更安全的构造方式,如CMAC。CMAC是基于CBC-MAC的一种改进,它使用密钥派生来防止某些攻击,特别是对于短消息的攻击。
在CMAC中,如果消息长度超过一个块大小,则最后一个块的计算会有所不同。具体来说,CMAC使用了一个额外的密钥LL,这个LL是通过将全零块通过SM4加密得到的结果,然后使用LL来修改最后一个块的计算,以确保即使是短消息也能获得足够的安全性。
CMAC(Cipher-based Message Authentication Code)是一种基于分组密码(如AES、SM4等)的消息认证码算法。它允许发送者生成一个固定大小的标签(MAC值),接收者可以使用相同的密钥和算法验证该标签,从而确认消息的完整性和真实性。下面是使用CMAC算法生成MAC的具体步骤:
-
初始化:
- 选择一个密钥KK,该密钥用于CMAC算法中的分组密码操作。
- CMAC需要一个临时密钥LL,LL是通过使用分组密码算法(如SM4)加密一个全零的分组(即16个字节的全零)得到的结果:L=EK(0b)L=EK(0b),其中EKEK是以密钥KK执行的分组密码加密操作,bb是分组大小(对于SM4,b=128b=128比特)。
-
消息处理:
- 将消息MM分割成nn个分组M1,M2,...,MnM1,M2,...,Mn,每个分组的大小为bb比特(128比特)。
- 如果消息长度恰好是bb比特的整数倍,则直接进入下一步。
- 如果消息长度不是bb比特的整数倍,则最后一个分组MnMn需要进行填充。填充规则是:
- 在MnMn后面添加一个1比特,然后添加足够数量的0比特,直到达到bb比特的边界,最后再添加一个表示原始消息长度(未填充之前)模264264的64比特值。
-
CMAC值计算:
- 对于第一个分组M1M1,计算C1=EK(M1⊕L)C1=EK(M1⊕L)。
- 对于中间的分组M2,...,Mn−1M2,...,Mn−1,每个分组MiMi的处理方式是Ci=EK(Ci−1⊕Mi)Ci=EK(Ci−1⊕Mi)。
- 对于最后一个分组MnMn,计算T=Cn−1⊕MnT=Cn−1⊕Mn,然后如果MnMn的长度是bb比特,则Cn=EK(T)Cn=EK(T);否则,Cn=EK(T⊕L)Cn=EK(T⊕L)。
-
生成MAC值:
- CMAC值就是CnCn,即最后一个分组MnMn经过上述计算后的结果。
总结起来,CMAC通过分组密码的安全性来保障消息认证码的安全性,它通过将消息分割成块,并使用链式加密机制来处理这些块,最终生成一个固定长度的MAC值。这个值可以用来验证消息的完整性和真实性。在实际应用中,确保密钥KK的安全管理是非常重要的,因为任何能够访问KK的人都可以伪造有效的MAC值。
CBC-MAC 用于可变长度消息的问题在于,应用于单块消息的 CBC-MAC 实质上相当于一个预言机,用于根据对手选择的值评估块密码。而这个预言机允许对手打破这个计划。
考虑第一个 CMAC,该 CMAC 仅限于由整数块组成的消息。那么 CMAC 和 CBC-MAC 之间的区别在于,CMAC 使用秘密值对最后一个块进行 xor 运算 - 你可以称之为调整 - 在应用分组密码之前(小心地)从密钥派生。这确保了最终块的处理方式与其他块不同,这反过来意味着对手不再有 oracle 来评估他选择的值的块密码。
为了使 CMAC 适用于不包含整数块的消息,CMAC(小心地)派生了第二个密钥值。CMAC 首先填充消息,使其包含整数块,然后在应用块密码之前,将第二个密钥与最后一个(填充的)块进行异或运算。
这种额外的复杂性可以通过始终填充消息来避免,但如果不这样做,CMAC 会为所有可能的消息的很大一部分节省分组密码评估。
密钥值是通过将分组密码应用于全零块,然后移动位值(有时将位异化为低位以获得有限域乘法)来得出的。