Истощение энтропии std :: random_device - PullRequest
0 голосов
/ 27 декабря 2018

Я использую std::random_device и хотел бы проверить оставшуюся энтропию.Согласно cppreference.com:

std::random_device::entropy

double entropy() const noexcept;

[...]

Возвращаемое значение

Значение энтропии устройства или ноль, если не применимо.

Примечания

Эта функция не полностью реализована в некоторых стандартных библиотеках.Например, LLVM libc ++ всегда возвращает ноль, даже если устройство недетерминировано.Для сравнения, реализация Microsoft Visual C ++ всегда возвращает 32, а boost.random возвращает 10.

Энтропию устройства ядра Linux / dev / urandom можно получить с помощью ioctl RNDGETENTCNT - это то, что std :: random_device ::entropy () в GNU libstdc ++ использует начиная с версии 8.1

Так что под Linux ang g ++> = 8.1, я должен быть хорошим ... но я не:

#include <random>
#include <iostream>

void drain_entropy(std::random_device& rd, std::size_t count = 1)
{
    while (count --> 0) {
        volatile const int discard = rd();
        (void) discard;
    }
}

int main()
{
    std::random_device rd;
    std::cout << "Entropy: " << rd.entropy() << '\n'; // Entropy: 32
    drain_entropy(rd, 1'000'000);
    std::cout << "Entropy: " << rd.entropy() << '\n'; // Entropy: 32
}

Живая демонстрация на Coliru (которая работает под Linux, верно?)

Я ожидаю, что генерация чисел из устройства истощает его энтропию.Но это не так.

Что происходит?

Ответы [ 2 ]

0 голосов
/ 27 декабря 2018

Вы можете увидеть, как .entropy() реализован здесь .

По сути, entropy() вызывает ioctl(fd, RNDGETENTCNT, &ent) и возвращает ent (после ограничения максимального количества битов)в целевом типе по мере необходимости).

Просто так получилось, что он не изменился после вашего drain_entropy вызова.

Вы можете вручную реализовать этот метод и увидеть, что он ведет себя так же,Даже если вы снимите зажим, энтропия практически не пострадает (она может даже увеличиться).

0 голосов
/ 27 декабря 2018

Библиотека не будет возвращать значение энтропии, превышающее число битов в ее типе результата, который в данном случае равен 32.

См. код libstd :

const int max = sizeof(result_type) * __CHAR_BIT__;
if (ent > max)
  ent = max;

Документация, с которой вы связались, объясняет это:

Получает оценку энтропии устройства со случайным числом, которая представляет собой значение с плавающей запятой между 0 и log 2 (max () + 1)(что равно std :: numeric_limits :: digits).

...