C++实践(四):C++实现AES-CMAC算法

C++实践(四):C++实现AES-CMAC算法AES CMACAES CMAC 使用了高级加密标准作为组分 为了产生一个消息认证码 CMAC 需要一个密钥 消息 message 及消息的长度 length 作为输入 输出是消息认证码 AES CMAC 的核心是 CBC MAC 对于待加密消息 M 应用 CBC MAC 算法 在 CMAC 操作中有两种情况 如果输入消息长度等于 Block 的整数倍 最后的 BlockM n 需要先于 K1 异或再进行处理 如果输

AES-CMAC

AES-CMAC算法实现与测试

// /*AES_CMAC: Use AES-128 /*Author: chenweiliang /*Version: 1.0 /*Reference: javafr_RFC_4493 // #pragma once #include "aes.h" class AES_CMAC { public: //key: 128-bit key AES_CMAC(const byte key[]); virtual ~AES_CMAC(); static const byte const_Rb[16]; static const byte const_Zero[16]; //msg: message to be authenticated //len: length of the message in bytes //mac: message authentication code void getCMAC(byte *msg, int len, byte *mac); //Copy K1 to key1 void getK1(byte *key1); //copy K2 to key2 void getK2(byte *key2); protected: private: AES mAes_128; //128-bit key byte mK[16]; //128-bit first subkey byte mK1[16]; //128-bit second subkey byte mK2[16]; //Utils function void leftShiftOneBit(byte *input_128,byte *output_128); void xor128(const byte *a, const byte *b, byte *out); void generateSubKey(); //lastb: last block of the intput message //pad: last block after padding //length: length of last block before padding void padding(byte *lastb,byte *pad,int length); }; 

aes_cmac.cpp:

// /*AES_CMAC: Use AES-128 /*Author: chenweiliang /*Version: 1.0 /*Reference: javafr_RFC_4493 // #include "aes_cmac.h" const byte AES_CMAC::const_Rb[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87 }; const byte AES_CMAC::const_Zero[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; void AES_CMAC::leftShiftOneBit(byte *input_128, byte *output_128) { byte overflow = 0x00; for (int i = 15; i >= 0; i--){ output_128[i] = input_128[i] << 1; output_128[i] |= overflow; overflow = (input_128[i] & 0x80) ? 0x01 : 0x00; } return; } void AES_CMAC::xor128(const byte *a, const byte *b, byte *out) { for (int i = 0; i < 16; i++){ out[i] = a[i] ^ b[i]; } } AES_CMAC::AES_CMAC(const byte key[]) { for (int i = 0; i < 16; i++){ mK[i] = key[i]; } mAes_128 = AES(mK,KEYLENGTH::KEY_LENGTH_16BYTES); generateSubKey(); } void AES_CMAC::generateSubKey() { //for output of AES-128 applied to 0^128 byte L[16]; //0^128 byte Z[16]; byte temp[16]; for (int i = 0; i < 16; i++){ Z[i] = 0; } mAes_128.encrypt(Z,L); //If MSB(L)==0,then mK1=L<<1 if ((L[0] & 0x80) == 0){ leftShiftOneBit(L, mK1); } //mK1=(L<<1)xor(Rb) else{ leftShiftOneBit(L, temp); xor128(temp, const_Rb, mK1); } if ((mK1[0] & 0x80) == 0){ leftShiftOneBit(mK1, mK2); } else{ leftShiftOneBit(mK1, temp); xor128(temp, const_Rb, mK2); } return; } void AES_CMAC::padding(byte *lastb, byte *pad, int length) { for (int i = 0; i < 16; i++){ if (i < length){ pad[i] = lastb[i]; } else if (i == length){ pad[i] = 0x80; } else{ pad[i] = 0x00; } } } void AES_CMAC::getCMAC(byte *msg, int len, byte *mac) { byte X[16]; byte Y[16]; byte msgLast[16]; byte padded[16]; //the number of blocks to be processed int n; //the number of bytes of the last block int r; //denoting last block is complete or not bool isComplete; n = (len + 15) / 16; if (n == 0){ n = 1; isComplete = false; } else{ if ((len % 16) == 0){ isComplete = true; } else{ isComplete = false; } } if (isComplete){ xor128(&msg[16*(n-1)], mK1, msgLast); } else{ padding(&msg[16*(n-1)], padded, len%16); xor128(padded, mK2, msgLast); } for (int i = 0; i < 16; i++){ X[i] = 0; } for (int i = 0; i < n - 1; i++){ //Y=(X)xor(meg_i) xor128(X, &msg[16 * i], Y); //X=AES(key,Y) mAes_128.encrypt(Y, X); } xor128(X, msgLast, Y); mAes_128.encrypt(Y, X); for (int i = 0; i < 16; i++){ mac[i] = X[i]; } } void AES_CMAC::getK1(byte *key1) { for (int i = 0; i < 16; i++){ key1[i] = mK1[i]; } } void AES_CMAC::getK2(byte *key2) { for (int i = 0; i < 16; i++){ key2[i] = mK2[i]; } } AES_CMAC::~AES_CMAC() { } 

main函数:

