了解OpenSSL中的引擎初始化

我正在尝试设置HMAC-SHA-256哈希的基本测试,但我遇到引擎设置问题。 理想情况下,我只想设置HMAC-SHA算法,但到目前为止,我还没有得到加载所有算法的一般情况。 目前我正在尝试设置默认摘要的行上获得段错误。

此外,我经常是一个Java人,所以不要犹豫,指出代码中的任何错误。

#include  #include  #include  #include  #include  int main() { unsigned char* key = (unsigned char*) "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"; unsigned char* data = (unsigned char*) "4869205468657265"; unsigned char* expected = (unsigned char*) "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7"; unsigned char* result; HMAC_CTX* ctx; ENGINE* e; ENGINE_load_builtin_engines(); ENGINE_register_all_complete(); ENGINE_set_default_digests(e); HMAC_CTX_init(ctx); HMAC_Init_ex(ctx, key, 40, EVP_sha256(), e); result = HMAC(NULL, NULL, 40, data, 16, NULL, NULL); HMAC_CTX_cleanup(ctx); ENGINE_finish(e); ENGINE_free(e); if (strcmp((char*) result, (char*) expected) == 0) { printf("Test ok\n"); } else { printf("Got %s instead of %s\n", result, expected); } } 

编辑:该程序现在已演变为以下,但我仍然在HMAC_Init_ex

 unsigned char* key = (unsigned char*) "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"; unsigned char* data = (unsigned char*) "4869205468657265"; unsigned char* expected = (unsigned char*) "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7"; unsigned char* result; unsigned int result_len = 64; HMAC_CTX ctx; ENGINE* e; result = (unsigned char*) malloc(sizeof(char) * result_len); e = (ENGINE*) ENGINE_new(); ENGINE_load_builtin_engines(); ENGINE_register_all_complete(); ENGINE_set_default_digests(e); HMAC_CTX_init(&ctx); HMAC_Init_ex(&ctx, key, 16, EVP_sha256(), e); HMAC_Update(&ctx, data, 40); HMAC_Final(&ctx, result, &result_len); HMAC_CTX_cleanup(&ctx); ENGINE_finish(e); ENGINE_free(e); 

正如Martin所说,您最初建议的问题是需要初始化ENGINE。 您编辑的代码的问题在于您正在使用ENGINE_new,它会为您提供一个全新的ENGINE,然后您需要使用密码方法,摘要方法等提供。事实上,您想要的是什么(以及几乎每个人都想要),完全忽略所有的ENGINE东西都是正确的选择。

一些辅助问题:

  • 你的字符串是hex的,但你需要一个\ x每个字符来实际获得字符串中该位置的hex字节,我怀疑这是你想要的。
  • 你试图从“数据”哈希40个字节,这不是那么长(实际效果:你最终部分哈希你的结果字符串)
  • 你的预期结果是(据我所知)不正确
  • 你会把随机字符打印到终端,因为HMAC函数会产生32字节的随机二进制数据,而不是可打印的东西。

以下代码编译,工作并通过测试。 它与您找到的示例代码略有不同(因为它仍然使用单独的HMAC_ *函数 – 如果您想使用HMAC_Update逐位进行散列,则非常有用):

 #include  #include  #include  #include  #include  #include  int main(void) { unsigned char* key = (unsigned char*) "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"; unsigned char* data = (unsigned char*) "\x48\x69\x20\x54\x68\x65\x72\x65"; unsigned char* expected = (unsigned char*) "\x49\x2c\xe0\x20\xfe\x25\x34\xa5\x78\x9d\xc3\x84\x88\x06\xc7\x8f\x4f\x67\x11\x39\x7f\x08\xe7\xe7\xa1\x2c\xa5\xa4\x48\x3c\x8a\xa6"; unsigned char* result; unsigned int result_len = 32; int i; HMAC_CTX ctx; result = (unsigned char*) malloc(sizeof(char) * result_len); ENGINE_load_builtin_engines(); ENGINE_register_all_complete(); HMAC_CTX_init(&ctx); HMAC_Init_ex(&ctx, key, 16, EVP_sha256(), NULL); HMAC_Update(&ctx, data, 8); HMAC_Final(&ctx, result, &result_len); HMAC_CTX_cleanup(&ctx); for (i=0; i!=result_len; i++) { if (expected[i]!=result[i]) { printf("Got %02X instead of %02X at byte %d!\n", result[i], expected[i], i); break; } } if (i==result_len) { printf("Test ok!\n"); } return 0; } 

当然,它没有回答关于如何初始化ENGINE的原始问题,但如果没有更多的上下文,那么实际上没有正确的答案,哪种情境在你的情况下并不相关……

好的,事实certificate你不必使用引擎,但我误解了如何不使用显式引擎。 我也误解了如何正确格式化测试向量。 最后我看了一下hmactest.c,这几乎是我想做的事情,我只是不明白代码。

我试图做的最终解决方案如下:

 int main() { unsigned char* key = (unsigned char*) "Jefe"; unsigned char* data = (unsigned char*) "what do ya want for nothing?"; unsigned char* expected = (unsigned char*) "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843"; unsigned char* result; unsigned int result_len = 32; int i; static char res_hexstring[32]; result = HMAC(EVP_sha256(), key, 4, data, 28, NULL, NULL); for (i = 0; i < result_len; i++) { sprintf(&(res_hexstring[i * 2]), "%02x", result[i]); } if (strcmp((char*) res_hexstring, (char*) expected) == 0) { printf("Test ok, result length %d\n", result_len); } else { printf("Got %s instead of %s\n", res_hexstring, expected); } } 

但由于我问的是完全不同的东西,我不确定如何处理原始问题。 建议?

看起来好像什么都没有分配引擎,所以e的首次使用是segfaulting。 我认为你需要先调用ENGINE *ENGINE_new(void)

(注意我已经使用过OpenSSL,但我之前没有使用过ENGINEfunction。)

更新 :我对自己的回答并不满意(之前我不得不冲下去喝茶)。 所以我的进一步说明是:

  1. 我已经看了一下ENGINE函数的(长) 手册页 ,我不太确定调用ENGINE_new就足够了。

  2. 我没注意到对HMAC_CTX_*函数的调用是采用未初始化的指针,而不是指向已分配结构的指针。 HMAC_CTX_init将尝试写入其ctx参数指向的内存,这将是段错误。 你需要像这样声明和使用ctx

     HMAC_CTX ctx; HMAC_CTX_init(&ctx); HMAC_Init_ex(&ctx, key, 40, EVP_sha256(), e); ... 

    这样你就可以在堆栈上分配结构,然后将指针传递给它。

  3. HMAC函数根本没有指向CTX的指针,因此除了全局或线程本地存储之外,我不确定它与CTX的连接是什么。 我认为您可以通过调用HMAC_Update一次或多次来绕过它,然后通过HMAC_Final来获取结果。 您需要为该结果分配空间,因此以下内容适用于此:

     unsigned int len; HMAC_Final(&ctx, result, &len);