保存或移动OpenSSL上下文以“稍后”或“其他地方”继续哈希

时间:2018-02-18 23:12:20

标签: c hash openssl

我会事先说,我的目标是以确保安全,而是验证数据的完整性。

我想使用OpenSSL例程为几TB的数据计算标准哈希。数据是逻辑序列化的(即一个字节数组),但分布在许多计算机上。

不是将庞大的数据集移动到单个进程(和内存空间)进行散列,而是希望传递散列“上下文”,以便散列计算可以在数据被保存的任何地方进行。

构建问题的另一种方法是,我想稍后向数据集添加字节并继续哈希计算,但会产生相同的哈希答案,就像所有字节最初都可用一样。

我遇到了一个棘手的问题,因为我无法弄清楚库如何存储“上下文”。我不知道我需要传递或保存以实现我的意图。

(可以安全地假设所有散列参与者都将使用相同版本的OpenSSL库。)

我调整了文档示例来处理两个字节块以方便讨论。现在我想知道有没有办法在chunk1和chunk2之间拔掉电脑上的插头,仍然得到相同的答案?或者如果chunk1和chunk2存储在不同的计算机上怎么办?

echo preg_replace('~^.{3}\K([^\s]*) *~', '-$1', 'jjfnj 948');

输出:

#include <openssl/evp.h>

#include <stdio.h>
#include <string.h>


void print_bytes(const unsigned char * bytes, size_t count, const char * prefix)
{
    printf("%s",prefix);
    for(size_t i = 0; i < count; ++i) {
        printf("%02x", bytes[i]);
    }
    printf(" (%zd Bytes)\n", count);
}


unsigned int md5_digest_process(const EVP_MD* type, const unsigned char *input, size_t numBytes, unsigned char* hash_out) {
    EVP_MD_CTX mdctx;
    unsigned int hash_len = 0;

    size_t chunk1_size = numBytes/2;
    size_t chunk2_size = numBytes - chunk1_size;


    EVP_MD_CTX_init(&mdctx);
    print_bytes( (const unsigned char *)&mdctx, sizeof(EVP_MD_CTX), "EVP_MD_CTX: " );

    EVP_DigestInit_ex(&mdctx, type, NULL);
    print_bytes( (const unsigned char *)&mdctx, sizeof(EVP_MD_CTX), "EVP_MD_CTX: " );

    // Hash chunk 1:
    EVP_DigestUpdate(&mdctx, input, chunk1_size);
    print_bytes( (const unsigned char *)&mdctx, sizeof(EVP_MD_CTX), "EVP_MD_CTX: " );

    // Hash chunk 2:    
    EVP_DigestUpdate(&mdctx, input+chunk1_size, chunk2_size);
    print_bytes( (const unsigned char *)&mdctx, sizeof(EVP_MD_CTX), "EVP_MD_CTX: " );

    EVP_DigestFinal_ex(&mdctx, hash_out, &hash_len);
    EVP_MD_CTX_cleanup(&mdctx);
    return hash_len;
}


int main(int argc, char *argv[]) {
    if (argc!=2) {
        fprintf(stderr, "One argument string expected.\n");
        return 1;
    }

    //OpenSSL_add_all_digests();
    //const EVP_MD *md = EVP_get_digestbyname("MD5");
    const EVP_MD *md = EVP_md5(); //EVP_sha256();
    if(!md) {
        fprintf(stderr, "Unable to init MD5 digest\n");
        return 1;
     }


    unsigned char hash[EVP_MAX_MD_SIZE];

    const unsigned char * allBytes = (const unsigned char *)argv[1];
    size_t numBytes = strlen(argv[1]); // skip null terminator, consistent with command line md5 -s [string]

    printf("Hashing %zd bytes. EVP_MAX_MD_SIZE is %zd, EVP_MD_CTX size is %zd bytes.\n", numBytes, EVP_MAX_MD_SIZE, sizeof(EVP_MD_CTX));

    int hash_len = md5_digest_process(md, allBytes, numBytes, hash);
    print_bytes(hash, hash_len, "Hash: " );

    return 0;
}

由于每次更新后$ ./a.out foobar Hashing 6 bytes. EVP_MAX_MD_SIZE is 64, EVP_MD_CTX size is 48 bytes. EVP_MD_CTX: 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 (48 Bytes) EVP_MD_CTX: 609d9d01010000000000000000000000000000000000000080274062cd7f0000000000000000000040de8e0101000000 (48 Bytes) EVP_MD_CTX: 609d9d01010000000000000000000000000000000000000080274062cd7f0000000000000000000040de8e0101000000 (48 Bytes) EVP_MD_CTX: 609d9d01010000000000000000000000000000000000000080274062cd7f0000000000000000000040de8e0101000000 (48 Bytes) Hash: 3858f62230ac3c915f300c664312c63f (16 Bytes) $ md5 -s foobar MD5 ("foobar") = 3858f62230ac3c915f300c664312c63f 没有变化,我推断算法状态实际上存储在别处,我不能简单地复制48个EVP_MD_CTX字节。

我在手册中看过EVP_MD_CTX,但我不知道如何将它用于我的目的。

0 个答案:

没有答案