ANSI-X99MAC algorithm and PBOC 3DES MAC algorithm, with DES algorithm tool

ANSI-X99MAC algorithm and PBOC's 3DES MAC algorithm, with DES algorithm tool
https://blog.csdn.net/MaxWoods/article/details/48525473

https://blog.csdn.net/redumbrella/article/details/7569887
https://blog.csdn.net/qq445803843/article/details/44927273

/************************************************** 
* PBOC-3DES MAC计算 
**************************************************/  
void PBOC_3DES_MAC( U08 *buf, U32 buf_size, U08 *key, U08 *mac_buf )  
{  
    U08 val[8],xor[8];  
    U08 keyL[8],keyR[8];  
    U08 block[512];  
    U16 x,n;  
    U16 i;  
    memcpy(keyL,key,8);  
    memcpy(keyR,&key[8],8);  
    //准备工作  
    memcpy( block, buf, buf_size ); //将输入数据赋值给临时变量block  
    x = buf_size / 8; //计算有多少个完整的块  
    n = buf_size % 8; //计算最后一个块有几个字节  
    if( n != 0 )     //y非0,则在其后补上0x00...  
    {  
        memset( &block[x*8+n], 0x00, 8-n );  
        block[x*8+n]=0x80;    
    }  
    else  
    {  
        memset( &block[x*8], 0x00, 8 );//如果最后一块长度是8个字节,则最后加80 00。。  
        block[x*8]=0x80;  
    }  
    //开始运算  
    memset( val, 0x00, 8 );//初始向量  
    memcpy( val, UPPAN,8 );  
    DataXOr(val,&block[0], 8,xor);  
    for( i = 1; i < x+1; i++ )    //有多少块循环多少次  
    {   
        CurCalc_DES_Encrypt(keyL,xor,val);//DES加密  
        DataXOr(val,&block[i*8], 8,xor);  
        // j += 8;   //用于取下一块的数据  
    }  
    CurCalc_DES_Encrypt(keyL,xor,val);  
    CurCalc_DES_Decrypt(keyR,val,xor);  
    CurCalc_DES_Encrypt(keyL,xor,val);  
    memcpy(mac_buf,val, 8 );  
}  

As long as there are standard DES encryption and decryption algorithms, similar to ANSI-X99MAC algorithm and PBOC3DES algorithm can be implemented very well. They are all implemented with the DES algorithm and then through a layer of algorithms. The realization principle can be understood by looking at the diagram. The 3DES algorithm is simpler to implement. It is the DES algorithm and decryption again.

/* 
************************************************************************************************************** 
* 
* 函数原型:void CurCalc_3DES_Encrypt( U08 *inkey, U08 *indata, U08 *outdata ) 
* 
* 函数功能:3DES加密 
* 
* 函数输入:inkey        16字节密码 
*           indata      8字节需要加密的数据 
*                 
* 函数输出:outdata      8字节加密结果输出 
* 
* 函数返回:无 
*    
************************************************************************************************************** 
*/  
void CurCalc_3DES_Encrypt( U08 *inkey, U08 *indata, U08 *outdata )  
{  
    U08 LKey[8];  
    U08 RKey[8];  
    U08 TmpDest[8];  

    MyCopy( LKey, inkey,   8 );  
    MyCopy( RKey, inkey+8, 8 );  

    CurCalc_DES_Encrypt( LKey, indata,  outdata );          //加  
    CurCalc_DES_Decrypt( RKey, outdata, TmpDest );          //解  
    CurCalc_DES_Encrypt( LKey, TmpDest, outdata );          //加  
}  

/* 
************************************************************************************************************** 
* 
* 函数原型:void CurCalc_3DES_Decrypt( U08 *inkey, U08 *indata, U08 *outdata ) 
* 
* 函数功能:3DES解密 
* 
* 函数输入:inkey        8字节密码 
*           indata      8字节需要解密的数据 
*                 
* 函数输出:outdata      8字节解密结果输出 
* 
* 函数返回:无 
*    
************************************************************************************************************** 
*/  
void CurCalc_3DES_Decrypt( U08 *inkey, U08 *indata, U08 *outdata )  
{  
    U08 LKey[8];  
    U08 RKey[8];  
    U08 TmpDest[8];  

    MyCopy( LKey, inkey,   8 );  
    MyCopy( RKey, inkey+8, 8 );  

    CurCalc_DES_Decrypt( LKey, indata,  outdata );          //解  
    CurCalc_DES_Encrypt( RKey, outdata, TmpDest );          //加  
    CurCalc_DES_Decrypt( LKey, TmpDest, outdata );          //解  
}  

