dtx3006 2015-04-20 18:40
浏览 487
已采纳

如何通过PKCS5_PBKDF2_HMAC和hash_hmac在C和php中获得相同的输出

I'm trying to duplicate a hashing function in C to be used on an existing database of hashes and salts. However once I reduced how PHP gets a sha256 hash and how c gets one, I can't get the same hashes.

I have looked though quite a few methods of getting the same hashes in C, but I can't quite figure out what's wrong the C code. The C code works, but the output is not the same.

Here is the base of my PHP code, it takes password and uses a single space as a salt, the rest of the code is just to visualize and see the output:

<?php
$salt = ' ';
$password = 'password';
$temp1 = hash_hmac('sha256', $salt, $password, true);


echo "======================
<br>";
echo "password  [${password}]
<br>";
echo "salt          [${salt}]
<br>";
echo "======================
<br>";
    echo gettype($temp1) . "
<br>";
    echo "each char as dechex(ord(x))
<br>";
    for ($i = 0; $i < strlen($temp1); ++$i) {
        $x = dechex(ord($temp1[$i]));
        echo "[$x] ";
    }

echo "-------------------------
<br>";
    echo "base64_encode
<br>";
echo base64_encode($temp1)."
<br>"; ?>

and the output

====================== 
password    [password] 
salt    [ ] 
====================== 
string 
each char as dechex(ord(x)) 
[52] [33] [c] [6b] [2f] [b6] [22] [cd] [bb] [73] [93] [c2] [5c] [be] [6c] [f4] [d3] [a6] [26] [cc] [ef] [aa] [9] [5e] [e0] [93] [33] [8] [83] [8d] [9] [63] ------------------------- 
base64_encode 
UjMMay+2Is27c5PCXL5s9NOmJszvqgle4JMzCIONCWM= 

The C I'm using, this is the simplest of examples I could find. I am only looking to get the same hash output. It does not have to use this method. I also included the base64 include function I'm using just in case:

    #include <string.h>
#include <stdio.h>
#include <openssl/evp.h>
#include <openssl/sha.h>
#include <openssl/pem.h>
#include <openssl/hmac.h>
#define PBKDF2_DIGEST_LENGTH        SHA256_DIGEST_LENGTH
#define PBKDF2_SALT_PREFIX          ""
#define PBKDF2_SALT_PREFIX_LENGTH   strlen(PBKDF2_SALT_PREFIX)
#define PBKDF2_PRF_ALGORITHM_OLD        EVP_sha512()
#define PBKDF2_DIGEST_LENGTH_OLD       SHA512_DIGEST_LENGTH
#define PBKDF2_SALT_LENGTH          32
#define PBKDF2_RESULT_LENGTH        PBKDF2_SALT_PREFIX_LENGTH + (2 * PBKDF2_DIGEST_LENGTH) + PBKDF2_SALT_LENGTH + 2
#define PBKDF2_ROUNDS               1000


#define PBKDF2_PRF_ALGORITHM        EVP_sha256()


char *base64encode (const void *b64_encode_this, int encode_this_many_bytes){
    BIO *b64_bio, *mem_bio;      //Declares two OpenSSL BIOs: a base64 filter and a memory BIO.
    BUF_MEM *mem_bio_mem_ptr;    //Pointer to a "memory BIO" structure holding our base64 data.
    b64_bio = BIO_new(BIO_f_base64());                      //Initialize our base64 filter BIO.
    mem_bio = BIO_new(BIO_s_mem());                           //Initialize our memory sink BIO.
    BIO_push(b64_bio, mem_bio);            //Link the BIOs by creating a filter-sink BIO chain.
    BIO_set_flags(b64_bio, BIO_FLAGS_BASE64_NO_NL);  //No newlines every 64 characters or less.
    BIO_write(b64_bio, b64_encode_this, encode_this_many_bytes); //Records base64 encoded data.
    BIO_flush(b64_bio);   //Flush data.  Necessary for b64 encoding, because of pad characters.
    BIO_get_mem_ptr(mem_bio, &mem_bio_mem_ptr);  //Store address of mem_bio's memory structure.
    BIO_set_close(mem_bio, BIO_NOCLOSE);   //Permit access to mem_ptr after BIOs are destroyed.
    BIO_free_all(b64_bio);  //Destroys all BIOs in chain, starting with b64 (i.e. the 1st one).
    BUF_MEM_grow(mem_bio_mem_ptr, (*mem_bio_mem_ptr).length + 1);   //Makes space for end null.
    (*mem_bio_mem_ptr).data[(*mem_bio_mem_ptr).length] = '\0';  //Adds null-terminator to tail.
    return (*mem_bio_mem_ptr).data; //Returns base-64 encoded data. (See: "buf_mem_st" struct).
}

