11

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

3 に答える 3

14

マーティンが言ったように、元の提案の問題は、エンジンを初期化する必要があることです。編集したコードの問題は、ENGINE_new を実行していたことでした。これにより、独自の完全に新しい ENGINE が取得され、暗号化メソッド、ダイジェスト メソッドなどを提供する必要があります。ほとんどの人が望んでいます)、すべての ENGINE を完全に無視するのが正しい選択です。

いくつかの副次的な問題:

  • あなたの文字列は16進数でしたが、文字列内のその位置でその16進バイトを実際に取得するには、文字ごとに \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;
}

もちろん、エンジンを初期化する方法についての元の質問には答えませんが、状況に関係がないことが判明したコンテキストがなければ、正しい答えはありません...

于 2008-10-29T00:08:01.367 に答える
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);
  }
}

しかし、私はまったく別のことを尋ねていたので、元の質問をどうすればよいかわかりません。提案?

于 2008-10-28T18:25:28.313 に答える
0

何もエンジンを割り当てていないように見えるので、最初の使用eは segfaulting です。まずは電話したほうがいいと思いますENGINE *ENGINE_new(void)

(私は OpenSSL を使用したことがありますが、ENGINE以前に関数を使用したことがないことに注意してください。)

更新:私は自分の答えに本当に満足していません(以前はお茶を飲みに行かなければなりませんでした)。したがって、私の追加のメモは次のとおりです。

  1. 関数の (長い) man ページを少し見ましたが、呼び出しで十分ENGINEかどうかはよくわかりません。ENGINE_new

  2. HMAC_CTX_*関数の呼び出しが、割り当てられた構造体へのポインターではなく、初期化されていないポインターを使用していることに気付きませんでした。HMAC_CTX_initパラメータが指すメモリに書き込もうとするため、ctxsegfault が発生します。ctx次のように宣言して使用する必要があります。

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

    そうすれば、スタックに構造体を割り当ててから、それにポインターを渡します。

  3. このHMAC関数は a へのポインターをまったく取りませんCTX。そのため、グローバルまたはスレッド ローカル ストレージを除けば、それが何に接続されているのかわかりませんCTXHMAC_Update1回以上呼び出してから結果を取得することで、それをバイパスできると思いますHMAC_Final。その結果にスペースを割り当てる必要があるため、次のようなものがそのために機能します。

    unsigned int len;
    HMAC_Final(&ctx, result, &len);
    
于 2008-10-28T09:46:12.123 に答える