Android 中使用AES-CMAC数据加密

Android 中使用AES-CMAC数据加密一般需要分为三个步骤 算出 L 的值 然后算出 K1 K2 的值 可以对比 AES 在线加密工具作为对比 算法逻辑 paramkey paramdata return publicstatic Aes Cmac01 byte key byte data 子密钥生成 步骤 1 将具有密钥 K 的 AES 128 应用于全零输

一般需要分为三个步骤:

算出L的值,然后算出K1,K2的值,可以对比AES在线加密工具作为对比

 / * 算法逻辑 * * @param key * @param data * @return */ public static byte[] Aes_Cmac01(byte[] key, byte[] data) { // 子密钥生成 // 步骤1,将具有密钥K的AES-128应用于全零输入块。 byte[] L = aesEncryptNoPadding(key, new byte[16], new byte[16]); Log.i(TAG, "configUUIDValue L: " + ByteUtils.bytes2HexStr(L)); // 步骤2,通过以下操作得出K1: //如果L的最高有效位等于0,则K1是L的左移1位。 byte[] FirstSubkey = Rol(L); if ((L[0] & 0x80) == 0x80) { // 否则,K1是const_Rb的异或和L左移1位。 FirstSubkey[15] ^= 0x87; } // Log.i(TAG, "configUUIDValue K1: "+ ByteUtils.bytes2HexStr(FirstSubkey)); // FirstSubkey = ByteUtils.hexStr2Bytes("AC362C7FCCE2BDC64B7D39A82A"); Log.i(TAG, "configUUIDValue K1: " + ByteUtils.bytes2HexStr(FirstSubkey)); // 步骤3,通过以下操作得出K2: //如果K1的最高有效位等于0,则K2是K1左移1位 byte[] SecondSubkey = Rol(FirstSubkey); if ((FirstSubkey[0] & 0x80) == 0x80) { // 否则,K2是const_Rb的异或,且K1左移1位 SecondSubkey[15] ^= 0x87; } // Log.i(TAG, "configUUIDValue K2: "+ ByteUtils.bytes2HexStr(SecondSubkey)); // SecondSubkey = ByteUtils.hexStr2Bytes("586C58FF99C57B32C2A78C96FA7350D3"); Log.i(TAG, "configUUIDValue K2: " + ByteUtils.bytes2HexStr(SecondSubkey)); Log.i(TAG, "configUUIDValue data: " + ByteUtils.bytes2HexStr(data)); // MAC 计算 if (((data.length != 0) && (data.length % 16 == 0)) == true) { //如果输入消息块的大小等于块大小(128位) // 最后一个块在处理之前应与K1异或 for (int j = 0; j < FirstSubkey.length; j++) { data[data.length - 16 + j] ^= FirstSubkey[j]; } } else { // 否则,最后一个块应填充10 ^ i byte[] padding = new byte[16 - data.length % 16]; padding[0] = (byte) 0x80; byte[] newData = new byte[data.length + padding.length]; System.arraycopy(data, 0, newData, 0, data.length); System.arraycopy(padding, 0, newData, data.length, padding.length); // data = data.Concat 
  
    (padding.AsEnumerable()).ToArray(); // 并与K2进行异或运算 for (int j = 0; j < SecondSubkey.length; j++) { newData[newData.length - 16 + j] ^= SecondSubkey[j]; } data = newData; } Log.i(TAG, "configUUIDValue data1: " + ByteUtils.bytes2HexStr(data)); // 先前处理的结果将是最后一次加密的输入。 byte[] encResult = aesEncryptNoPadding(key, new byte[16], data); // 先前处理的结果将是最后一次加密的输入。 byte[] HashValue = new byte[16]; System.arraycopy(encResult, encResult.length - HashValue.length, HashValue, 0, HashValue.length); Log.i(TAG, "configUUIDValue data HashValue: " + ByteUtils.bytes2HexStr(HashValue)); return HashValue; } private static byte[] Rol(byte[] b) { byte[] output = new byte[b.length]; byte overflow = 0; for (int i = b.length - 1; i >= 0; i--) { output[i] = (byte) (b[i] << 1); output[i] |= overflow; if ((b[i] & 0x80) > 0) { overflow = 1; } else { overflow = 0; } } return output; } / * AES加密 * * @param keys * @param iv * @param data * @return */ public static byte[] aesEncryptNoPadding(byte[] keys, byte[] iv, byte[] data) { try { //1.根据字节数组生成AES密钥 SecretKey key = new SecretKeySpec(keys, "AES"); //2.根据指定算法AES自成密码器 "算法/模式/补码方式" Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding"); //3.CBC模式需要向量vi IvParameterSpec ivps = new IvParameterSpec(iv); //4.初始化密码器,第一个参数为加密(Encrypt_mode)或者解密解密(Decrypt_mode)操作,第二个参数为使用的KEY cipher.init(Cipher.ENCRYPT_MODE, key, ivps); //5.获取加密内容的字节数组(这里要设置为utf-8)不然内容中如果有中文和英文混合中文就会解密为乱码 byte[] byte_encode = data; //6.根据密码器的初始化方式--加密:将数据加密 byte[] byte_AES = cipher.doFinal(byte_encode); Log.i(TAG, "aesEncryptNoPadding: keys:" + ByteUtils.bytes2HexStr(keys)); Log.i(TAG, "aesEncryptNoPadding: 加密前:"+ByteUtils.bytes2HexStr(data)); Log.i(TAG, "aesEncryptNoPadding: 加密后:"+ByteUtils.bytes2HexStr(byte_AES)); //7.返回 return byte_AES; } catch (GeneralSecurityException e) { e.printStackTrace(); } return null; } public static byte[] aesEncryptPadding(byte[] keys, byte[] iv, byte[] data) { try { //1.根据字节数组生成AES密钥 SecretKey key=new SecretKeySpec(keys, "AES"); //2.根据指定算法AES自成密码器 "算法/模式/补码方式" Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding"); //3.CBC模式需要向量vi IvParameterSpec ivps = new IvParameterSpec(iv); //4.初始化密码器,第一个参数为加密(Encrypt_mode)或者解密解密(Decrypt_mode)操作,第二个参数为使用的KEY cipher.init(Cipher.ENCRYPT_MODE, key,ivps); //5.获取加密内容的字节数组(这里要设置为utf-8)不然内容中如果有中文和英文混合中文就会解密为乱码 byte [] byte_encode=data; //6.根据密码器的初始化方式--加密:将数据加密 byte [] byte_AES=cipher.doFinal(byte_encode); //7.返回 return byte_AES; }catch (GeneralSecurityException e) { e.printStackTrace(); } return null; } public static byte[] aesDecryptPadding(byte[] keys, byte[] iv, byte[] data) { try { //1.根据字节数组生成AES密钥 SecretKey key=new SecretKeySpec(keys, "AES"); //2.根据指定算法AES自成密码器 "算法/模式/补码方式" Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding"); //3.CBC模式需要向量vi IvParameterSpec ivps = new IvParameterSpec(iv); //4.初始化密码器,第一个参数为加密(Encrypt_mode)或者解密解密(Decrypt_mode)操作,第二个参数为使用的KEY cipher.init(Cipher.DECRYPT_MODE, key,ivps); //5.获取加密内容的字节数组(这里要设置为utf-8)不然内容中如果有中文和英文混合中文就会解密为乱码 byte [] byte_encode=data; //6.根据密码器的初始化方式--加密:将数据加密 byte [] byte_AES=cipher.doFinal(byte_encode); //7.返回 return byte_AES; }catch (GeneralSecurityException e) { e.printStackTrace(); } return null; } public static byte[] aesDecryptNoPadding(byte[] keys, byte[] iv, byte[] data) { try { //1.根据字节数组生成AES密钥 SecretKey key=new SecretKeySpec(keys, "AES"); //2.根据指定算法AES自成密码器 "算法/模式/补码方式" Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding"); //3.CBC模式需要向量vi IvParameterSpec ivps = new IvParameterSpec(iv); //4.初始化密码器,第一个参数为加密(Encrypt_mode)或者解密解密(Decrypt_mode)操作,第二个参数为使用的KEY cipher.init(Cipher.DECRYPT_MODE, key,ivps); //5.获取加密内容的字节数组(这里要设置为utf-8)不然内容中如果有中文和英文混合中文就会解密为乱码 byte [] byte_encode=data; //6.根据密码器的初始化方式--加密:将数据加密 byte [] byte_AES=cipher.doFinal(byte_encode); //7.返回 return byte_AES; }catch (GeneralSecurityException e) { e.printStackTrace(); } return null; } 
  

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/226321.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月16日 下午11:49
下一篇 2026年3月16日 下午11:49


相关推荐

  • 单工,半双工,全双工区别以及TDD和FDD区别

    单工,半双工,全双工区别以及TDD和FDD区别作为一名学通信的,居然对这个概念还是没搞清楚,兼职就是丢了大脸了!现在总结如下,理解比较浅,大部分网上查的,有不对的,请批评指正!单工,半双工,全双工区别单工单工就是指A只能发信号,而B只能接收信号,通信是单向的,就象灯塔之于航船——灯塔发出光信号而航船只能接收信号以确保自己行驶在正确的航线上。半双工指一个时间段内只有一个动作发生,举个简单例子,一天窄窄的马路,同时只能有一辆车通过,

    2022年6月12日
    56
  • 离线地图的原理_matplotlib地图

    离线地图的原理_matplotlib地图侵权说明:如文章内容有侵权行为,请联系本人告知,本人会尽快删除修改,避免扩大影响。Bmap说明:Bmap由北京百度网讯科技有限公司提供技术支持为用户提供包括智能路线规划、智能导航(驾车、步行、骑行)、实时路况等出行相关服务的平台。本身并不提供离线功能,因为离线会导致“搜索周边”“搜索路线”“交通状况”等实时性数据要求的功能缺失。Bmap加载原理简图:离线地图…

    2025年6月13日
    4
  • (转)C# Assembly.Load 使用

    (转)C# Assembly.Load 使用在C#中,我们要使用反射,首先要搞清楚以下命名空间中几个类的关系:在C#中,我们要使用反射,首先要搞清楚以下命名空间中几个类的关系:System.Reflection命名空间(1)AppDoma

    2022年7月1日
    21
  • 如何用C语言实现【简易关机程序】[通俗易懂]

    如何用C语言实现【简易关机程序】[通俗易懂]C语言初阶、有趣的代码

    2022年7月22日
    18
  • matplotlib用于标注文字的函数_python annotate

    matplotlib用于标注文字的函数_python annotateMatplotlib库标注在工作有很大作用:Annotate的构造函数为:Annotation(s,xy,xytext=None,xycoords=‘data’,textcoords=None,arrowprops=None,annotation_clip=None,**kwargs)用于绘制连接图上两点的箭头。关键参数:s为注释文本内容xy为被注释的坐标点,二维元组形如(…

    2025年6月6日
    4
  • Web开发 Cs和Bs架构

    Web开发 Cs和Bs架构CS架构:是指客户端与服务器举个例子:qq.exe文件在电脑上安装就可以看做是一个客户端,而数据就是从服务器发送过来的,优点在于,安全性能相对而言较高,缺点在于,对于不同的操作系统需要开发出不同版本的软件BS架构:是指游览器与服务器比如说qq.com可以在浏览器中直接访问优点在于,具有可移植性缺点在于,安全性能相对较低,以及与电脑自身的网速有关…

    2025年10月10日
    5

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号