当前位置:   article > 正文

应用安全系列之二十八:随机数_那些属于不安全的随机数接口

那些属于不安全的随机数接口

        随机数产生器有两种:非确定性的随机数产生器和确定性的随机数产生器。

        非确定性的随机数产生器(Non-deterministic Random Bit Generators),也称为真随机数产生器,简称NRBG,主要是利用物理熵源的随机数发生器,它的随机性是不可预测的,(熵源是一种产生完全不可预测的无序数据的比特源,而且各比特之间满足统计独立,例如:噪声源、热源、硬盘寻道时间、模数转换过程,等等)。

        确定性的随机数产生器(Deterministic Random Bit Generators)也称为伪随机数产生器,简称DRBG,包括DRBG产生算法和一个熵源的输出作为输入,产生一个依赖于输入的确定的比特序列。目前广泛拥护各个平台和软件的API之中,例如,C、C++的rand、Java的random等,在指定初始种子之后,确定性随机数产生器产生一个确定的比特序列,因此称之为“确定性”。一般都是使用非确定性的随机数产生器产生种子,然后,再使用确定性的随机数产生器产生随机数。

        实际上没有真正的随机性,伪随机数生成器 (PRNG) 近似于随机算法。在实际的编程过程中,大部分使用的都是伪随机数生成器 (PRNG)。PRNG 包括两种类型:统计学的 PRNG 和密码学的 PRNG。统计学的 PRNG 提供很多有用的统计属性,导致输出结果很容易预测,因此产生的随机数随机性就比较差。如果需要生成值不可预测的随机数,这种类型并不适用。密码学的 PRNG 生成的输出结果较难预测,可以很好地解决随机数的随机性问题。

        各种语言都提供了不同的随机数产生接口,建议使用安全版本的随机数产生接口。例如,Java语言中的Math.random()和java.util.Random()是非常不好的伪随机数产生接口,java.security.SecureRandom()基于Linux虚拟文件/dev/urandom产生随机数,是比较安全的随机数产生接口。

例如,如下代码就是不安全的代码:

  1. final static BASE = 100000;
  2. long generateRandomID() throws Exception{
  3. double rand = BASE * Math.random();
  4. while (rand < BASE / 10){
  5. rand = rand * 10;
  6. }
  7. return= Long.parseLong(Double.toString(rand).substring(0, 6));
  8. }

正确的代码如下:

  1. final static BASE = 100000;
  2. static java.security.SecureRandom secureRandom =
  3. new java.security.SecureRandom ();
  4. long generateRandomID() throws Exception{
  5. double rand = BASE * secureRandom.nextDouble();
  6. while (rand < BASE / 10){
  7. rand = rand * 10;
  8. }
  9. return = Long.parseLong(Double.toString(rand).substring(0, 6));
  10. }

       这里需要记住的是:使用SecureRandom 也不一定能够产生安全的随机数,需要注意如果使用不安全的随机数种子,还是会产生不安全的随机数,示例代码如下:

  1. final static BASE = 100000;
  2. static java.security.SecureRandom secureRandom =
  3. new java.security.SecureRandom ();
  4. long generateRandomID() throws Exception{
  5. double rand = BASE * secureRandom.nextDouble();
  6. secureRandom.setSeed(1000);
  7. while (rand < BASE / 10){
  8. rand = rand * 10;
  9. }
  10. return = Long.parseLong(Double.toString(rand).substring(0, 6));
  11. }

        这里的代码调用了setSeed并且传递了一个常数,其实是画蛇添足,反而导致随机数不够随机了,正确的做法就是不要设置种子。

        在实际的使用的时候,需要根据实际需要尽量选择安全的随机数产生器,特别是跟加密相关的地方,一定要使用安全的随机数生成器,否则,可能会影响加密内容的安全性。各种语言的随机数产生器罗列如下表,:

语言不安全的随机数产生器安全的随机数产生器说明
JavaMath.randomjava.security.SecureRandom
java.util.Random
C#System.RandomSystem.Security.Cryptography.RNGCryptoServiceProvider
Crand()randombytes_buf()randombytes_buf是libsodium库提供的
PHPrand()mt_rand()
gmp_random_bits(int $bits): GMPuniqid(string $prefix = "", bool $more_entropy = false): string建议设置more_entropy为true
gmp_random_range()random_bytes(int $length): string
gmp_random(int $limiter = 20): GMPrandom_int(int $min, int $max): int
Pythonrand()os.urandom()
random.randintrandom.SystemRandom
secrets.token_bytes()secrets模块需要Python3.6以及更高的版本
secrets.token_hex()
secrets.SystemRandom
Objective Crand()arc4random() Objective C可以直接使用C的函数
random()arc4random_uniform()
randomize()
Swiftsqlite3_randomness()arc4random() 
drand48()arc4random_buf()
JavaScriptMath.randomwindow.crypto. getRandomValues()
Math.round
Rubyrand()SecureRandom.random_bytes()
SecureRandom.hex()
SecureRandom.uuid()
SecureRandom.base64()
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/413271
推荐阅读
相关标签
  

闽ICP备14008679号