【问题标题】:Generating random sequences of bits生成随机位序列
【发布时间】:2012-04-04 22:49:32
【问题描述】:

我正在尝试生成一个包含具有给定长度的绝对随机密钥的文件,比如说 100 位并将它们存储在一个文件中。最好的方法是什么?哪种语言提供最好的库?提前致谢。

【问题讨论】:

  • 计算机上没有什么是绝对随机的。只是看起来如此。
  • @PortableWorld:你错了。完全有可能获得所需的任何熵级别的计算机生成随机位。
  • 不,他是对的。计算机是确定性设备。您可能会使用磁盘驱动器等外围设备来生成熵,但即使这样也很可疑。当然,真正的 HRNG 是个例外。
  • @PortableWorld:它们可能不是绝对随机的,但你可以让它们绝对不可预测,我听说有些人使用他们的温度计作为熵的来源,因为他们现在已经内置了这些。
  • 投反对票?是否有人希望他的答案是唯一的非否定投票?

标签: c# java c++ c random


【解决方案1】:

随机性来自不同级别的“强度”;你可以得到 true 随机位或 pseudo 随机位。真正的随机位从现实世界的来源中获得熵。 随机位产生一个看似随机但实际上是可预测的位序列。

在生成密钥时,您应该始终使用指定为具有加密强度的随机生成器。这些随机位生成器经过精心设计,真正不可预测。切勿使用较弱的随机源来生成密钥。

在 C# 中,您可以通过创建一个恰当命名的 random number generator cryptographic service provider 的实例,然后调用 GetBytes 来获取所需长度的随机字节数组。

不用说:生成自己的加密密钥时要非常小心。密码学就​​是将密钥的安全性用于消息的安全性;如果您对如何生成、存储和传输密钥不太小心,那么安全系统就会受到威胁。如果您自己不是密码学专家,请考虑聘请密码学专家,而不是尝试推出自己的密码代码。

我还注意到,根据您的应用程序,100 位可能太小或太大。它可能太小,因为您的算法可能容易受到如此小的密钥大小的攻击,并且它可能太大,因为某些国家限制使用或出口具有过多位数的加密软件。考虑咨询律师。

【讨论】:

    【解决方案2】:

    取决于您所说的绝对随机是什么意思。如果可以接受伪随机数生成器,那么 C++ <random> 库是一个不错的选择。

    如果您需要比这更强大的保证,那么您仍然可以使用来自<random>std::random_device,如果您的平台具有该功能,它会提供非确定性随机数。它甚至可以提供对加密随机数生成器的访问。您必须检查平台的文档。

    #include <random>
    #include <iostream>
    
    int main() {
        std::random_device r("/dev/random"); // Cryptographically secure RNG on Linux, OpenBSD, OSX, (using libc++)
        unsigned int completely_random_value = r();
        std::cout << completely_random_value << '\n';
    }
    

    可能与您相关的一件事是 Microsoft 文档中关于他们在 VS11 中实现 random_device 的注释:“在此实现中,默认生成的值不是不确定的。”这是 Visual Studio 的 C++11 库的另一个不幸的实现质量问题(至少伴随着他们的 chrono::high_resolution_clock 的低分辨率)

    【讨论】:

      【解决方案3】:

      真正的随机数不能由确定性过程生成,因此语言的选择在某种意义上并不重要。既然您说“密钥”,那么您可能正在寻找加密密钥,而通过确定性过程生成这些密钥确实非常危险,并且会导致无数系统中断。

      我会重新考虑整个事情——如果您自己生成加密密钥,那么您绝对应该重新考虑整个事情。业余爱好者,无论编程多么熟练,都不应该编写密码代码。这导致的系统错误数不胜数。

      【讨论】:

      • @Perry:计算机无法生成真正的随机数,但它们可以生成不确定的数字。
      • 您可以通过什么方式使用纯确定性硬件创建“非确定性”数字?
      • @Perry:你在拖钓。所述确定性硬件可以从非确定性源获取输入。现在放弃吧。
      • 这个“非确定性来源”在普通计算机上是什么?像 Ted T'so 的 /dev/random 这样的东西在黑魔法中几乎没有可敬的一面。我不是“拖钓”——我是一名领域专家,而且这里几乎没有其他人是。人们弄错 RNG 的次数令人吃惊——最近几个月的一个很好的例子,请参阅eprint.iacr.org/2012/064.pdf——你们似乎都不明白自己在说什么,然而,我们有人们向进行密钥生成的人提供非常糟糕的建议。
      • 引用约翰·冯·诺依曼的话:“任何考虑用算术方法产生随机数字的人,当然都处于一种罪恶状态。”
      【解决方案4】:

      在 C/C++ 中相对容易,假设您了解没有随机数之类的东西,而只是伪随机数:

      uint8_t *randomBytes(int length)
      {
          uint8_t buffer = malloc(length);
      
          for (int i = 0; i < length; i++)
          {
              buffer[i] = arc4random_uniform(256); // or similar random function
          }
      
          return buffer; // don't forget to free buffer when done!
      }
      

      在 Java 中,您将返回一个字节数组,如下所示:

      byte[] randomBytes(int length)
      {
          Random rand = new Random();
          byte[] buffer = new byte[length];
      
          for (int i = 0; i < length; i++)
          { 
              buffer[i] = (byte) rand.nextInt(256);
          }
      
          return buffer;
      }
      

      在 C# 中,它与 Java 基本相同,但有一些不同:

      byte[] randomBytes(int length)
      {
          Random rand = new Random();
          byte[] buffer = new byte[length];
      
          for (int i = 0; i < length; i++)
          { 
              buffer[i] = (byte) rand.Next(256);
          }
      
          return buffer;
      }
      

      【讨论】:

      • 那些甚至不是加密强度 PRNG。
      • @CodeInChaos 我早在密码学问题出现之前就回答了,所以请删除你的反对票。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-09
      • 2012-12-29
      • 1970-01-01
      • 1970-01-01
      • 2012-01-20
      • 2013-08-13
      相关资源
      最近更新 更多