AES-CMAC代码实现

2 篇文章 1 订阅
2 篇文章 1 订阅

AES-CMAC代码的C++实现

  1. 本人使用的codeblock,来编写代码,以及代码的仿真和调试的,感觉挺好用,
  2. 代码实现主要分为三部分,start,mid,end。类似CRC校验的实现方式,
  3. /加密算法 plaintext 明文,ciphertext 密文 key 秘钥*/
    void EncryPtion(uint8_t plaintext[16], uint8_t key[16], uint8_t ciphertext[16])
    {
    int i,j;
    uint8_t state[4][4];
    for(i=0;i<4;i++)
    for(j=0;j<4;j++)
    state[j][i]=plaintext[4i+j];
    key_Expansion(key); //秘钥扩展
    Roundkey(state,0);
    for(i=1;i<10;i++)
    Round_4(state,i);
    Round_3(state);
    for(i=0;i<4;i++)
    for(j=0;j<4;j++)
    ciphertext[4
    i+j]=state[j][i];
    }

//CMAC
void k1_k2(uint8_t key[16], uint8_t key_1[16], uint8_t key_2[16])
{
uint8_t L[16];
uint8_t Zero_n[16]={0X00};
int i;
EncryPtion(Zero_n,key,L);
if(L[0]>=0X80)
{
for(i=0;i<16;i++)
key_1[i]=L[i]<<1;
key_1[15]=key_1[15]^0X87;
}
else
{
for(i=0;i<16;i++)
key_1[i]=L[i]<<1;
}
if(key_1[0]>=0X80)
{
for(i=0;i<16;i++)
key_2[i]=key_1[i]<<1;
key_2[15]=key_2[15]^0X87;
}
else
{
for(i=0;i<16;i++)
key_2[i]=key_1[i]<<1;
}
}

/k1_k2_test*/

void k1_k2_test(uint8_t * key, Mac_Para_Out *mac_para_out)
{
uint8_t L[16];
uint8_t Zero_n[16]={0X00};
int i;
EncryPtion(Zero_n,key,L);
if(L[0]>=0X80)
{
for(i=0;i<16;i++)
mac_para_out->key_1[i]=L[i]<<1;
mac_para_out->key_1[15]=mac_para_out->key_1[15]^0X87;
}
else
{
for(i=0;i<16;i++)
mac_para_out->key_1[i]=L[i]<<1;
}
if(mac_para_out->key_1[0]>=0X80)
{
for(i=0;i<16;i++)
mac_para_out->key_2[i]=mac_para_out->key_1[i]<<1;
mac_para_out->key_2[15]=mac_para_out->key_2[15]^0X87;
}
else
{
for(i=0;i<16;i++)
mac_para_out->key_2[i]=mac_para_out->key_1[i]<<1;
}
/*printf(“将KEY_1 KEY_2的值打印出来”);
printf("\r\n");
for(i=0;i<16;i++)
{
printf("%x key1 “,mac_para_out->key_1[i]);
printf(”%x key2 “,mac_para_out->key_2[i]);
printf(”\r\n");

}*/

}

//对于消息不是密文分组的整数倍,
void fil(uint8_t *last_test, uint32_t length, uint8_t out_text[16])
{
int i;
for(i=0;i<16;i++)
{
if(i<length)
out_text[i]=last_test[i];
else if(i==length)
out_text[i]=0X80;
else
out_text[i]=0X00;
}
}

