aes128 cmac java,C语言实现AES-128 CMAC算法

aes128 cmac java,C语言实现AES-128 CMAC算法MessageAuthe MAC 是一种保障信息完整性和认证的密码学方法 其中 CMAC 的全称是 Cypher BasedMessage 基于 AES 等对称加密方式实现消息认证 通信双方需要共享一个对称密钥 由发送方生成一个 MAC 值 附在消息后面 接收方计算收到消息的 MAC 如果和收到的 MAC 一致 则说明没有被篡改 并且能确认发送方一定

MessageAuthentication Code(MAC)是一种保障信息完整性和认证的密码学方法,其中CMAC的全称是Cypher-Based

Message Authentication Code,基于AES等对称加密方式实现消息认证。通信双方需要共享一个对称密钥,由发送方生成一个MAC值,附在消息后面,接收方计算收到消息的MAC,如果和收到的MAC一致,则说明没有被篡改,并且能确认发送方一定拥有相同的密钥,即认证身份。

美国国家标准与技术研究院NIST推荐了一种CMAC计算方式,可以避免CBC-MAC带来的缺点,编号为800-3B,文档可以从其官网上下载。该算法通过MAC密钥生成k1和k2两个子密钥,并规定了数据位填充的规则,可以通过AES-128、AES-192、AES-256三种模式进行MAC计算,支持所有整数字节的数据以及长度为0的输入。下图为MAC算法处理不需要位填充和需要位填充的两种情况。本文介绍AES-128生成的CMAC实现。

97415eca387a1225db3195890cefbdcb.png

本C代码外部依赖项是mbedTLS的密码学库,下载及使用见《C语言实现AES加密解密》。

55ec2faf725863810335e3748b5175cb.png

表1外部调用列表

本CMAC算法包括的内部函数如下。

b00a2f0afbb7289df425ad5cfb0987fa.png

表2本代码中设计的函数

本CMAC算法包括的全局变量如下。

b03695dc4be6515d6f70e8723d0faf5f.png

表3本代码中的全局变量

CMAC实现部分代码如下:

#include

#include “mbedtls/aes.h”

#include “mbedtls/compat-1.3.h”

uint8_t MAC[16];

uint8_t MACkey[16];

uint8_t k1[16];

uint8_t k2[16];

mbedtls_aes_context aes;

void leftshift(int len, uint8_t* add, uint8_t*des)

{

int i;

for (i = 0; i < len - 1; i++)

{

des[i] = (add[i] << 1) + (add[i + 1] >= 0x80?1:0);

}

des[len – 1] = add[len – 1] << 1;

}

void ArrayXor(int len, uint8_t*a1, uint8_t*a2, uint8_t*des)

{

int i;

for (i = 0; i < len; i++)

{

des[i] = a1[i] ^ a2[i];

}

}

void LoadMacKey(uint8_t *key)

