如何在 C 中使用 /dev/random 或 urandom?

2024-10-29 08:35:00
admin
原创
196
摘要:问题描述:我想在 C 中使用/dev/random或/dev/urandom。我该怎么做?我不知道如何在 C 中处理它们,如果有人知道请告诉我怎么做。谢谢。解决方案 1:一般来说,最好避免打开文件来获取随机数据,因为该过程中存在许多故障点。在最近的 Linux 发行版中,getrandom系统调用可用于获取加...

问题描述:

我想在 C 中使用/dev/random/dev/urandom。我该怎么做?我不知道如何在 C 中处理它们,如果有人知道请告诉我怎么做。谢谢。


解决方案 1:

一般来说,最好避免打开文件来获取随机数据,因为该过程中存在许多故障点。

在最近的 Linux 发行版中,getrandom系统调用可用于获取加密安全随机数,如果 GRND_RANDOM没有指定为标志并且读取量最多为 256 字节,则它不会失败。

截至 2017 年 10 月,OpenBSD、Darwin 和 Linux(带有-lbsd)现在都已实现arc4random加密安全且不会失败的。这使其成为一个非常有吸引力的选择:

char myRandomData[50];
arc4random_buf(myRandomData, sizeof myRandomData); // done!

否则,你可以将随机设备当作文件来使用。你从中读取数据,然后获得随机数据。我在这里使用open/ read,但fopen/fread也同样有效。

int randomData = open("/dev/urandom", O_RDONLY);
if (randomData < 0)
{
    // something went wrong
}
else
{
    char myRandomData[50];
    ssize_t result = read(randomData, myRandomData, sizeof myRandomData);
    if (result < 0)
    {
        // something went wrong
    }
}

在关闭文件描述符之前,您可以读取更多随机字节。/dev/urandom 永远不会阻塞,并且始终会填充您请求的字节数,除非系统调用被信号中断。它被认为是加密安全的,应该是您的首选随机设备。

/dev/random 更加挑剔。在大多数平台上,它返回的字节数可能比您要求的要少,并且如果没有足够的字节可用,它可能会阻塞。这使得错误处理过程更加复杂:

int randomData = open("/dev/random", O_RDONLY);
if (randomData < 0)
{
    // something went wrong
}
else
{
    char myRandomData[50];
    size_t randomDataLen = 0;
    while (randomDataLen < sizeof myRandomData)
    {
        ssize_t result = read(randomData, myRandomData + randomDataLen, (sizeof myRandomData) - randomDataLen);
        if (result < 0)
        {
            // something went wrong
        }
        randomDataLen += result;
    }
    close(randomData);
}

解决方案 2:

上面还有其他准确的答案。FILE*不过,我需要使用流。以下是我所做的...

int byte_count = 64;
char data[64];
FILE *fp;
fp = fopen("/dev/urandom", "r");
fread(&data, 1, byte_count, fp);
fclose(fp);

解决方案 3:

只需打开文件进行读取,然后读取数据即可。在 C++11 中,您可能希望使用std::random_device提供对此类设备的跨平台访问。

解决方案 4:

Zneak 100% 正确。读取比启动时所需的随机数略大的随机数缓冲区也很常见。然后,您可以填充内存中的数组,或将它们写入您自己的文件以供以后重复使用。

上述内容的典型实现:

typedef struct prandom {
     struct prandom *prev;
     int64_t number;
     struct prandom *next;
} prandom_t;

这或多或少就像一盘磁带,可以随时向前移动,需要时可以神奇地用另一根线补充。有很多服务提供大型文件转储,其中只包含使用更强大的生成器生成的随机数,例如:

  • 放射性衰变

  • 光学行为(光子撞击半透明镜子)

  • 大气噪声(不如上述噪声强烈)

  • 一群醉醺醺的猴子在键盘上打字,移动老鼠(开玩笑)

不要使用“预打包”的熵作为加密种子,以防万一。这些集合对于模拟来说很好,但对于生成密钥等来说则完全不行。

不关心质量,如果您需要大量数字来进行蒙特卡罗模拟之类的操作,最好以不会导致 read() 阻塞的方式提供它们。

但是,请记住,数字的随机性与生成数字所涉及的复杂性一样具有确定性。/dev/random/dev/urandom很方便,但不如使用 HRNG(或从 HRNG 下载大量转储)那么强大。 还值得注意的是,/dev/random 通过熵进行重新填充,因此根据情况,它可能会阻塞相当长一段时间。

解决方案 5:

zneak 的回答很简单,但实际情况比这更复杂。例如,您需要首先考虑 /dev/{u}random 是否真的是随机数设备。如果您的机器已被入侵并且设备被替换为指向 /dev/zero 或稀疏文件的符号链接,则可能会发生这种情况。如果发生这种情况,随机流现在完全可以预测。

最简单的方法(至少在 Linux 和 FreeBSD 上)是在设备上执行 ioctl 调用,只有当设备是随机生成器时该调用才会成功:

int data;
int result = ioctl(fd, RNDGETENTCNT, &data); 
// Upon success data now contains amount of entropy available in bits

如果这是在第一次读取随机设备之前执行的,那么你很有可能已经获得了随机设备。因此@zneak 的答案可以更好地扩展为:

int randomData = open("/dev/random", O_RDONLY);
int entropy;
int result = ioctl(randomData, RNDGETENTCNT, &entropy);

if (!result) {
   // Error - /dev/random isn't actually a random device
   return;
}

if (entropy < sizeof(int) * 8) {
    // Error - there's not enough bits of entropy in the random device to fill the buffer
    return;
}

int myRandomInteger;
size_t randomDataLen = 0;
while (randomDataLen < sizeof myRandomInteger)
{
    ssize_t result = read(randomData, ((char*)&myRandomInteger) + randomDataLen, (sizeof myRandomInteger) - randomDataLen);
    if (result < 0)
    {
        // error, unable to read /dev/random 
    }
    randomDataLen += result;
}
close(randomData);

不久前,Insane Coding 博客介绍了这个问题和其他陷阱;我强烈建议阅读整篇文章。我必须赞扬他们提出的解决方案。

编辑以添加(2014-07-25)...

巧合的是,我昨晚读到,作为LibReSSL 努力的一部分,Linux 似乎正在获得GetRandom()系统调用。截至撰写本文时,尚无消息表明它何时会在内核通用版本中可用。然而,这将是获取加密安全随机数据的首选接口,因为它消除了通过文件访问带来的所有陷阱。另请参阅 LibReSSL可能的实现。

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用