void AES_CMAC(uint8_t * MASS , uint8_t key, uint32_t length,uint8_t * mac)
{
int i,j,n,last_i;
int flag=0; //用于标记密文分组是否完整
uint8_t M_c1[16]={0x00}, M_c2[16],M_c_k[16]; //用于存放中间数据
uint8_t key_1[16],key_2[16]; //分组秘钥
uint8_t last[16],Cn[16];
n=(length+15)/16; //用于确定分几组
last_i=length%16;
k1_k2(key, key_1,key_2);
if(last_i0)
flag=1; //标明是分组长度b=128的整数倍
if(flag
0)
fil(&MASS[16
(n-1)], last_i,last);
//对前n-1轮
for(i=0;i<(n-1);i++)
{
for(j=0;j<16;j++)
M_c2[j]=M_c1[j]^MASS[16*i+j];
EncryPtion(M_c2,key,M_c1); // M_c1 is output
printf("\r\n");
printf(“AES_CMAC:将M_c1的结果输出来,也就是前N-1轮加密的结果”);
printf("\r\n");
for(j=0;j<16;j++)
printf("%x " , M_c1[j]);
printf("\r\n");

}
 printf("\r\n");

if(flag==1)
{
    for(i=0;i<16;i++)
    M_c_k[i]=MASS[16*(n-1)+i]^M_c1[i]^key_1[i];
    EncryPtion(M_c_k, key, Cn);
    printf("\r\n");
    printf("将Cn的结果输出来,也就是第N次加密后的结果");
     printf("\r\n");
    for(i=0;i<16;i++)
    {
        printf("%x " ,Cn[i]);
    }
    printf("\r\n");
}
else
{
    for(i=0;i<16;i++)
    M_c_k[i]=last[i]^M_c1[i]^key_2[i];
    EncryPtion(M_c_k, key,Cn);
    printf("\r\n");
    printf("将最后不全的数值Cn的结果输出,也就是最后不全部分补全后输出");
     printf("\r\n");
    for(i=0;i<16;i++)
    {
        printf("%x " , Cn[i]);
    }
    printf("\r\n");
}
for(i=0;i<16;i++)
    mac[i]=Cn[i];

}

/第一次开始计算**/
void CMAC_CalStart(uint8_t *data, uint8_t * key, uint32_t len, Mac_Para_Out *mac_para_out )
{
int j;
for(j=0;j<16;j++)
// mac_para_out->M_c2[j]=data[j]mac_para_out->M_c1[j]mac_para_out->key_1[j];
mac_para_out->M_c2[j]=mac_para_out->M_c1[j]^data[j];
EncryPtion(mac_para_out->M_c2,key,mac_para_out->M_c1);

printf("将第一次加密后的结果放到struct里,并将其输出出来");
 printf("\r\n");
for( j = 0 ; j < 16 ;j++)
{
    printf("%x ",mac_para_out->M_c1[ j ]);
}
printf("\r\n");

}

/中间部分计算***/
void CMAC_CalMid(uint8_t *data, uint8_t * key, uint32_t len, Mac_Para_Out mac_para_out)
{
int i,j,n;
n=(len+15)/16; //用于确定分几组
printf("\r\n");
printf(“将上一次加密后结果输出,,,,”);
printf("\r\n");
for( j = 0 ; j < 16 ;j++)
{
printf("%x ",mac_para_out->M_c1[ j ]);
}
for(i=0;i<(n);i++)
{
for(j=0;j<16;j++)
mac_para_out->M_c2[j]=mac_para_out->M_c1[j]^data[16
i+j];
EncryPtion(mac_para_out->M_c2,key,mac_para_out->M_c1); // M_c1 is output

 printf("\r\n");
    printf("mid部分,将中间n次加密后的结果放到struct里,并将其输出出来");
    printf("\r\n");
for( j = 0 ; j < 16 ;j++)
{
    printf("%x ",mac_para_out->M_c1[ j ]);
}
 printf("\r\n");
}

}

