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) {// 如果是一位的话,要补0hexString.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