BigInteger
を特定のサイズのバイト配列に変換し、最初 (左端) のバイトを使用してキーを作成する必要があります。このためには、キーを表すために値を左にパディングする必要があるため、DH で使用される素数 p のサイズを知る必要があります。標準化された DH パラメータを使用することをお勧めします (または、少なくとも素数のサイズが 8 で割り切れることを確認してください)。
BigInteger.toByteArray()
返される値は符号付き(2 の補数) ビッグ エンディアン バイト配列としてエンコードされるため、を使用して取得したバイト配列の前にゼロ値のバイトがある場合があることに注意してください。結果が素数 (バイト単位) よりも大きい場合は、このバイトを削除する必要があります。
public static byte[] encodeSharedSecret(final BigInteger sharedSecret, final int primeSizeBits) {
// TODO assignment add additional tests on input
final int sharedSecretSize = (primeSizeBits + Byte.SIZE - 1) / Byte.SIZE;
final byte[] signedSharedSecretEncoding = sharedSecret.toByteArray();
final int signedSharedSecretEncodingLength = signedSharedSecretEncoding.length;
if (signedSharedSecretEncodingLength == sharedSecretSize) {
return signedSharedSecretEncoding;
}
if (signedSharedSecretEncodingLength == sharedSecretSize + 1) {
final byte[] sharedSecretEncoding = new byte[sharedSecretSize];
System.arraycopy(signedSharedSecretEncoding, 1, sharedSecretEncoding, 0, sharedSecretSize);
return sharedSecretEncoding;
}
if (signedSharedSecretEncodingLength < sharedSecretSize) {
final byte[] sharedSecretEncoding = new byte[sharedSecretSize];
System.arraycopy(signedSharedSecretEncoding, 0,
sharedSecretEncoding, sharedSecretSize - signedSharedSecretEncodingLength, signedSharedSecretEncodingLength);
return sharedSecretEncoding;
}
throw new IllegalArgumentException("Shared secret is too big");
}
その後、ある種の鍵導出スキームを使用して鍵バイトを導出する必要があります。使用する必要があるものは、実装している標準によって異なります。
RFC 2631に記載されているとおり
X9.42 は、ZZ から本質的に任意の量のキーイング マテリアルを生成するためのアルゴリズムを提供します。私たちのアルゴリズムは、いくつかのオプションのフィールドを義務付け、他のフィールドを省略することによって、そのアルゴリズムから派生しています。
KM = H ( ZZ || OtherInfo)
H はメッセージ ダイジェスト関数 SHA-1 [FIPS-180] ZZ は、セクション 2.1.1 で計算された共有秘密値です。
ZZ が p と同じ数のオクテットを占めるように、先頭のゼロを保持する必要があります。
秘密の抽出に関する DH 実装の 1.49 (現時点での最新バージョン)までの Bouncy Castle ライブラリでバグを発見したことに注意してください。素数 p までの結果。これにより、192 回に 1 回 (!) 不正な派生キーが発生します。