222

/******************************************************* 
* 名称:获取报文MAC值 
* 功能:报文MAC算法 
* 入口: 
* *buf ,要计算的数据缓冲区;buf_size,计算数据的长度 
* *key ,密钥(8B) 
* 出口:mac_buf,计算出来的MAC值(8B) 
ansi x9.9 MAC算法 

********************************************************/  
void Ansi99X_Get_MAC( U08 *buf, U32 buf_size, U08 *key, U08 *mac_buf )  
{  
    U08 val[8],xor[8];  
    U08 block[512];  
    U16 x,n;  
    U16 i,j=0;  
    //准备工作  
    memcpy( block, buf, buf_size ); //将输入数据赋值给临时变量block  
    x = buf_size / 8; //计算有多少个完整的块  
    n = buf_size % 8; //计算最后一个块有几个字节  
    if( n != 0 )     //y非0,则在其后补上0x00...  
    {  
        memset( &block[x*8+n], 0x00, 8-n );  
        x += 1; //将补上的这一块加上去  
    }  
    //开始运算  
    memset( val, 0x00, 8 );  
    for( i = 0; i < x; i++ )  //有多少块循环多少次  
    {  
        DataXOR(val,&block[j], 8,xor);  
        CurCalc_DES_Encrypt(key,xor,val);//DES加密  
        j += 8;  //用于取下一块的数据  
    }  
    memcpy(mac_buf,val, 8 );  
}  

333

/* 
************************************************************************************************* 
*  异或           
************************************************************************************************* 
*/  
void DataXOR( U08 *source, U08 *dest, U32 size, U08 *out )  
{  
   int i;  
   for( i = 0; i < size; i++ )  
   { out[i] = dest[i] ^ source[i]; }  
}  

For the principle of implementing the MAC algorithm, you can refer to the instruction manual of the CPU card or the PBOC specification. As shown in the figure:
MAC calculation:
write picture description here

Mac calculation steps:

1. The terminal sends the GET CHALLENGE command to the CPU card to obtain a 4-byte random number, followed by "0x00000000", and the obtained 8-byte result is used as the initial value of the MAC calculation.

2. Check whether the number of bytes of "04D6960024 + val" is a multiple of 8, if not, fill in "0x8000...", if it is, fill in "0x8000000000000000", and then divide the obtained result into D1, D2, D3 by 8 bytes each. …

3. Determine the length of the key.

If the key length is 8 bytes, the MAC is calculated as follows:

write picture description here

If the key length is 16 bytes, the MAC is calculated as follows:
write picture description here

Introduction to MAC

The MAC is generated using all elements of the command, including the command header. The integrity of a command, including the data elements in the command data field (if present), is guaranteed by secure messaging. Use the single or triple DEA encryption method to generate the MAC as follows:
Step 1: Take the 8-byte hexadecimal number '0' as the initial variable.
Step 2: Concatenate the data together in order to form a data block.
The third step: the data block is divided into 8-byte data blocks, labeled as D1, D2, D3, D4, etc. The final data block may be 1-8 bytes.

write picture description here
Step 4: If the length of the last data block is 8 bytes, add the hexadecimal number '80 00 00 00 00 00 00 00' after it, and go to the fifth step. If the length of the last data block is less than 8 bytes, add the hexadecimal number '80' after it, if it reaches the length of 8 bytes, go to the fifth step; otherwise, add the hexadecimal number '0' after it ' until the length reaches 8 bytes.
Step 5: Encrypt these data blocks using the MAC process key. If the secure messaging supports single-length MAC DEA keys, the MAC procedure key is used to generate the MAC as shown in the following figure.
Step 6: The final result is the 4-byte MAC obtained from the left side of the calculation result.
write picture description here

Source code implementation:

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);  
        }  
    }  

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325992895&siteId=291194637