指定された長さの完全にランダムなキーを含むファイルを生成しようとしています。たとえば、100ビットをファイルに保存します。それを行うための最良の方法は何ですか?また、どの言語が最良のライブラリを提供しますか?前もって感謝します。
4 に答える
ランダム性にはさまざまなレベルの「強さ」があります。真のランダム ビットまたは疑似ランダム ビットのいずれかを取得できます。真にランダムなビットは、実世界のソースからエントロピーを導き出します。疑似ランダム ビットは、ランダムに見えるが実際には予測可能な一連のビットを生成します。
キーを生成するときは、暗号化強度を持つように指定されたランダムネス ジェネレーターを常に使用する必要があります。これらのランダム ビット ジェネレーターは、真に予測不可能になるように慎重に設計されています。キーを生成するためにランダム性の弱いソースを使用しないでください。
C# では、適切な名前の乱数ジェネレーター暗号化サービス プロバイダーのインスタンスを作成し、 GetBytesを呼び出して目的の長さのランダム バイトの配列を取得することで、これを行うことができます。
言うまでもなく、独自の暗号鍵を生成するときは十分に注意してください。暗号化とは、キーのセキュリティをメッセージのセキュリティに活用することです。キーの生成、保存、送信の方法に十分注意しないと、セキュリティ システムが危険にさらされます。自分で暗号化コードを作成しようとするのではなく、暗号化の専門家を雇うことを検討してください。
また、アプリケーションによっては、100 ビットでは鍵のサイズが小さすぎたり、大きすぎたりする場合があることにも注意してください。アルゴリズムが小さい鍵サイズでの攻撃に対して脆弱である可能性があるという点で小さすぎる可能性があり、一部の国ではビット数が多すぎる暗号化ソフトウェアの使用または輸出を制限しているという意味で大きすぎる可能性があります。弁護士に相談することを検討してください。
完全にランダムとはどういう意味かによって異なります。疑似乱数ジェネレーターが受け入れられる場合は、C++<random>
ライブラリが最適なオプションです。
それよりも強力な保証が必要な場合でも、プラットフォームにその機能がある場合、非決定論的な乱数を提供するstd::random_device
fromを使用できる場合があります。<random>
暗号乱数ジェネレーターへのアクセスを提供する場合もあります。プラットフォームのドキュメントを確認する必要があります。
#include <random>
#include <iostream>
int main() {
std::random_device r("/dev/random"); // Cryptographically secure RNG on Linux, OpenBSD, OSX, (using libc++)
unsigned int completely_random_value = r();
std::cout << completely_random_value << '\n';
}
関連する可能性があることの 1 つは、VS11 での random_device の実装に関する Microsoft のドキュメントからの次のメモです。「この実装では、デフォルトで生成される値は非決定論的ではありません。」これは、Visual Studio の C++11 ライブラリのもう 1 つの残念な実装品質の問題です (少なくとも、chrono::high_resolution_clock の解像度が低いことに伴います)。
真の乱数は決定論的なプロセスでは生成できないため、言語の選択はある意味では重要ではありません。「キー」と言うので、おそらく暗号化キーを探していると思いますが、これらを決定論的なプロセスで生成することは非常に危険であり、多数のシステム ブレークの原因となります。
私は全体を考え直します -- そして、自分で暗号鍵を生成しているのであれば、絶対に全体を考え直すべきです。どんなにプログラミングが得意でも、アマチュアは暗号化コードを書くべきではありません。これにより、数え切れないほど多くのシステム バグが発生しました。
C/C++ では、乱数のようなものは存在せず、疑似乱数にすぎないことを理解していると仮定すると、比較的簡単です。
uint8_t *randomBytes(int length)
{
uint8_t buffer = malloc(length);
for (int i = 0; i < length; i++)
{
buffer[i] = arc4random_uniform(256); // or similar random function
}
return buffer; // don't forget to free buffer when done!
}
Java では、次のようにバイト配列を返します。
byte[] randomBytes(int length)
{
Random rand = new Random();
byte[] buffer = new byte[length];
for (int i = 0; i < length; i++)
{
buffer[i] = (byte) rand.nextInt(256);
}
return buffer;
}
C# では、ほとんど Java と同じですが、いくつかの違いがあります。
byte[] randomBytes(int length)
{
Random rand = new Random();
byte[] buffer = new byte[length];
for (int i = 0; i < length; i++)
{
buffer[i] = (byte) rand.Next(256);
}
return buffer;
}