Intel Secure Key (RDRAND) возможно странное поведение - PullRequest
0 голосов
/ 11 ноября 2018

Я уже некоторое время использую предоставляемую Intel функцию RNG, чтобы обеспечить себя случайностью с помощью написанной мной программы на C ++ / CLI.

Однако через некоторое время что-то поразиломне как то особенно подозрительно.Среди прочего я прошу случайное число от 1 до 4 и каждый раз записываю результат на бумаге.Вот результаты:

2, 3, 3, 2, 1, 3, 4, 2, 3, 2, 3, 1, 3, 2, 3, 1, 2, 4, 2, 2, 1, 2, 1, 3, 1, 3, 3, 3, 3.

Количество 1с: 6 Количество 2с: 9 Количество 3с: 12 Количество 4с: 2 Всего: 29

Мне действительно интересно, есть ли проблема с RNG от Intel, моим алгоритмом, методологией или чем-то еще?Или вы считаете, что смещение пока недостаточно велико?

Я использую Windows 10 Pro, мой процессор - Intel Core i7-4710MQ.Скомпилировано с VS2017.

Методология:

  1. Запустите командную строку Powershell
  2. Загрузите мою сборку с помощью Add-Type -Path <mydll>
  3. Invoke [rdrw.Random]::Next(4)
  4. Добавьте один к результату

Подробности, которые могут иметь значение: я не очень часто спрашиваю об этом числе, так что между розыгрышами проходит некоторое время, и обычно это происходит, когдаRNG не использовался в течение некоторого времени (по крайней мере, один час).

И да, это ленивый алгоритм, я не хотел беспокоить себя исключениями.

Алгоритм следующий:

#include <immintrin.h>

namespace rdrw {

#pragma managed(push,off)
    unsigned long long getRdRand() {
        unsigned long long val = 0;

        while (!_rdrand64_step(&val));
        return val;
    }
#pragma managed(pop)

    public ref class Random abstract sealed
    {
    public:
        // Returns a random 64 bit unsigned integer
        static unsigned long long Next() {
            return getRdRand();
        }

        // Return a random unsigned integer between 0 and max-1 (inclusive)
        static unsigned long long Next(unsigned long long max) {
            unsigned long long nb = max - 1;
            unsigned long long mask = 1;
            unsigned long long draw = 0;

            if (max <= 1)
                return 0;

            // Create a bitmask that's at least as big as the biggest acceptable value
            while ((nb&mask) != nb)
            {
                mask <<= 1;
                mask |= 1;
            }

            do
            {
                // Throw unnecessary bits
                draw = Next() & mask;
            } while (draw>nb);
            return draw;
        }

        // return a random unsigned integer between min and max-1 inclusive
        static unsigned long long Next(unsigned long long min, unsigned long long max) {

            if (max == min)
                return min;
            if (max < min)
                return 0;
            unsigned long long diff = max - min;
            return Next(diff) + min;
        }
    };
}

Спасибо за ваши идеи!

...