在C中实现hmac sha1

在C中实现hmac sha1,c,hash,openssl,otp,hmacsha1,C,Hash,Openssl,Otp,Hmacsha1,我正在尝试生成Hmac-sha1的一小段代码。我被要求自己使用OpenSSL LIB为SHA1计算编写hmac实现代码。 在对算法进行“wiki”操作后,以下是我的内容。我使用了RFC 2246指定测试值的输入: Count Hexadecimal HMAC-SHA-1(secret, count) 0 cc93cf18508d94934c64b65d8ba7667fb7cde4b0 1 75a48a19d4cbe100644e8ac1397e

我正在尝试生成Hmac-sha1的一小段代码。我被要求自己使用OpenSSL LIB为SHA1计算编写hmac实现代码。 在对算法进行“wiki”操作后,以下是我的内容。我使用了RFC 2246指定测试值的输入:

   Count    Hexadecimal HMAC-SHA-1(secret, count)
   0        cc93cf18508d94934c64b65d8ba7667fb7cde4b0
   1        75a48a19d4cbe100644e8ac1397eea747a2d33ab
   2        0bacb7fa082fef30782211938bc1c5e70416ff44
   3        66c28227d03a2d5529262ff016a1e6ef76557ece
   4        a904c900a64b35909874b33e61c5938a8e15ed1c
   5        a37e783d7b7233c083d4f62926c7a25f238d0316
   6        bc9cd28561042c83f219324d3c607256c03272ae
   7        a4fb960c0bc06e1eabb804e5b397cdc4b45596fa
   8        1b3c89f65e6c9e883012052823443f048b4332db
   9        1637409809a679dc698207310c8c7fc07290d9e5
下面的代码是我使用RFC2104中的示例完成的,我根据需要获得计数器=0的值,但当计数器值设置为其他值(如2,3等)时,HMAC SHA1与RFC 2246中的上述值不匹配。另一个问题是,如果我使用memcpy和memset而不是bzero或bcopy,代码将显示不同(错误)的Hmac Sha1值,该值与COUNTER=0值不匹配。请解释一下为什么会有这种奇怪的动物

    #include <openssl/evp.h>
    #include <openssl/bn.h>
    #include <openssl/sha.h>
    #include <openssl/err.h>
    #include <openssl/conf.h>
    #include <openssl/engine.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>     /* for memset() */
    #include <unistd.h>

    #define IPAD 0x36
    #define OPAD 0x5C

    #define SHA1_DIGESTLENGTH 20
    #define SHA1_BLOCK_LENGTH 64
    #define COUNTER_LENGTH 8

    typedef unsigned          char uint8_t;
    typedef unsigned short     int uint16_t;
    typedef unsigned           int uint32_t;

    /**
     * Key
     */
   #define SECRET {  0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30  }
#define COUNTER {  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }



void hmacsha1(){
    uint8_t key[]= SECRET;
    int key_len = sizeof(key);
    uint8_t ctr[] = COUNTER;
    unsigned char k_ipad[65];    /* inner padding -
     * key XORd with ipad
     */
    unsigned char k_opad[65];    /* outer padding -
     * key XORd with opad
     */
    int i;
    uint8_t digest[20];
    memset(digest, 0, sizeof(digest));
    /*
     * the HMAC_MD5 transform looks like:
     *
     * MD5(K XOR opad, MD5(K XOR ipad, text))
     *
     * where K is an n byte key
     * ipad is the byte 0x36 repeated 64 times
     * opad is the byte 0x5c repeated 64 times
     * and text is the data being protected
     */

    /* start out by storing key in pads */

    bzero( k_ipad, sizeof k_ipad);
    bzero( k_opad, sizeof k_opad);
    bcopy( key, k_ipad, key_len);
    bcopy( key, k_opad, key_len);

/*
    memset( k_ipad, 0, sizeof k_ipad);
    memset( k_opad, 0, sizeof k_opad);
    memcpy( key, k_ipad, key_len);
    memcpy( key, k_opad, key_len);
*/
    /* XOR key with ipad and opad values */
    for (i=0; i<64; i++) {
        k_ipad[i] ^= 0x36;
        k_opad[i] ^= 0x5c;
    }
    /*
     * perform inner MD5
     */
    EVP_MD_CTX mdctx;
    const EVP_MD *md;

    unsigned char md_value[EVP_MAX_MD_SIZE];
    unsigned int md_len;

    OpenSSL_add_all_digests();


    md = EVP_get_digestbyname("sha1");

    if(!md) {
        printf("Unknown message digest\n");
        exit(1);
    }

    EVP_MD_CTX_init(&mdctx);
    EVP_DigestInit_ex(&mdctx, md, NULL);
    EVP_DigestUpdate(&mdctx, k_ipad, 64 );
    EVP_DigestUpdate(&mdctx, ctr, 8 );
    EVP_DigestFinal_ex(&mdctx, md_value, &md_len);

    EVP_MD_CTX_init(&mdctx);
    EVP_DigestInit_ex(&mdctx, md, NULL);
    EVP_DigestUpdate(&mdctx, k_opad, 64 );
    EVP_DigestUpdate(&mdctx, md_value, md_len );
    EVP_DigestFinal_ex(&mdctx, digest, &md_len);
    EVP_MD_CTX_cleanup(&mdctx);

    printf("Digest is: ");
    for(i = 0; i < md_len; i++) printf("%02x", digest[i]);
    printf("\n");

}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包含/*用于memset()*/
#包括
#定义iPad0x36
#定义OPAD 0x5C
#定义SHA1_DIGESTLENGTH 20
#定义SHA1_块长度64
#定义计数器长度8
typedef无符号字符uint8;
typedef无符号短整数uint16\u t;
typedef unsigned int uint32\u t;
/**
*钥匙
*/
#定义秘密{0x31、0x32、0x33、0x34、0x35、0x36、0x37、0x38、0x39、0x30、0x31、0x32、0x33、0x34、0x35、0x36、0x37、0x38、0x39、0x30}
#定义计数器{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}
void hmacsha1(){
uint8_t key[]=秘密;
int key_len=sizeof(key);
uint8_t ctr[]=计数器;
未签名字符k_[65];/*内部填充-
*ipad键盘XORd
*/
无符号字符k_opad[65];/*外部填充-
*带opad的键XORd
*/
int i;
uint8_t摘要[20];
memset(摘要,0,sizeof(摘要));
/*
*HMAC_MD5转换如下所示:
*
*MD5(KXOR opad,MD5(KXOR ipad,文本))
*
*其中K是一个n字节的密钥
*ipad是字节0x36,重复64次
*opad是重复64次的字节0x5c
*文本是被保护的数据
*/
/*从将钥匙存放在键盘开始*/
bzero(k_ipad,k_ipad的尺寸);
bzero(k_opad,k_opad的大小);
b复印件(钥匙、k_ipad、钥匙);
复印件(钥匙、钥匙、钥匙);
/*
memset(k_ipad,0,k_ipad尺寸);
memset(k_opad,0,k_opad的大小);
memcpy(键、k_ipad、键);
memcpy(键、k_opad、键、len);
*/
/*带有ipad和opad值的XOR键*/
对于(i=0;i首先,您必须

memcpy(k_ipad, key, key_len);

memcpy(k_opad, key, key_len);
而不是

memcpy( key, k_ipad, key_len);

memcpy( key, k_opad, key_len);

您可能不应该使用strncpy并尝试memcpy。strncpy可能会将某些0x00字节解释为字符串的结尾,而memcpy则不会。谢谢woodleg.as。让我尝试一下,然后返回:)您好woodleg.as,我已经更新了代码,请让我知道您的评论我并不是真正的安全专家。我提出这个建议是因为我觉得strncpy可能不适合您要求的任务。我希望其他对安全算法更了解的SO用户可以帮助您。对于任何其他关注这个问题的人有一天,我很确定openssl有它自己的HMAC功能:谢谢!难怪它不起作用!被bcopy弄糊涂了!!