{

int i;

uint8_t plain[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

uint8_t Rb[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87 };

uint8_t c0[16];

for (i = 0; i < 16; i++)

{

MACkey[i] = key[i]; // set MAC key

}

mbedtls_aes_setkey_enc(&aes, MACkey, 128);

mbedtls_aes_crypt_ecb(&aes, AES_ENCRYPT, plain, c0);

if (c0[0]<0x80) //generate k1

{

leftshift(16, c0, k1);

}

else

{

leftshift(16, c0, k1);

ArrayXor(16, k1, Rb, k1);

}

if (k1[0] < 0x80) //generate k2

{

leftshift(16, k1, k2);

}

else

{

leftshift(16, k1, k2);

ArrayXor(16, k2, Rb, k2);

}

}

void GenerateMAC(int len, uint8_t *add, uint8_t *macvalue)

{

int i,block;

uint8_t IVtemp[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};

uint8_t Blocktemp[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

if (len % 16 == 0 && len!=0)

{

mbedtls_aes_setkey_enc(&aes, MACkey, 128);// load mac key

block = len / 16;

for (i = 0; i < block-1; i++)

{

ArrayXor(16, &add[i * 16], IVtemp, Blocktemp);

mbedtls_aes_crypt_ecb(&aes, AES_ENCRYPT, Blocktemp, IVtemp);

}

ArrayXor(16, &add[(block-1)*16], IVtemp, Blocktemp);

ArrayXor(16, Blocktemp, k1, Blocktemp);

mbedtls_aes_crypt_ecb(&aes, AES_ENCRYPT, Blocktemp, macvalue);

}

else

{

if (len==0)

{

mbedtls_aes_setkey_enc(&aes, MACkey, 128);// load mac key

block = 1;

Blocktemp[0] = 0x80;//padding the first bit with 1

ArrayXor(16, Blocktemp, k2, Blocktemp);

mbedtls_aes_crypt_ecb(&aes, AES_ENCRYPT, Blocktemp, macvalue);

}

else

{

mbedtls_aes_setkey_enc(&aes, MACkey, 128);// load mac key

uint8_t remain = len % 16;

block = len / 16 + 1;

for (i = 0; i < block - 1; i++)

{

ArrayXor(16, &add[i * 16], IVtemp, Blocktemp);

mbedtls_aes_crypt_ecb(&aes, AES_ENCRYPT, Blocktemp, IVtemp);

}

// the last block padding

for (i = 0; i < remain; i++)

{

Blocktemp[i] = add[(block – 1) * 16 + i];

}

Blocktemp[remain] = 0x80;

for (i = remain + 1; i < 16; i++)

{

Blocktemp[i] = 0;

}

// end of the last block padding

ArrayXor(16, Blocktemp, k2, Blocktemp);

ArrayXor(16, Blocktemp, IVtemp, Blocktemp);

mbedtls_aes_crypt_ecb(&aes, AES_ENCRYPT, Blocktemp, macvalue);

}

}

}

uint8_t VerifyMAC(int len, uint8_t *add, uint8_t *macvalue1)

{

int i, block;

uint8_t IVtemp[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

uint8_t Blocktemp[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

uint8_t macvalue[16];

uint8_t result=1;

if (len % 16 == 0 && len != 0)

{

mbedtls_aes_setkey_enc(&aes, MACkey, 128);// load mac key

block = len / 16;

for (i = 0; i < block - 1; i++)

{

ArrayXor(16, &add[i * 16], IVtemp, Blocktemp);

mbedtls_aes_crypt_ecb(&aes, AES_ENCRYPT, Blocktemp, IVtemp);

}

ArrayXor(16, &add[(block – 1) * 16], IVtemp, Blocktemp);

ArrayXor(16, Blocktemp, k1, Blocktemp);

mbedtls_aes_crypt_ecb(&aes, AES_ENCRYPT, Blocktemp, macvalue);

}

else

{

if (len == 0)

{

mbedtls_aes_setkey_enc(&aes, MACkey, 128);// load mac key

block = 1;

Blocktemp[0] = 0x80;//padding the first bit with 1

ArrayXor(16, Blocktemp, k2, Blocktemp);

mbedtls_aes_crypt_ecb(&aes, AES_ENCRYPT, Blocktemp, macvalue);

}

else

{

mbedtls_aes_setkey_enc(&aes, MACkey, 128);// load mac key

uint8_t remain = len % 16;

block = len / 16 + 1;

for (i = 0; i < block - 1; i++)

{

ArrayXor(16, &add[i * 16], IVtemp, Blocktemp);

mbedtls_aes_crypt_ecb(&aes, AES_ENCRYPT, Blocktemp, IVtemp);

}

// the last block padding

for (i = 0; i < remain; i++)

{

Blocktemp[i] = add[(block – 1) * 16 + i];

}

Blocktemp[remain] = 0x80;

for (i = remain + 1; i < 16; i++)

{

Blocktemp[i] = 0;

}

// end of the last block padding

ArrayXor(16, Blocktemp, k2, Blocktemp);

ArrayXor(16, Blocktemp, IVtemp, Blocktemp);

mbedtls_aes_crypt_ecb(&aes, AES_ENCRYPT, Blocktemp, macvalue);

}

}

result = 1;

for (i = 0; i < 16; i++)

{

if (macvalue[i] != macvalue1[i])

{

return(result);

}

}

result = 0;

return(result);

}

Main函数部分代码如下:

int main()

{

uint8_t data[64] = { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,

0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,

0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,

0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 };

uint8_t tf=2;

uint8_t tk[16] = { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c };

LoadMacKey(tk);//加载MAC key

GenerateMAC(33, data, MAC);// 数据字节长度,数据地址,MAC地址

tf=VerifyMAC(33, data, MAC); // 数据字节长度,数据地址,MAC地址

}



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

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

(0)
上一篇 2026年3月17日 下午5:28
下一篇 2026年3月17日 下午5:28


相关推荐

  • Linux用telnet判断端口是否通

    Linux用telnet判断端口是否通通的[root@1222~]#telnet127.0.0.14531Trying127.0.0.1…Connectedto127.0.0.1.Escapecharacteris’^]’.不通[root@1222~]#telnet127.0.0.14581Trying127.0.0.1…telnet:connecttoaddress127.0.0.1:Connectionrefused退出方式1.输入Ctrl+】键,然后

    2025年8月23日
    6
  • 深入解析OpenAI Agents Python项目中的智能体构建

    深入解析OpenAI Agents Python项目中的智能体构建

    2026年3月16日
    3
  • intellij idea快捷键大全_idea中快捷键

    intellij idea快捷键大全_idea中快捷键最常用代码结构优化Ctrl+Alt+L:格式化代码Ctrl+Alt+I:将选中的代码进行自动缩进编排,这个功能在编辑JSP文件时也可以工作Ctrl+Alt+O:优化导入的类和包(去掉无用的import语句)Ctrl+/或Ctrl+Shift+/:注释(//或者/**/)Ctrl+Shift+J:两行合成一行,删去不必要的空格匹配代码格式跳转定位Ctrl+Alt+B:跳转到方…

    2022年10月9日
    5
  • 加密门禁卡复制

    加密门禁卡复制本文主要是针对一下加密门禁卡解密复制问题。最近发现补一张要50,成本的话白卡2块钱一张,读卡器可以白嫖也可以24多买一个不带壳pn532模块。一.卡类型IC卡是智能卡的总称。普通IC卡,0扇区不可以修改,其他扇区可反复擦写,我们使用的电梯卡、门禁卡等智能卡发卡商所使用的都是M1卡,可以理解为物业发的原卡。UID卡普通复制卡,可以重复擦写所有扇区,主要应用在IC卡复制上,遇到带有防火墙的读卡器就会失效。CUID卡可擦写防屏蔽卡,可以重复擦写所有扇区,UID卡复制无效的情况

    2022年6月25日
    117
  • Maven之(七)pom.xml配置文件详解[通俗易懂]

    Maven之(七)pom.xml配置文件详解[通俗易懂]鉴于CSDN对**版权保护的不作为**以及落后的运营手段,本博客将于近期关闭,并清空全部文章。原有文章将会经过再次的校对、整理,转移至本人在**简书**的[博客空间](https://www.jianshu.com/u/3ec23ef9a408)。…

    2022年7月20日
    14
  • 获取即梦AI永久会员教程

    获取即梦AI永久会员教程

    2026年3月12日
    2

发表回复

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

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