算法系列6《MAC》



1. 简介


    MAC是使用命令的所有元素(包括命令头)产生的。一条命令的完整性,包括命令数据域(如果存在的话)中的数据元,通过安全报文传送得以保证。按照如下的方式使用单重或三重DEA加密方式产生MAC:
第一步:取8个字节的16进制数字’0’作为初始变量。
第二步:按照顺序将数据串联在一起形成数据块。
第三步:将该数据块分成8字节为单位的数据块,标号为D1、D2、D3、D4等。最后的数据块有可能是1-8个字节。





第四步:如果最后的数据块长度是8字节的话,则在其后加上16进制数字’80 00 00 00 00 00 00 00’,转到第五步。如果最后的数据块长度不足8字节,则在其后加上16进制数字’80’,如果达到8字节长度,则转入第五步;否则在其后加入16进制数字’0’直到长度达到8字节。
第五步:对这些数据块使用MAC过程密钥进行加密。如果安全报文传送支持单长度的MAC DEA密钥,则依照下图的方式使用MAC 过程密钥来产生MAC。

第六步:最终得到是从计算结果左侧取得的4字节长度的MAC。






2. 源码实现:

  1. void DoSSMac(const BYTE* input, intnInLen, const BYTE* key, int nKeyLen, BYTE* output)  
  2.     {  
  3.         BYTE byInitVec[8];   //初始向量  
  4.         BYTE byTemp[8];  
  5.   
  6.         memset(byInitVec, 0x00,sizeof(byInitVec));  
  7.         memset(byTemp,   0x00,sizeof(byTemp));  
  8.   
  9.         memcpy(byInitVec, input, 8);  
  10.   
  11.         BYTEbySubKey[3][16][48];        //秘钥  
  12.   
  13.         memset(bySubKey, 0x01, sizeof(bySubKey));  
  14.   
  15.         int i = 0;  
  16.         int j = (nInLen >> 3);  
  17.   
  18.         //构造并生成SubKeys  
  19.         BYTE nKey = (nKeyLen >> 3) > 3 ?3 : (nKeyLen >> 3);  
  20.         for (i = 0; i < nKey; i++)  
  21.         {  
  22.            SetSubKey(&bySubKey[i], &key[i << 3]);  
  23.         }  
  24.   
  25.         memcpy(output, input, 8);  
  26.         if (1 == nKey)    //单倍长Key(8字节)  
  27.         {  
  28.             j--;  
  29.             for (int i = 0; i <j; ++i)  
  30.             {  
  31.                Xor(input + 8 * (i + 1), output, 8, output);  
  32.                RunDes(output, 0, &bySubKey[0], output);  
  33.   
  34.                //memcpy(byInitVec, output, 8);           //将输出设定为扭转变量  
  35.             }  
  36.         }  
  37.       <span style="color:#ff0000;"//转换关系就在这里  
  38.        else if (2 == nKey)    //双倍长Key(16字节)  
  39.         {        
  40.             j -= 2;  
  41.             for (i = 0; i < j;++i)  
  42.             {  
  43.                Xor(input + 8 * (i + 1), output, 8, output);  
  44.                RunDes(output, 0, &bySubKey[0],output);       //将输出设定为扭转变量      
  45.             }  
  46.             Xor(input + 8 * (++i),output, 8, output);        //最后一块数据和上面加密结果异或  
  47.             RunDes(output, 0,&bySubKey[0], output);  
  48.             RunDes(output, 1,&bySubKey[1], output);  
  49.             RunDes(output, 0,&bySubKey[0], output);  
  50.         }</span>  
  51.         else  //三倍长Key(24字节)   尚未验证  
  52.         {  
  53.             //j -= 2;  
  54.             for (i = 0, j =(nInLen >> 3) - 2; i < j; ++i, input += 8)  
  55.             {  
  56.                Xor(input + 8 * (i + 1), output, 8, byTemp);  
  57.                RunDes(byTemp, 0, &bySubKey[0], output);  
  58.   
  59.                memcpy(byInitVec, output, 8);           //将输出设定为扭转变量  
  60.             }  
  61.             Xor(input + 8 * i,output, 8, output);  
  62.             RunDes(output, 2,&bySubKey[0], output);  
  63.             RunDes(output, 1,&bySubKey[1], output);  
  64.             RunDes(output, 0,&bySubKey[0], output);  
  65.         }  
  66.     }  
  67.   
  68.    

3. GP MAC

GP中定义的MAC可以和PBOC中的MAC通过简单计算相互转换,如下:
DATA=84820000100102030405060708800000
ICV=0000000000000000
KEY=404142434445464748494A4B4C4D4E4F
安全通道协议标识ALGSCP=02
 
3DES_MAC_1为PBOC中规定的计算MAC方法
3DES_MAC_1(ICV+DATA,KEY,MAC1)//MAC1=106729A5F51BFC24
 
 
GP_MAC为GP中规定的计算MAC方法,相当于CBC_MAC取后8字节。
DATAL=LAST(DATA,16)
DATAB=COPY(DATA,1,16)
KEY1=COPY(KEY,1,16)
CBC_3DES_EN(ICV+DATAB,KEY1,_DATA) 
XDATA=XOR(_DATA,DATAL)
GP_MAC(XDATA,KEY,MAC2)//MAC2=106729A5F51BFC24
 
在你仔细读了PBOC_MAC源码后,相信你就会理解上面GP_MAC和PBOC_MAC的转换关系了。




文/闫鑫原创   转载请注明出处http://blog.csdn.net/yxstars/article/details/38456657

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值