【问题标题】:C++ - Extracting random numbers from /dev/urandomC++ - 从 /dev/urandom 中提取随机数
【发布时间】:2016-03-01 15:04:19
【问题描述】:

我需要许多加密安全数字,因此我正在考虑从/dev/urandom 中提取随机性,然后将其“转换”为(例如)unsigned long long int。我想它应该非常有效,而且似乎在密码学上是安全的,但我将来会更多地研究这方面。
现在的问题是:我该怎么做?

我找到了这段代码:

char * block;
short size = 1;
ifstream urandom("/dev/urandom", ios::in|ios::binary);
urandom.read(block,size);
urandom.close();

这有意义吗?以及如何将我得到的内容转换为我想要的类型?

编辑 - 使用 C++11 的random 接口

根据 cmets 的建议,我尝试在整数上使用均匀分布,并将 random_device 初始化为 /dev/urandom。代码如下:

std::uniform_int_distribution<unsigned int> dist(0, modulus-1);
std::random_device urandom("/dev/urandom");
for(unsigned int i = start ; i < end ; ++i)
{
    vector[i] = dist(urandom);
}

问题是这段代码比以前慢了大约 1000 倍(我使用的是 xorshift128+ 生成器):5 毫秒对近 5 秒。这是正常的吗?老实说,我认为从/dev/urandom 流式传输字节并将它们转换为unsigned int 会更快......我错过了什么吗?

【问题讨论】:

  • 如果你真的想要安全号码,你不应该使用/dev/urandom...
  • @SimonKraemer 我明白你的意思,但普遍认为/dev/urandom 的安全性是可以接受的,至少基于我在互联网上所做的研究。无论如何,我稍后会调查这一点。目前我只想让它工作......
  • 有什么理由不信任already available 的随机数生成器?
  • 为什么不使用 C++11 random 接口? en.cppreference.com/w/cpp/numeric/random/random_device/…
  • 您有arc4random() 可用吗?它将返回一个uint32_t,您可以将两个调用或字节的结果组合起来:arc4random_buf()

标签: c++ random


【解决方案1】:

所以你的第一个例子是不正确的,会导致未定义的行为。

char* 块没有指向任何已分配的数据,因此 ifstream::read 实际上会写入未分配的内存。

除此之外,size 的类型是 signed short,而它应该是 size_t

为了阅读unsigned long long int,您可以像这样使用`ifstream':

#include <iostream>
#include <fstream>

int main()
{
    using namespace std;
    unsigned long long int random_value = 0; //Declare value to store data into
    size_t size = sizeof(random_value); //Declare size of data
    ifstream urandom("/dev/urandom", ios::in|ios::binary); //Open stream
    if(urandom) //Check if stream is open
    {
        urandom.read(reinterpret_cast<char*>(&random_value), size); //Read from urandom
        if(urandom) //Check if stream is ok, read succeeded
        {
            std::cout << "Read random value: " << random_value << std::endl;
        }
        else //Read failed
        {
            std::cerr << "Failed to read from /dev/urandom" << std::endl;
        }
        urandom.close(); //close stream
    }
    else //Open failed
    {
        std::cerr << "Failed to open /dev/urandom" << std::endl;
    }
    return 0;
}

有趣的部分是实际使用urandom.read(reinterpret_cast&lt;char*&gt;(&amp;random_value), size); 读取的地方

size 应该是明确的。通过使用sizeof,我们得到了我们想要存储随机值的数据的实际大小(以字节为单位)。这很有用,因为此值在不同的体系结构(例如 32 位和 64 位)上可能不同。
如果您在此处传递的数据类型是指针,请小心。 sizeof 只会返回指针的大小,而不是它所指向的数据的大小。

random_value 的类型为 unsigned long long int。所以&amp;random_value 是相应指针unsigned long long int* 的类型。 但是我们想读取字节(char),因此需要将值从unsigned long long int*更改/转换为char*reinterpret_cast&lt;char*&gt;(&amp;random_value))。

【讨论】:

    猜你喜欢
    • 2017-06-24
    • 1970-01-01
    • 2016-09-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-26
    • 1970-01-01
    • 2021-02-15
    • 1970-01-01
    相关资源
    最近更新 更多