1. 概述
CMAC(Cipher Block Chaining-Message Authentication Code),也简称为CBC_MAC,它是一种基于对称秘钥分组加密算法的消息认证码。由于其是基于“对称秘钥分组算法”的,故可以将其当做是对称算法的一种操作模式。
CMAC可以应用的算法主要有:AES、DES、3DES等。
什么是基于AES的CMAC算法?
采用AES加密算法,使用密钥K,对明文P进行加密,得到的密文C,作为明文P的认证码,和明文P一起传输给接收方。接收方收到后,再使用自己的密钥,对明文再做一次AES加密,生成新的认证码,与接收到的发送方的认证码进行对比验证。如果相等,说明明文没有被篡改,接收方就可以接收明文并处理;如果不相等,说明明文被篡改,数据不安全,则丢弃!
这就是基于AES的CMAC算法,多用于消息数据的正确性认证,生成的认证码,叫作message authentication code,消息认证码,简称MAC。
实现代码:AESUtil.java
package com.example.util.aes;
import java.nio.charset.StandardCharsets;
import javax.crypto.Cipher;
import javax.crypto.Mac;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
/**
* Created by sunnydlee on 2024/4/22 23:09.
*/
public class AESUtil {
public static void main(String[] args) {
byte[] encryptBytes = encryptAESCMAC("123456","12345678testkey");
String hexString = bytesToHex(encryptBytes);
System.out.println("CMAC加密:"+hexString);
}
/**
* AES-CMAC加密
* @param data 待加密数据
* @param secretKey 密钥
*/
public static byte[] encryptAESCMAC(String data, String secretKey) {
try {
// 创建一个Mac对象
Mac mac = Mac.getInstance("AESCMAC");
// 初始化Mac对象,使用SecretKeySpec包装密钥
SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes(), "AES");
mac.init(secretKeySpec);
// 执行加密操作
return mac.doFinal(data.getBytes());
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* AES-CBC加密
*/
public static String encryptAESCBC(String data, String key, String iv) {
try {
IvParameterSpec ivSpec = new IvParameterSpec(iv.getBytes());
SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
byte[] encrypted = cipher.doFinal(data.getBytes());
// return Base64.encodeToString(encrypted, Base64.DEFAULT);
return bytesToHex(encrypted);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* AES-CBC解密
*/
public static String decryptAESCBC(String data, String key, String iv) {
try {
IvParameterSpec ivSpec = new IvParameterSpec(iv.getBytes());
SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
byte[] result = cipher.doFinal(data.getBytes());
return new String(result, StandardCharsets.UTF_8);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static String bytesToHex(byte[] bytes) {
StringBuilder hexString = new StringBuilder();
for (byte b : bytes) {
String hex = Integer.toHexString(0xFF & b);
if (hex.length() == 1) {
// 如果是一位的话,要补0
hexString.append('0');
}
hexString.append(hex);
}
return hexString.toString();
}
}
AES-CMAC测试:
待加密数据:"123456"
密钥:"12345678testkey"
加密后数据:"84e6e4cb947a5d52c912cc46b5de9c07"
参考链接:https://blog.csdn.net/wjz110201/article/details/130132078
参考链接:https://blog.csdn.net/KXue0703/article/details/119522934