2

そのため、RSA キー ペアを作成するための独自の実装を持つ独自のライブラリを使用しています。公開鍵の構造体は次のようになります。

typedef struct
{
   unsigned int bits;                         //Length of modulus in bits
   unsigned char modulus[MAX_RSA_MOD_LEN];    //Modulus
   unsigned char exponent[MAX_RSA_MOD_LEN];   //Exponent
} RSA_PUB_KEY

検証スキームの一部として指数とモジュールの両方をサーバーに送信できるように、指数とモジュールの両方を抽出する方法を見つける必要があります。これはかなり標準的な手順だと思います(またはそう願っています)。私はすでにこれらの2つの同様の質問を読みました:

しかし、これまでのところ、私は運がありませんでした。また、必要に応じて「ビット」フィールドを使用してモジュラスを抽出する方法もわかりません。つまり、私がしなければならないことは、この公開鍵を Java で再作成できるようにすることです。

BigInteger m = new BigInteger(MODULUS); 
BigInteger e = new BigInteger(EXPONENT);

RSAPublicKeySpec keySpec = new RSAPublicKeySpec(m, e);
KeyFactory fact = KeyFactory.getInstance("RSA");
PublicKey pubKey = fact.generatePublic(keySpec);

return pubKey;

編集:

これが私が今行っていることです: (RSAPublic は上記の RSA_PUB_KEY 構造体です)。

//RSAPublic.bits = length of modulus in bits                
log("Modulus length: "+std::to_string(RSAPublic.bits));
log("Key length: "+std::to_string(keyLengthInBits));

//Calculating buffer size for converted hexadec. representations
int modulusLengthInBytes = (RSAPublic.bits+7)/8 ;
int exponentLengthInBytes = (keyLengthInBits+7)/8;

char convertedMod[modulusLengthInBytes*2+1];
char convertedExp[exponentLengthInBytes*2+1];

//Conversion
int i;
for(i=0; i<modulusLengthInBytes ; i++){
  sprintf(&convertedMod[i*2], "%02X", RSAPublic.modulus[i]);
}
for(i=0; i<exponentLengthInBytes ; i++){
  sprintf(&convertedExp[i*2], "%02X", RSAPublic.exponent[i]);
}

//Print results
printf("Modulus: %s\n", convertedMod);  
printf("Exponent: %s\n", convertedExp); 

そして、これは出力です:

Modulus length: 16
Key length: 512
Modulus: 0000
Exponent: 0A000200FFFFFFFFFFFF0000600007004DDA0100B01D0000AEC642017A4513000000000000000000000000000000000000000000000000000000000000000000
4

2 に答える 2

2

16進数変換について言及しているので、バイナリデータを送信することはできないと思います。データをテキストとして送信できる最もコンパクトな方法は base 64 を使用することですが、これは 16 進数よりも複雑です。

クライアント側

あなたが持っているリンクからのメソッドを使用して、unsigned char 配列を 16 進文字列に変換します。このbitsフィールドは、 で指定された配列から使用するバイト数を決定します(bits+7)/8

実装によっては、オーバーフロー ビットを明示的に選択する必要があるか、残りがゼロになる可能性があります。これはエンディアンにも依存するため、実装の詳細がわからないため、少しいじる必要があるかもしれません。

エンコードされた文字列を取得したら、それらをサーバーに送信します。

サーバ側

BigInteger(String val, int radix)エンコードされた文字列を接続から読み取り、 16 進数 (16) の基数を使用してコンストラクターに渡します。

BigIntegerその後、必要な値を持つ Aが得られます。

于 2013-08-09T21:50:10.827 に答える
1

公開指数の最初のバイトがすべてゼロの場合、ビッグ エンディアン配列を扱っています。これが最も一般的です。原則として、公開指数はモジュラスと同じ大きさにすることができますが、通常はそうではありません。最も一般的な値は 65537、17、および 3 で、場合によっては 2 でもありますが、3 と 2 はあまり適切な値ではありません。他の 2 ~ 4 バイトの素数も一般的です。

エンディアンがわかっている場合は、モジュラスを確認できます。最上位のバイト値が の場合00、モジュラスの符号付き表現を扱っています。それ以外の場合は、署名されていない可能性があります。ビットを含むモジュラスの最上位バイトは、常に80またはそれ以上である必要があります。そうしないと、キーのサイズが指定されたキーのサイズよりも小さくなるためです。もちろん、これは鍵のサイズが 8 の倍数であることを前提としています。

Java はビッグ エンディアンBigInteger(およびその他の数値表現) でのみ機能します。したがって、C でリトル エンディアン エンコーディングを使用している場合は、Java で値を逆にする必要があります。これを実現するには、文字列内の 16 進数値を逆にするのがおそらく最善です。一度に 2 つの 16 進数文字を処理するようにしてください。

次に、DrYap が示唆したように、の 16 進数コンストラクターを使用しますBigIntegernew BigInteger(1, MODULUS)バイト配列を使用することになった場合は、エンコーディングの最上位ビット値に関係なく正の数を取得できるようにするため、使用したい場合があることに注意してください。

于 2013-08-10T00:26:51.477 に答える