【问题标题】:Understanding engine initialization in OpenSSL了解 OpenSSL 中的引擎初始化
【发布时间】:2012-11-25 12:57:13
【问题描述】:

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

另外,我经常使用 Java,因此请随时指出代码中的任何错误。

#include <openssl/hmac.h>
#include <openssl/evp.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

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);

【问题讨论】:

    标签: c openssl


    【解决方案1】:

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

    一些附属问题:

    • 您的字符串是十六进制的,但您需要为每个字符添加一个 \x 才能在字符串中的该位置实际获取该十六进制字节,我怀疑这正是您想要的。
    • 您试图从“数据”中散列 40 个字节,这并不长(实际效果:您最终会部分散列结果字符串)
    • 您的预期结果(据我所知)不正确
    • 您可以将随机字符打印到终端,因为 HMAC 函数会生成 32 字节的随机二进制数据,而不是可打印的内容。

    以下代码可以编译、运行并通过测试。它与您找到的示例代码有点不同(因为它仍然使用单独的 HMAC_* 函数 - 如果您想使用 HMAC_Update 一点一点地进行散列,这很有用):

    #include <openssl/engine.h>
    #include <openssl/hmac.h>
    #include <openssl/evp.h>
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    
    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 的原始问题,但是如果没有更多上下文,确实没有正确的答案,而上下文与您的情况无关...

    【讨论】:

      【解决方案2】:

      好的,事实证明您不必使用引擎,但我完全误解了如何不使用显式引擎。我也误解了如何正确格式化测试向量。最后,我查看了 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);
        }
      }
      

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

      【讨论】:

      【解决方案3】:

      看起来好像没有分配引擎,所以e 的第一次使用是segfaulting。我认为您需要先致电ENGINE *ENGINE_new(void)

      (请注意,我使用过 OpenSSL,但之前没有使用过 ENGINE 函数。)

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

      1. 我已经看过ENGINE 函数的(长)man page,但我不太确定调用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);
        

      【讨论】:

      • 感谢 Martin 的建议,我已经尝试过了,但仍然卡住了。我很好奇关于你没有使用它的 ENGINE 评论。是否可以在没有引擎的情况下使用 OpenSSL?
      猜你喜欢
      • 1970-01-01
      • 2012-07-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-14
      • 1970-01-01
      • 2022-12-04
      相关资源
      最近更新 更多