首页 > 代码库 > 算法系列6——MAC

算法系列6——MAC

GP中定义的MAC可以和PBOC中的MAC通过简单计算相互转换,如下:

 

DATA=http://www.mamicode.com/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=http://www.mamicode.com/XOR(_DATA,DATAL)
GP_MAC(XDATA,KEY,MAC2)//MAC2=106729A5F51BFC24

 

 

在你仔细读了下面PBOC_MAC源码后,相信你就会理解上面GP_MAC和PBOC_MAC的转换关系了。

 

void DoSSMac(const BYTE* input, intnInLen, const BYTE* key, int nKeyLen, BYTE* output)
    {
        BYTE byInitVec[8];   //初始向量
        BYTE byTemp[8];

        memset(byInitVec, 0x00,sizeof(byInitVec));
        memset(byTemp,   0x00,sizeof(byTemp));

        memcpy(byInitVec, input, 8);

        BYTEbySubKey[3][16][48];        //秘钥

        memset(bySubKey, 0x01, sizeof(bySubKey));

        int i = 0;
        int j = (nInLen >> 3);

        //构造并生成SubKeys
        BYTE nKey = (nKeyLen >> 3) > 3 ?3 : (nKeyLen >> 3);
        for (i = 0; i < nKey; i++)
        {
           SetSubKey(&bySubKey[i], &key[i << 3]);
        }

        memcpy(output, input, 8);
        if (1 == nKey)    //单倍长Key(8字节)
        {
            j--;
            for (int i = 0; i <j; ++i)
            {
               Xor(input + 8 * (i + 1), output, 8, output);
               RunDes(output, 0, &bySubKey[0], output);

               //memcpy(byInitVec, output, 8);           //将输出设定为扭转变量
            }
        }
      <span style="color:#ff0000;"> //转换关系就在这里
       else if (2 == nKey)    //双倍长Key(16字节)
        {      
            j -= 2;
            for (i = 0; i < j;++i)
            {
               Xor(input + 8 * (i + 1), output, 8, output);
               RunDes(output, 0, &bySubKey[0],output);       //将输出设定为扭转变量    
            }
            Xor(input + 8 * (++i),output, 8, output);        //最后一块数据和上面加密结果异或
            RunDes(output, 0,&bySubKey[0], output);
            RunDes(output, 1,&bySubKey[1], output);
            RunDes(output, 0,&bySubKey[0], output);
        }</span>
        else  //三倍长Key(24字节)   尚未验证
        {
            //j -= 2;
            for (i = 0, j =(nInLen >> 3) - 2; i < j; ++i, input += 8)
            {
               Xor(input + 8 * (i + 1), output, 8, byTemp);
               RunDes(byTemp, 0, &bySubKey[0], output);

               memcpy(byInitVec, output, 8);           //将输出设定为扭转变量
            }
            Xor(input + 8 * i,output, 8, output);
            RunDes(output, 2,&bySubKey[0], output);
            RunDes(output, 1,&bySubKey[1], output);
            RunDes(output, 0,&bySubKey[0], output);
        }
    }