在OpenSSL中多次调用摘要更新

时间:2016-01-18 13:36:42

标签: c hash openssl

我已经读过,为了使用EVP_Digest调用发送要散列的大数据,可以多次调用EVP_DIgestUpdate。

我需要调用EVP_Update并获取部分计算的哈希值,然后发送剩余的输入(以及部分计算的哈希值)来计算输入的整个哈希值。

我已编写以下代码进行测试:

 int try()
 {
 EVP_MD_CTX ctx;
 const EVP_MD *md;
 //char data[] = "Test Message\n";
 unsigned char md_value[EVP_MAX_MD_SIZE];
 unsigned int md_len, i;
 char *data = "test";

 OpenSSL_add_all_digests();

 md = EVP_get_digestbyname("SHA256");

 if(!md) {
        printf("Unknown message digest\n");
        exit(1);
 }
 EVP_MD_CTX_init(&ctx);
 EVP_DigestInit_ex(&ctx, md, NULL);
 EVP_DigestUpdate(&ctx, data, strlen(data));
 //EVP_DigestUpdate(&ctx, toB64val, strlen(toB64val));
 EVP_DigestFinal_ex(&ctx, md_value, &md_len); //retrieve digest from ctx unto md_value and #bytes written is copied into md_len


 EVP_MD_CTX newctx;
  //char data[] = "Test Message\n";
  unsigned char new_md_value[EVP_MAX_MD_SIZE];
  unsigned int new_md_len;

  EVP_MD_CTX_init(&newctx);
  EVP_DigestInit_ex(&newctx, md, NULL);
 char *newdata = " message";
 printf("md_len = %d\n", md_len);
 int newlen = md_len;
 EVP_DigestUpdate(&newctx, md_value, 32);
 EVP_DigestUpdate(&newctx, newdata, strlen(data));
 //EVP_DigestUpdate(&ctx, toB64val, strlen(toB64val));
 EVP_DigestFinal_ex(&newctx, new_md_value, &new_md_len);

 EVP_MD_CTX_cleanup(&newctx);

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

 return 0;

 }

我正在尝试为&#34;测试消息&#34;计算哈希值(sha256)。作为我的输入。 但是,我需要能够检索&#34;部分计算的哈希&#34;的&#34;测试&#34;然后再将它再次提供给另一个新的上下文计算整个输入。

然而哈希o&#34;测试消息&#34;如单独计算不匹配。有人可以帮忙吗?

谢谢

2 个答案:

答案 0 :(得分:0)

SHA256块大小为64字节,因此您只能在输入消息的64字节边界上获得有意义的部分哈希。在内部,EVP正在缓冲消息,直到它达到64字节。

当请求散列结果时,消息用1位填充,后跟0位,后跟64位消息长度(以位为单位),使其成为64字节的倍数。

因此,您计算的第一个哈希是在消息上:

c  = '\0';

其次,即使您的部分消息是64字节的倍数,您也不能将部分散列作为数据传递给新散列。假设您打算在最后一次调用{"test", 1'b1, 415'b0, 64'h32} 时传递strlen(newdata)而不是strlen(data),那么您计算的哈希值将超过填充的320位消息:

EVP_DigestUpdate

与填充的96位消息的哈希值不同:

{<32-byte hash>, " message", 1'b1, 127'b0, 64'h320}

为了继续部分哈希,必须保存并恢复哈希状态({"test message", 1'b1, 351'b0, 64'h96} )(不确定EVP是否为此提供API)。因为您的部分消息太短,所以哈希状态将不会从初始更新,并且消息残留(最后未完成块的部分)将位于EVP上下文内的缓冲区中,等待用于构成块的更多数据。因此,除了哈希状态之外,您还需要保存并恢复消息残留。

答案 1 :(得分:0)

如果要获取“部分摘要”,可以复制EVP_MD_CTX,然后从副本中获取摘要。因此:

EVP_MD_CTX ctx, partial_ctx;

/* ... call EVP_DigestUpdate() several times... */
EVP_DigestUpdate(&ctx, data, data_len);

/* Now, we're going to get the digest up thus far, without
 * interrupting/changing the final digest, by making a copy of ctx,
 * and using the copy to get the partial digest.
 */
EVP_MD_CTX_init(&partial_ctx);
EVP_MD_CTX_copy(&partial_ctx, &ctx);
EVP_DigestFinal_ex(&partial_ctx, partial_md_value, &partial_md_len);

/* Don't forget to cleanup the partial ctx. */
EVP_MD_CTX_cleanup(&partial_ctx);

/* Continue digesting more data to get the final digest. */
EVP_DigestUpdate(&ctx, data, data_len);

希望这有帮助!