質問
HMAC-SHA-256ハッシュの基本的なテストをセットアップしようとしていますが、エンジンのセットアップに問題があります。理想的には、HMAC-SHA-アルゴリズムのみをセットアップしたいのですが、これまでのところ、すべてのアルゴリズムをロードして動作させる一般的なケースさえ得ていません。現在、デフォルトのダイジェストを設定しようとしている行でセグメンテーション違反が発生しています。
また、私は定期的にJavaの男なので、コードの誤りを指摘することをtoしないでください。
#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);
解決
元の提案の問題は、Martinが言ったように、エンジンを初期化する必要があるということです。編集したコードの問題は、ENGINE_newを実行していたことです。これにより、独自の完全に新しいENGINEが取得されます。次に、暗号メソッド、ダイジェストメソッドなどを提供する必要があります。ほぼすべての人が望んでいます)、エンジンのすべてを完全に無視するのが正しい選択です。
いくつかの付随的な問題:
- 文字列は16進数でしたが、文字列内のその位置で実際にその16進数バイトを取得するには、文字ごとに\ xが必要でした。
- &quot; data&quot;から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を初期化する方法に関する元の質問には答えませんが、コンテキストがなければ、それに対する正しい答えはありません。コンテキストは状況に関係ないことが判明します...
他のヒント
わかりました。エンジンを使用する必要はありませんが、明示的なエンジンを使用しない方法を正確に誤解していました。また、テストベクターを適切にフォーマットする方法を誤解しました。最後に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
の最初の使用はセグメンテーション違反です。最初に ENGINE * ENGINE_new(void)
を呼び出す必要があると思います。
(OpenSSLを使用したことがありますが、 ENGINE
関数を使用したことがないことに注意してください。)
更新:私は自分の答えにあまり満足していません(以前はお茶に飛び出さなければなりませんでした)。それで、私のさらなるメモは:
-
(長い) manを少し見てきました
ENGINE
関数のページで、ENGINE_new
を呼び出すだけで十分かどうかはわかりません。 -
HMAC_CTX _ *
関数の呼び出しが、割り当てられた構造へのポインターではなく、初期化されていないポインターを使用していることに気付きませんでした。HMAC_CTX_init
は、ctx
パラメーターが指すメモリに書き込みを試みます。これにより、セグメンテーション違反が発生します。次のようにctx
を宣言して使用する必要があります:HMAC_CTX ctx; HMAC_CTX_init(&ctx); HMAC_Init_ex(&ctx, key, 40, EVP_sha256(), e); ...
その方法で、スタックに構造体を割り当ててから、ポインターを渡します。
-
HMAC
関数はCTX
へのポインタをまったく使用しないため、グローバルストレージまたはスレッドローカルストレージとは別に、わかりませんCTX
への接続です。HMAC_Update
を1回以上呼び出し、続いてHMAC_Final
を呼び出して結果を取得することで、これをバイパスできると思います。その結果のためにスペースを割り当てる必要があるため、次のようなものがそのために機能します:unsigned int len; HMAC_Final(&ctx, result, &len);