了解 OpenSSL 中的引擎初始化

发布于 2024-07-07 06:14:45 字数 1947 浏览 3 评论 0原文

我正在尝试设置 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);

I'm trying to set up a basic test of HMAC-SHA-256 hashing but I'm having problems with the engine setup. Ideally I would like to set up only the HMAC-SHA-algorithm but so far I haven't even gotten the general case where load all the algorithms to work. Currently I'm getting segfaults on the row where I try to set the default digests.

Also, I'm regularly a Java guy, so don't hesitate to point out any mistakes in the code.

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

EDIT: The program has now evolved to the following, but I'm still segfaulting at 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);

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

自由如风 2024-07-14 06:14:45

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

一些附属问题:

  • 您的字符串是十六进制的,但是您需要每个字符一个 \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;
}

当然,它并没有回答您最初的问题:如何初始化引擎,但是如果没有更多上下文,实际上没有正确的答案,而该上下文与您的情况无关......

The problem with your original suggestion is, as Martin said, that you need to initialise the ENGINE. The problem with your edited code was that you were doing ENGINE_new, which is getting you a completely new ENGINE of your own, which you then need to provide with cipher methods, digest methods, etc. In fact, for what you want (and what almost everybody wants), just completely ignoring all of the ENGINE stuff is the right choice.

Some subsidiary problems:

  • your strings were hex, but you needed a \x per character to actually get that hex byte at that position in the string, which I suspect was what you wanted.
  • you were trying to hash 40 bytes from "data", which wasn't that long (actual effect: you'd end up partly hashing your result string)
  • your expected result was (as far as I can tell) incorrect
  • you would print out random characters to the terminal, since the HMAC function will produce 32 bytes of random binary data, not printable stuff.

The following code compiles, works and passes the test. It's a bit different to the example code you found (since it still uses the individual HMAC_* functions - useful if you want to do your hashing bit by bit using 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;
}

Of course, it doesn't answer your original question about how to initialise ENGINEs, but there's really no right answer to that without having more context, which context turns out not to be relevant in your situation...

や三分注定 2024-07-14 06:14:45

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

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

Okay, turns out that you don't have to use an engine but I'd misunderstood exactly how not to use an explicit engine. I also misunderstood how to properly format the test vectors. In the end I looked at hmactest.c which pretty much does all I want to do, I just didn't understand the code.

The final solution to what I was trying to do looks like this:

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

But since I was asking about something entirely different, I'm unsure about what to do with the original question. Suggestions?

烛影斜 2024-07-14 06:14:45

看起来好像没有任何东西分配引擎,因此 e 的第一次使用是段错误。 我认为你需要先调用 ENGINE *ENGINE_new(void)

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

更新:我对自己的答案不太满意(我有之前冲去喝茶)。 所以我的进一步注释是:

  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, 结果, &len); 
      

It looks as though nothing is allocating an engine, so the first use of e is segfaulting. I think you need to call ENGINE *ENGINE_new(void) first.

(Note that I've used OpenSSL, but I haven't used the ENGINE functions before.)

Update: I'm not really happy with my own answer (I had to dash off to tea, before). So my further notes are:

  1. I've had a bit of a look at the (long) man page for the ENGINE functions, and I'm not quite sure that calling ENGINE_new is sufficient.

  2. I didn't notice that the calls to the HMAC_CTX_* functions were taking an uninitialized pointer, rather than a pointer to an allocated structure. HMAC_CTX_init will try to write to the memory pointed to by its ctx parameter, which will segfault. You need to declare and use ctx like this:

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

    That way you're allocating the structure on the stack, and then passing a pointer to it.

  3. The HMAC function doesn't take a pointer to a CTX at all, so apart from global or thread-local storage, I'm not sure what it's connection to the CTX is. I think you can bypass that by calling HMAC_Update one-or-more times, followed by HMAC_Final to get the result. You'd need to allocate space for that result, so something like the following would work for that:

    unsigned int len;
    HMAC_Final(&ctx, result, &len);
    
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文