5

EC キーを使用したデータの署名中に、ランダム シードとして使用する OpenSSL 固有のデータをフィードしたいと考えています。これは、自分のアプリケーションを別の参照アプリケーション (クローズド ソース) と比較するために行っています。このユーティリティは、秘密鍵を含むファイル、署名するデータを含むファイル、およびランダム データを含むファイルをパラメーターとして受け取ります。

私は EC キーの生成とデータの署名を行いましたが、共通点がないため、2 つのアプリケーションを比較することはできません。OpenSSL は、データの署名に使用されるランダム データを (おそらく /dev/random から) 生成するため、実行ごとに異なる署名が得られます。

RAND_clear()と組み合わせて試してみましRAND_add()たが、署名が変化し続けています。ECDSA の概念全体を理解していないか、何か間違っています。

アプリケーションを比較するための 2 つ目のオプションは、公開鍵をインポートし、参照プログラムによって生成された署名を検証することです。これはより良いオプションですが、指定された公開鍵の例 (83 文字の 16 進文字列) をインポートできません。EC_POINT_oct2point()私にnullの結果を与え続けます。

ヘルプ/ポインター/リファレンスは大歓迎です。

char * key_as_binary_data;  //369368AF243193D001E39CE76BB1D5DA08A9BC0A63307AB352338E5EA5C0E05A0C2531866F3E3C2702
int data_size;  //Size of the key buffer
EC_POINT * ecpoint = NULL;
EC_GROUP * ecgroup = NULL;
EC_KEY * eckey = NULL;
point_conversion_form_t form = POINT_CONVERSION_UNCOMPRESSED;
int asn1_flag = OPENSSL_EC_NAMED_CURVE;

eckey = EC_KEY_new();
ecpoint = EC_POINT_new(ecgroup);
ecgroup = EC_GROUP_new_by_curve_name(OBJ_sn2nid("sect163k1"));
EC_GROUP_set_asn1_flag(ecgroup, asn1_flag);
EC_GROUP_set_point_conversion_form(ecgroup, form);
EC_KEY_set_group(eckey,ecgroup);
EC_KEY_generate_key(eckey);

//This gives me a null ecpoint
EC_POINT_oct2point(ecgroup,ecpoint,key_as_binary_data,data_size-1,ctx); 
EC_KEY_set_public_key(eckey,ecpoint);
4

5 に答える 5

3

これは、その公開鍵をロードする方法です。

  EC_KEY    *key = NULL;
  EC_POINT *pub_key;
  const EC_GROUP *group;

  SSL_library_init();
  SSL_load_error_strings();

  key = EC_KEY_new_by_curve_name(NID_sect163k1);
  group = EC_KEY_get0_group(key);
  pub_key = EC_POINT_new(group);

  EC_POINT_hex2point(group,
    "369368AF243193D001E39CE76BB1D5DA08A9BC0A63307AB352338E5EA5C0E05A0C2531866F3E3C2702", pub_key, NULL);

  EC_KEY_set_public_key(key, pub_key);

  if (!EC_KEY_check_key(key)) {
    printf("EC_KEY_check_key failed:\n");
    printf("%s\n",ERR_error_string(ERR_get_error(),NULL));
  } else {
    printf("Public key verified OK\n");
  }

OKを確認しているようですので、署名をチェックするために機能するはずです。

あなたのバグは(ecgroup内の)NULLをEC_POINT_new()に渡しただけかもしれないと思います。

于 2009-07-23T15:20:24.743 に答える
2

プールをクリアしてリセットしているにもかかわらず、異なる結果が得られる理由は、デフォルトで OpenSSL の RAND 実装が pid を出力ブロックにハッシュするためです (正確には、同じシードを使用するアプリケーションでも同じ結果が得られないようにするためです)。 99.9% の確率で問題が発生するため、PRNG 出力)。

さらに、そうでなかったとしても、シード ファイルを一連のランダム バイトに変換するために OpenSSL が使用するのと同じ PRNG を参照アプリケーションが使用する可能性は低いです。(もちろん、参照アプリケーションが実際に OpenSSL も使用している場合を除きます)。まず、リファレンス アプリが使用する PRNG の種類を把握する必要があります。これは、X9.31 や FIPS-186 のような標準的な PRNG 設計である場合もあれば、完全にカスタム化されたものである場合もあります。次に、その設計を OpenSSL 用に再実装し、 経由でプラグインしRAND_set_rand_methodます。

検証に関して: 行を転置する必要があるようです:

   ecpoint = EC_POINT_new(ecgroup);
   ecgroup = EC_GROUP_new_by_curve_name(OBJ_sn2nid("sect163k1"));

そうしないと、最初から ecpoint が NULL に設定されEC_KEY_generate_key、グループが NULL に設定されているため失敗します。openssl-0.9.8k の crypto/ec/ec_key.c からの引用:

if (!eckey || !eckey->group)
   {
   ECerr(EC_F_EC_KEY_GENERATE_KEY, ERR_R_PASSED_NULL_PARAMETER);
   return 0;
   }
于 2009-08-07T15:34:26.563 に答える
0

署名手順は純粋に、あなたが署名したことを他の誰かが確認できるようにするためのものです。実際に秘密鍵を持っていなくても、メッセージ (または任意のデータ) に署名するために使用されたのは秘密鍵でした。

アルゴリズムはウィキペディアElliptic_Curve_DSAで概説されて います 「署名生成アルゴリズム」を読むと、署名の強度を高め、秘密鍵を突き止めるための攻撃を困難にするためにランダムデータが使用されているようです。

したがって、これは単なるハッシュではないため、署名は毎回異なると予想する必要があります。

セクション「署名検証アルゴリズム」を参照して、検証手順が、openssl バージョンが ECDSA メソッドとクローズド ソース プログラムに関して有効な署名を出力していることを確認するために使用する手順であることを確認してください。

于 2009-07-23T12:10:35.090 に答える
0

のドキュメントが見つからないためRAND_clear、再現可能な乱数が得られない理由についてコメントできません。

しかし、それができたとしても、あなたが望んでいることはできないかもしれません。ECDSA 署名の生成では、特定の範囲内のランダムな整数を選択する必要があります。アルゴリズムの 2 つの異なる実装では、エントロピー ソースからそのような整数を生成する方法について、まったく異なるアイデアが存在する可能性があります。私の知る限り、エントロピーのビットを必要な数に変換する手段は、ECDSAアルゴリズムの一部ではありません。

したがって、たとえば (もちろん非常に悪い例です)、1 つの実装で次のようにすることができます。

int random_number = rand() % n;

そして別の人はこれを行うかもしれません:

int random_number = (rand() * n) / RAND_MAX;

そのため、同じシード データを提供しても、異なる実装から異なる署名を取得する可能性があります。できることは、有効な署名を生成したかどうかを検証することだけです。

于 2009-07-23T13:17:56.390 に答える