C语言:ANSI-X9.9-MAC算法实现

示例代码:

****************************************************************************************

"mac.c"

/* ANSI-X9.9-MAC算法
 * 将data分为单位8字节的数据块(不足补0x00),分别标号D1-Dn
 * 初始向量E0^D1-->E1(E0与D1异或后DES加密得到E1)
 * E1^D2-->E2
 * 依此类推,得到En,即为MAC

 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/evp.h>
#include <openssl/err.h>

#define CHECK( func ) {             \
    if( EXIT_FAILURE == (func) ){   \
        exit( EXIT_FAILURE );       \
    }                               \
}

/* DES_CBC加密 */
static int encryptDes( unsigned char *key, unsigned char *plain,
    unsigned char *cipher, int plen )
{
    int clen = 0;
    int tmplen = 0;
    EVP_CIPHER_CTX ctx;

    /* 01:加密初始化
     * 使用DES_CBC算法加密 */
    EVP_EncryptInit( &ctx, EVP_des_cbc(), key, NULL );
    /* 设置不填充(缺省填充) */
    if( 0 == plen % 8 ){
        EVP_CIPHER_CTX_set_padding( &ctx, 0 );
    }

    /* 02:加密 */
    if( !EVP_EncryptUpdate( &ctx, cipher, &clen, plain, plen ) ){
        ERR_print_errors_fp( stderr );
        fprintf( stderr, "EVP_EncryptUpdate error\n" );
        return EXIT_FAILURE;
    }

    /* 03:加密后处理 */
    if( !EVP_EncryptFinal( &ctx, cipher + clen, &tmplen ) ){
        ERR_print_errors_fp( stderr );
        fprintf( stderr, "EVP_EncryptFinal error\n" );
        return EXIT_FAILURE;
    }
    clen += tmplen;

    return clen;
}

/* ASCII字符串转十六进制字符串显示 */
static int str2hex( unsigned char *sSrc, unsigned char *sDest, int nSrcLen )
{
    int  i, DestLen = 0;
    char szTmp[2 + 1];

    /* LOOP:针对每1个字符处理 */
    for( i = 0; i < nSrcLen; i++ )
    {
        sprintf( szTmp, "%02X", (unsigned char) sSrc[i] );
        memcpy( &sDest[i * 2], szTmp, 2 );
        DestLen += 2;
    }

    return DestLen;
}

/* 异或计算 */
static void xor( unsigned char *in1, unsigned char *in2,
    unsigned char *out, int len )
{
    while( len-- )
        *out++ = *in1++ ^ *in2++;
}

/* ANSI-X9.9-MAC算法 */
static int mac_X9_9( unsigned char *key, unsigned char *iv,
    unsigned char *data, unsigned char *mac, int len )
{
    int i = 0;
    int num = 0;
    unsigned char updata[9999 + 1] = {0};
    unsigned char ddata[8] = {0};
    unsigned char edata[8] = {0};
    unsigned char xdata[8] = {0};

    /* LOOP:以8字节为单位循环计算 */
    memcpy( edata, iv, 8 );
    memcpy( updata, data, len );
    num = ( len + 7 ) / 8;
    for( i = 0; i < num; i++ )
    {
        /* 确认Di */
        memcpy( ddata, updata + i * 8, 8 );

        /* 计算异或 */
        xor( edata, ddata, xdata, 8 );

        /* DES加密 */
        CHECK( encryptDes( key, xdata, edata, 8 ) );
    }

    /* 返回MAC-转换十六进制 */
    str2hex( edata, mac, 8 );

    return EXIT_SUCCESS;
}

/* 测试程序 */
int main( int argc, char *argv[] )
{
    int i = 0;
    unsigned char mac[999] = {0};
    unsigned char key[] = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08};
    unsigned char iv[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};

    if( 1 == argc ){
        fprintf( stderr, "Usage: %s <buf>\n", argv[0] );
        exit( EXIT_FAILURE );
    }

    printf( "BUF[%s]\n", argv[1] );

    CHECK( mac_X9_9( key, iv, argv[1], mac, strlen( argv[1] ) ) );

    printf( "MAC[%s]\n", mac );

    exit( EXIT_SUCCESS );
}

****************************************************************************************

"Makefile":

#执行文件
bin=imacx99

#目标文件
objects=mac.o

#连接规则
$(bin):$(objects)
 gcc -o ~/bin/$(bin) $(objects) -lssl -lcrypto -ldl

#清理对象
.PHONY:clean
clean:
 -rm ~/bin/$(bin) $(objects)

****************************************************************************************

验证效果:

【P.S.】说明:

  1. 以上截图中用于校验的“DES算法工具”可以网上搜索下载到;

转载于:https://my.oschina.net/u/2445210/blog/868708

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值