// /*Main: Test AES,CMAC /*Author: chenweiliang /*Version: 1.0 /*Note: To test AES-128,please comment the macro definition /* "#define AES_CMAC_TEST" and uncomment it for CMAC testing // #include "aes.h" #include "aes_cmac.h" #ifndef AES_CMAC_TEST #define AES_CMAC_TEST #endif // !AES_CMAC_TEST #include 
    void print128(unsigned char state[16]){ for (int i = 0; i < 16; i++){ printf("%02hhx", state[i]); if (i % 8 == 7){ printf(" "); } } printf("\n"); } void print512(unsigned char data[64]){ for (int i = 0; i < 64; i++){ printf("%02hhx", data[i]); if (i % 8 == 7){ printf(" "); } if (i % 32 == 31){ printf("\n"); } } printf("\n"); } void printn(unsigned char data[], int n) { for (int i = 0; i < n; i++){ printf("%02hhx", data[i]); if (i % 8 == 7){ printf(" "); } if (i % 16 ==15&&i!=n-1){ printf("\n "); } else if (i == n - 1){ printf("\n"); } } } using namespace std; int main() { #ifdef AES_CMAC_TEST unsigned char K1[16], K2[16], mac[16], TT[12]; unsigned char M[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 }; unsigned char key[16] = { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }; AES_CMAC aes_cmac = AES_CMAC(key); printf("AES-CMAC Test\n"); printf("-------------------------------------------------------------------\n"); printf("SubKeyGeneration\n"); printf("K "); print128(key); printf("K1 "); aes_cmac.getK1(K1); print128(K1); printf("K2 "); aes_cmac.getK2(K2); print128(K2); printf("-------------------------------------------------------------------\n"); printf("\n-------------------------------------------------------------------\n"); aes_cmac.getCMAC(M, 0, mac); printf("Example 1: len=0\n"); printf("M 
   
     \n" 
   ); printf("AES-CMAC: "); print128(mac); printf("-------------------------------------------------------------------\n"); aes_cmac.getCMAC(M, 16, mac); printf("Example 2: len=16\n"); printf("M "); printn(M, 16); printf("AES-CMAC: "); print128(mac); printf("-------------------------------------------------------------------\n"); aes_cmac.getCMAC(M, 40, mac); printf("Example 3: len=40\n"); printf("M "); printn(M, 40); printf("AES-CMAC: "); print128(mac); printf("-------------------------------------------------------------------\n"); aes_cmac.getCMAC(M, 64, mac); printf("Example 4: len=64\n"); printf("M "); printn(M, 64); printf("AES-CMAC: "); print128(mac); printf("-------------------------------------------------------------------\n"); #else unsigned char input[16] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }; unsigned char key[] = { 0x0f, 0x15, 0x71, 0xc9, 0x47, 0xd9, 0xe8, 0x59, 0x0c, 0xb7, 0xad, 0xd6, 0xaf, 0x7f, 0x67, 0x98 }; printf("AES Test\n"); AES aes = AES(key, KEYLENGTH::KEY_LENGTH_16BYTES); printf("Key length: 128\n"); printf("key: "); print128(key); printf("Message: "); print128(input); byte out[16]; aes.encrypt(input, out); printf("ciphertext: "); print128(out); aes.decrypt(out,out); printf("plaintext: "); print128(out); #endif // AES_CMAC_TEST return 0; } 

参考文献

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

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

(0)
上一篇 2026年3月19日 上午10:22
下一篇 2026年3月19日 上午10:22


相关推荐

  • Mac下Homebrew更新国内源brew update卡死(完美解决,网上都不完整)

    Mac下Homebrew更新国内源brew update卡死(完美解决,网上都不完整)

    2021年4月22日
    346
  • Go如何发送广播包

    Go如何发送广播包

    2022年1月6日
    59
  • 数学速算法_小学数学速算技巧全收录,寒假全面提升!

    数学速算法_小学数学速算技巧全收录,寒假全面提升!小编说:关注“学习方法报”免费获取更多学习干货,助你快速提分。想订阅报纸的各位童鞋请点击底部菜单——“微商城”查询答案的各位童鞋请点击底部菜单——“答案查询”——“小学答案”很多同学反映,自己的数学计算能力弱,每次数学考试,很多时间都花费在了计算上面,希望我能帮助他解决这个问题。所以今天我们就来和大家分享小学数学中的实用的速算技巧,同学们只要掌握了这个方法,计算问题一定会有一个大的提高!…

    2022年6月29日
    47
  • ssm框架过时了吗_spring实战

    ssm框架过时了吗_spring实战SpringSpring是一个开源的免费的框架Spring是一个轻量级的,非入侵式的框架控制反转(IOC),面向切面编程(AOP)支持事务的处理,对框架整合的支持IOC理论UserDaoUserDaoImpUserSeviceUserServiceImp在之前,用户的需求可能会影响原来的代码。使用一个set。public void setUserDao(UserDao userDao){ this.userDao = userDao;}之前是主动创建对象,控制

    2022年8月9日
    4
  • TCP与udp区别_个人总结和工作总结的区别

    TCP与udp区别_个人总结和工作总结的区别TCP与UDP区别总结:1、TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接2、TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付3、TCP面向字节流,实际上是TCP把数据看成一连串无结构的字节流;UDP是面向报文的UDP没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如IP电话,实时视频会议等)4、每一条TCP连接只能是点到点的;UDP

    2025年9月19日
    11
  • 哈佛结构和普林斯顿结构的区别_普林斯顿大学和哈佛大学哪个更厉害

    哈佛结构和普林斯顿结构的区别_普林斯顿大学和哈佛大学哪个更厉害哈佛结构是一种将程序指令存储和数据存储分开的存储器结构。中央处理器首先到程序指令存储器中读取程序指令内容,解码后得到数据地址,再到相应的数据存储器中读取数据,并进行下一步的操作(通常是执行)。程序指令存储和数据存储分开,可以使指令和数据有不同的数据宽度,如Microchip公司的PIC16芯片的程序指令是14位宽度,而数据是8位宽度。      哈佛结构的微处理器通常具有较高的执行效

    2022年10月5日
    4

发表回复

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

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