int main(void)
{
    static unsigned char hb[PBKDF2_DIGEST_LENGTH];
    static unsigned char hashBlock[PBKDF2_DIGEST_LENGTH];

    char *password = "password";
    char *salt = " ";
    int passes = 1;


    PKCS5_PBKDF2_HMAC(password, strlen(password), salt, strlen(salt) , passes, PBKDF2_PRF_ALGORITHM, PBKDF2_DIGEST_LENGTH, hb);

    unsigned int i = 0;
    printf("printf hex
");
    while(i<32)
    {
        printf("[%x] ",  hb[i]);
        ++i;
    }
    printf("

");
    printf("base-64 encode
");
    printf("%s 
", base64encode(hb, 32));

    return 0;
}

The output that C produces, basically to visualize the output:

    ./pbkdf2_hack
printf hex
[f8] [8b] [fe] [58] [64] [f8] [a] [ef] [c0] [da] [b2] [97] [42] [ce] [b3] [83] [67] [85] [a5] [f2] [c8] [94] [7b] [2d] [82] [5d] [8a] [a5] [c0] [46] [9a] [24]

base-64 encode
+Iv+WGT4Cu/A2rKXQs6zg2eFpfLIlHstgl2KpcBGmiQ=

Compiling, in case something needs to be different here:

gcc pbkdf2_example.c -lcrypto -o pbkdf2_example
  • 写回答

1条回答

  • duan0530 2015-04-21 16:03
    关注

    By trying various combinations I found the proper way of updating the hash. I didn't really search for documentation so its probably my fault. I am posting this so someone hopefully doesn't have the same frustration I've had.

    #include <string.h>
    #include <stdio.h>
    #include <openssl/evp.h>
    #include <openssl/sha.h>
    #include <openssl/pem.h>
    #include <openssl/hmac.h>
    #define PBKDF2_DIGEST_LENGTH        SHA256_DIGEST_LENGTH
    #define PBKDF2_DIGEST_LENGTH_OLD       SHA512_DIGEST_LENGTH
    #define PBKDF2_ROUNDS               1000
    #define PBKDF2_PRF_ALGORITHM        EVP_sha256()
    
    void PBKDF2_HMAC_SHA_256(const char* pass, const unsigned char* salt, int iterations, unsigned char outputbytes, char* HexResult)
    {
        unsigned int i;
        unsigned char digest[outputbytes];
        PKCS5_PBKDF2_HMAC(pass, strlen(pass), salt, strlen(salt), 1, EVP_sha256(), outputbytes, digest);
        for (i = 0; i < sizeof(digest); i++)
           sprintf(HexResult + (i * 2), "%02x", 255 & digest[i]);
    }
    
    char *base64encode (const void *b64_encode_this, int encode_this_many_bytes){
        BIO *b64_bio, *mem_bio;      //Declares two OpenSSL BIOs: a base64 filter and a memory BIO.
        BUF_MEM *mem_bio_mem_ptr;    //Pointer to a "memory BIO" structure holding our base64 data.
        b64_bio = BIO_new(BIO_f_base64());                      //Initialize our base64 filter BIO.
        mem_bio = BIO_new(BIO_s_mem());                           //Initialize our memory sink BIO.
        BIO_push(b64_bio, mem_bio);            //Link the BIOs by creating a filter-sink BIO chain.
        BIO_set_flags(b64_bio, BIO_FLAGS_BASE64_NO_NL);  //No newlines every 64 characters or less.
        BIO_write(b64_bio, b64_encode_this, encode_this_many_bytes); //Records base64 encoded data.
        BIO_flush(b64_bio);   //Flush data.  Necessary for b64 encoding, because of pad characters.
        BIO_get_mem_ptr(mem_bio, &mem_bio_mem_ptr);  //Store address of mem_bio's memory structure.
        BIO_set_close(mem_bio, BIO_NOCLOSE);   //Permit access to mem_ptr after BIOs are destroyed.
        BIO_free_all(b64_bio);  //Destroys all BIOs in chain, starting with b64 (i.e. the 1st one).
        BUF_MEM_grow(mem_bio_mem_ptr, (*mem_bio_mem_ptr).length + 1);   //Makes space for end null.
        (*mem_bio_mem_ptr).data[(*mem_bio_mem_ptr).length] = '\0';  //Adds null-terminator to tail.
        return (*mem_bio_mem_ptr).data; //Returns base-64 encoded data. (See: "buf_mem_st" struct).
    }
    
    /*
        const * , not changing the value or pointer
    
    */
    void DisplayItem(const unsigned char *hb, const char *title) {
    
        unsigned int i = 0;
        printf("printf hex
    ");
        while(i<32)
        {
            printf("[%x] ",  hb[i]);
            ++i;
        }
        printf("base-64 encode %s
    ", title);
        printf("%s 
    ", base64encode(hb, 32));
        printf("
    
    ");
    
    }
    
    int main(void)
    {
        static unsigned char hb[PBKDF2_DIGEST_LENGTH];
        static unsigned char hashBlock[PBKDF2_DIGEST_LENGTH];
        unsigned char finalBlock[PBKDF2_DIGEST_LENGTH];
        SHA256_CTX ctx;
        HMAC_CTX hmac_ctx;
    
        char* title = "";
        unsigned char *password = "password";
        unsigned char *salt = " ";
        int passes = 1;
    
        memset(hb, 0, PBKDF2_DIGEST_LENGTH);
        HMAC_Init(&hmac_ctx, password, strlen(password), PBKDF2_PRF_ALGORITHM);
        HMAC_Update(&hmac_ctx, salt, strlen(salt));
        HMAC_Final(&hmac_ctx, hb, NULL);
        DisplayItem(hb, "HMAC_CTX pass salt - correct working setup");
    
        memset(hb, 0, PBKDF2_DIGEST_LENGTH);
        SHA256_Init(&ctx);
        SHA256_Update(&ctx, salt, strlen(salt));
        SHA256_Update(&ctx, password, strlen(password));
        SHA256_Final(hb, &ctx);
        DisplayItem(hb, "SHA256_CTX salt pass");
    
    
        memset(hb, 0, PBKDF2_DIGEST_LENGTH);
        SHA256_Init(&ctx);
        SHA256_Update(&ctx, password, strlen(password));
        SHA256_Update(&ctx, salt, strlen(salt));
        SHA256_Final(hb, &ctx);
        DisplayItem(hb, "SHA256_CTX  pass salt");
    
        memset(hb, 0, PBKDF2_DIGEST_LENGTH);
        HMAC_Init(&hmac_ctx, salt, strlen(salt), PBKDF2_PRF_ALGORITHM);
        HMAC_Update(&hmac_ctx, password, strlen(password));
        HMAC_Final(&hmac_ctx, hb, NULL);
        DisplayItem(hb, "HMAC_CTX salt pass");
    
    
        memset(hb, 0, PBKDF2_DIGEST_LENGTH);
        PKCS5_PBKDF2_HMAC(password, strlen(password), salt, strlen(salt), 1, PBKDF2_PRF_ALGORITHM, PBKDF2_DIGEST_LENGTH, hb);
        DisplayItem(hb, "PKCS5_PBKDF2_HMAC pass salt");
    
        memset(hb, 0, PBKDF2_DIGEST_LENGTH);
        PKCS5_PBKDF2_HMAC(salt, strlen(salt), password, strlen(password), 1, PBKDF2_PRF_ALGORITHM, PBKDF2_DIGEST_LENGTH, hb);
        DisplayItem(hb, "PKCS5_PBKDF2_HMAC salt pass");
        /*
        char *outputfoo[PBKDF2_DIGEST_LENGTH];
        memset(outputfoo, 0, PBKDF2_DIGEST_LENGTH);
        PBKDF2_HMAC_SHA_256(password, salt, 1, hb, outputfoo);
        printf("xxxxxx    %s 
    ", outputfoo);
        */
    
    
    
        return 0;
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 delta降尺度计算的一些细节,有偿
  • ¥15 Arduino红外遥控代码有问题
  • ¥15 数值计算离散正交多项式
  • ¥30 数值计算均差系数编程
  • ¥15 redis-full-check比较 两个集群的数据出错
  • ¥15 Matlab编程问题
  • ¥15 训练的多模态特征融合模型准确度很低怎么办
  • ¥15 kylin启动报错log4j类冲突
  • ¥15 超声波模块测距控制点灯,灯的闪烁很不稳定,经过调试发现测的距离偏大
  • ¥15 import arcpy出现importing _arcgisscripting 找不到相关程序