14

今日、私は次のように考えました: まあ、NIST SP 800-90Aの RDRAND 実装に大きな疑いがあるとしても、それは依然として疑似乱数発生器 (PRNG) のハードウェア実装であり、機密性の低いアプリケーションには十分であるに違いありません。それで、メルセンヌ ツイスターの代わりに自分のゲームで使用することを考えました。

したがって、この命令を使用することでパフォーマンスが向上するかどうかを確認するために、次の 2 つのコードの時間を比較しました。

// test.cpp
#include <cstdio>

int main()
{
    unsigned int rnd = 0;
    for(int i = 0; i < 10000000; ++i) {
        __builtin_ia32_rdrand32_step(&rnd);
    }
    printf("%x\n", rnd);
}

//test2.cpp
#include <cstdio>
#include <random>

int main()
{
    unsigned int rnd = 0;
    __builtin_ia32_rdrand32_step(&rnd);
    std::mt19937 gen(rnd);
    for(int i = 0; i < 10000000; ++i) {
        rnd ^= gen();
    }
    printf("%x\n", rnd);
}

2つを実行すると、次のようになります。

$ time ./test
d230449a

real    0m0.361s
user    0m0.358s
sys     0m0.002s

$ time ./test2 
bfc4e472

real    0m0.051s
user    0m0.050s
sys     0m0.002s

したがって、Mersenne Twister は、私の CPU では RDRAND よりもはるかに高速です。まあ、私はがっかりしました、私のゲームから除外されました. しかし、RDRAND は暗号的に安全な PRNG (CSPRNG) であるため、舞台裏で多くのことを行います...他の CSPRNG と比較すると、より公正になります。そこで、Rabbitの実装 (RFC を C に単純に変換したもので、パフォーマンスのための巧妙なトリックはありません) を使用して、次のテストを作成しました。

// test3.cpp
#include <cstdio>

extern "C"
{
#include "rabbit.h"
}

int main()
{
    rabbit_state s;
    unsigned long long buf[2];
    __builtin_ia32_rdrand64_step(&buf[0]);
    __builtin_ia32_rdrand64_step(&buf[1]);
    rabbit_init_key(&s, (uint8_t*)&buf[0]);

    for(int i = 0; i < 10000000; ++i) {
        rabbit_extract(&s, (uint8_t*)&buf[0]);
    }
    printf("%llx\n", buf[0]);
}

そして驚いたことに、最初の 2 つの疑似乱数データの 2 倍を生成し、RDRAND よりも良い時間を得ることができました。

$ time ./test3 
8ef9772277b70aba

real    0m0.344s
user    0m0.341s
sys     0m0.002s

3 つすべてが、最適化を有効にしてコンパイルされました。

そのため、RDRAND が NSA バックドアをすべてのソフトウェア暗号化に埋め込むために作成されたという偏執狂が広まっています。また、RDRAND よりも高速なソフトウェア CSPRNG が少なくとも 1 つあり、最も広く使用されている適切な PRNG である Mersenne Twister は、RDRAND よりもはるかに高速です。最後に、 RDRAND のように、AES の 2 つのスクランブラー層の背後に隠れていないオープンソースの監査可能なソフトウェア エントロピー プール (/dev/randomや など) があります。/dev/urandom

では、質問: RDRAND を使用する必要がありますか? 合法的な使用法はありますか?それとも、使用を完全に停止する必要がありますか?

4

5 に答える 5

25

他の回答で指摘されているように、RDRAND には真のランダム性がシードされています。特に、ハードウェアで生成された 128 ビットのランダム性を使用して内部 CSPRNG を頻繁に再シードし、511 * 128 ビットごとに少なくとも 1 回の再シードを保証します。このドキュメントのセクション 4.2.5 を参照してください。

https://software.intel.com/en-us/articles/intel-digital-random-number-generator-drng-software-implementation-guide

したがって、あなたの例では、単一の 128 ビット シードを使用して、rabbit_extract から 1,000 万回のランダム ドローを生成しました。RDRAND バージョンでは、250 万回の 128 ビット ドローに相当し、CSPRING が少なくとも 2,500,000/511 = 4,892 回再シードされたことを意味します。

したがって、うさぎの例に入る 128 ビットのエントロピーの代わりに、RDRAND の例に入るエントロピーは少なくとも 4,892*128 = 626,176 ビットでした。

これは、ハードウェア サポートなしで 0.361 秒で得られるよりもはるかに大きなエントロピーです。実際のランダム性が重要な作業を行っている場合、これは問題になる可能性があります。1 つの例は、大量のデータの秘密共有である Shamir です。他にあるかどうかはわかりません。

結論として、これは速度のためではなく、高度なセキュリティのためです。もちろん、それがバックドアであるかどうかという問題は厄介ですが、いつでも他のソースと XOR できるので、少なくとも害はありません。

于 2014-12-06T00:22:29.663 に答える
10

RDRAND単なるPRNGではありません。これは、FIPS 準拠の白色化された TRNG です。RDRAND違いは、CPU から直接取得された実際のエントロピーがかなり多く含まれていることに依存できることです。の主な用途はRDRAND、OS/ライブラリ/アプリケーションにエントロピーを提供することです。

/dev/randomアプリケーションがエントロピーを取得するための他の唯一の良い方法は、通常、またはなどの OS 提供のエントロピー ソースを使用することです/dev/urandom(通常は からエントロピーを引き出します/dev/random)。ただし、その OS では、どこかでエントロピーを見つける必要もあります。通常、これにはディスクとネットワークのアクセス時間のわずかな違いが使用されます (+ その他の半ランダムな入力)。これらのデバイスは常に存在するとは限らず、エントロピーのソースとして設計されていません。多くの場合、それらはあまり良いソースではなく、非常に高速でもありません。そのため、それをサポートするシステムでRDRANDは、オペレーティング システムの暗号的に安全な乱数ジェネレーターのエントロピー ソースとしてよく使用されます。

速度に関しては、特にゲームの場合、(安全でない) PRNG を使用することは完全に有効です。妥当なランダム シードが必要な場合は、結果としてシードすることをお勧めしますがRDRAND、OS 提供の RNG からシードする方が移植性が高く、より安全なオプションである場合もあります (完全に信頼できない場合)。インテルまたは米国)。


現在、RDRAND は、Rabbit などの速度のために作成された (あまり分析されていない) ストリーム暗号ではなく、(AES) CTR_DRBG を使用して実装されていることに注意してください。さらに重要なことは、実行前に CPU 内のエントロピー ソースからエントロピーを取得する必要があることです。

于 2014-11-06T14:30:03.137 に答える