只要有标准的DES加密和解密算法,类似ANSI-X99MAC算法和PBOC3DES算法就很好实现。他们都是用DES算法再经过一层算法实现的。实现原理看图就能看明白。3DES算法实现就更简单了。就是DES算法再加解密一次。
/* ************************************************************************************************************** * * 函数原型: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 ); //解 }
/******************************************************* * 名称:获取报文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 ); }
/* ************************************************************************************************* * 异或 ************************************************************************************************* */ void DataXOR( U08 *source, U08 *dest, U32 size, U08 *out ) { int i; for( i = 0; i < size; i++ ) { out[i] = dest[i] ^ source[i]; } }
/************************************************** * 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 ); }
实现MAC算法的原理,可以参考CPU卡指令手册或PBOC规范。如图:
MAC的计算:
3DES算法计算MAC