/最后不全的,需要补全计算/
void CMAC_CalEnd(uint8_t *data, uint8_t * key, uint32_t len, Mac_Para_Out *mac_para_out)
{
int i,j,n,last_i;
int flag=0; //用于标记密文分组是否完整
uint8_t last[16];
n=(len+15)/16; //用于确定分几组
last_i=len%16;
if(last_i0)
flag=1; //标明是分组长度b=128的整数倍
if(flag
0)

printf("\r\n");
printf("end:将上一次加密后结果输出,,,,");
printf("\r\n");
for( j = 0 ; j < 16 ;j++)
    {
        printf("%x ",mac_para_out->M_c1[ j ]);
    }

fil(&data[16*(n-1)], last_i,last);
//对前n-1轮
for(i=0;i<n-1;i++)
{
    for(j=0;j<16;j++)
    mac_para_out->M_c2[j]=mac_para_out->M_c1[j]^data[16*i+j];
    EncryPtion(mac_para_out->M_c2,key,mac_para_out->M_c1);  // M_c1  is output
    printf("\r\n");
    printf("cal_end:将M_c1的结果输出来,也就是前N-1轮加密的结果");
     printf("\r\n");
    for(i=0;i<16;i++)
    printf("%x " , mac_para_out->M_c1[i]);
    printf("\r\n");

}
 printf("\r\n");

if(flag==1)
{
    for(i=0;i<16;i++)
    mac_para_out->M_c_k[i]=data[16*(n-1)+i]^mac_para_out->M_c1[i]^mac_para_out->key_1[i];
    EncryPtion(mac_para_out->M_c_k, key, mac_para_out->Cn);
    printf("\r\n");
    printf("将Cn的结果输出来,也就是第N次加密后的结果");
     printf("\r\n");
    for(i=0;i<16;i++)
    {
        printf("%x " ,mac_para_out->Cn[i]);
    }
    printf("\r\n");
}
else
{
    for(i=0;i<16;i++)
    mac_para_out->M_c_k[i]=last[i]^mac_para_out->M_c1[i]^mac_para_out->key_2[i];
    EncryPtion(mac_para_out->M_c_k, key,mac_para_out->Cn);
    printf("\r\n");
    printf("将最后不全的数值Cn的结果输出,也就是最后不全部分补全后输出");
     printf("\r\n");
    for(i=0;i<16;i++)
    {
        printf("%x " ,mac_para_out->Cn[i]);
    }
    printf("\r\n");
}

}

  1. main函数
    /**主函数/

int main()
{
uint8_t mac[16]={0};
uint8_t key[16]={22, 11, 15, 16, 28, 11, 20, 56, 11, 55, 15, 88, 34, 44, 44, 33};
uint8_t Mass[62]={ 12, 22, 22, 40, 45, 96, 65, 33, 77, 11, 73, 93, 17, 44, 55, 22,
88, 57, 12, 03, 33, 55, 66, 74, 77, 88, 45,56, 65, 51, 30, 34, 54, 46, 55, 66, 77, 11,
65, 55, 44, 19, 33, 22, 52, 11, 23, 32, 24, 45,
43, 45, 45, 17, 45, 54, 41, 65, 67, 76, 37, 10};
uint8_t Mass_start[16]={12, 22, 22, 40, 45, 96, 65, 33, 77, 11, 73, 93, 17, 44, 55, 22};
uint8_t Mass_mid[32]={88, 57, 12, 03, 33, 55, 66, 74, 77, 88, 45,56, 65, 51, 30, 34,
54, 46, 55, 66, 77, 11,65, 55, 44, 19, 33, 22, 52, 11, 23,32};
/uint8_t Mass_mid[48]={12, 22, 22, 40, 45, 96, 65, 33, 77, 11, 73, 93, 17, 44, 55, 22,
88, 57, 12, 03, 33, 55, 66, 74, 77, 88, 45,56, 65, 51, 30, 34,
54, 46, 55, 66, 77, 11,65, 55, 44, 19, 33, 22, 52, 11, 23,32};
/
uint8_t Mass_last[14]={24, 45,43, 45, 45, 17, 45, 54, 41, 65, 67, 76, 37, 10};

     Mac_Para_Out mac_para_out;

            printf("这个是对于62个都进行CMAC运算后的结果");
            printf("\r\n");
            AES_CMAC(Mass,key ,62,mac );
            for(int i=0;i<16;i++)
            printf("%x ",mac[i]);

            printf("\r\n");
            printf("这个是对于前16个都进行CMAC运算后的结果");
            printf("\r\n");
            k1_k2_test(key, &mac_para_out);
            CMAC_CalStart(Mass_start,key ,16,&mac_para_out);
            for(int i=0;i<16;i++)
            printf("%x ",mac_para_out.M_c1[i]);
            printf("\r\n");

           printf("这个是对中间32个进行CMAC计算结果");
            printf("\r\n");
            CMAC_CalMid(Mass_mid,key,32,&mac_para_out );
            for(int i=0;i<16;i++)
            printf("%x ",mac_para_out.M_c1[i]);
            printf("\r\n");

            printf("这个是对于最后14个都进行CMAC运算后的结果");
            printf("\r\n");
            CMAC_CalEnd(Mass_last,key,14, &mac_para_out);
            for(int i=0;i<16;i++)
            printf("%x ",mac_para_out.Cn[i]);

     return 0;

}

5.关于CMAC算法的介绍,好多人都写过,我这里就不说了,就把结果发出来,记录一下,感兴趣的,可以看我 之前的文章,
在这里插入图片描述
在这里插入图片描述

  • 4
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值