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
