赞
踩
随机数产生器有两种:非确定性的随机数产生器和确定性的随机数产生器。
非确定性的随机数产生器(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产生随机数,是比较安全的随机数产生接口。
例如,如下代码就是不安全的代码:
- final static BASE = 100000;
-
-
-
- long generateRandomID() throws Exception{
-
- double rand = BASE * Math.random();
-
- while (rand < BASE / 10){
-
- rand = rand * 10;
-
- }
-
-
-
- return= Long.parseLong(Double.toString(rand).substring(0, 6));
-
- }
正确的代码如下:
- final static BASE = 100000;
-
- static java.security.SecureRandom secureRandom =
-
- new java.security.SecureRandom ();
-
-
-
- long generateRandomID() throws Exception{
-
- double rand = BASE * secureRandom.nextDouble();
-
- while (rand < BASE / 10){
-
- rand = rand * 10;
-
- }
-
-
-
- return = Long.parseLong(Double.toString(rand).substring(0, 6));
-
- }
这里需要记住的是:使用SecureRandom 也不一定能够产生安全的随机数,需要注意如果使用不安全的随机数种子,还是会产生不安全的随机数,示例代码如下:
- final static BASE = 100000;
-
- static java.security.SecureRandom secureRandom =
-
- new java.security.SecureRandom ();
-
-
-
- long generateRandomID() throws Exception{
-
- double rand = BASE * secureRandom.nextDouble();
- secureRandom.setSeed(1000);
-
- while (rand < BASE / 10){
-
- rand = rand * 10;
-
- }
-
-
-
- return = Long.parseLong(Double.toString(rand).substring(0, 6));
-
- }
这里的代码调用了setSeed并且传递了一个常数,其实是画蛇添足,反而导致随机数不够随机了,正确的做法就是不要设置种子。
在实际的使用的时候,需要根据实际需要尽量选择安全的随机数产生器,特别是跟加密相关的地方,一定要使用安全的随机数生成器,否则,可能会影响加密内容的安全性。各种语言的随机数产生器罗列如下表,:
语言 | 不安全的随机数产生器 | 安全的随机数产生器 | 说明 |
Java | Math.random | java.security.SecureRandom | |
java.util.Random | |||
C# | System.Random | System.Security.Cryptography.RNGCryptoServiceProvider | |
C | rand() | randombytes_buf() | randombytes_buf是libsodium库提供的 |
PHP | rand() | mt_rand() | |
gmp_random_bits(int $bits): GMP | uniqid(string $prefix = "", bool $more_entropy = false): string | 建议设置more_entropy为true | |
gmp_random_range() | random_bytes(int $length): string | ||
gmp_random(int $limiter = 20): GMP | random_int(int $min, int $max): int | ||
Python | rand() | os.urandom() | |
random.randint | random.SystemRandom | ||
secrets.token_bytes() | secrets模块需要Python3.6以及更高的版本 | ||
secrets.token_hex() | |||
secrets.SystemRandom | |||
Objective C | rand() | arc4random() | Objective C可以直接使用C的函数 |
random() | arc4random_uniform() | ||
randomize() | |||
Swift | sqlite3_randomness() | arc4random() | |
drand48() | arc4random_buf() | ||
JavaScript | Math.random | window.crypto. getRandomValues() | |
Math.round | |||
Ruby | rand() | SecureRandom.random_bytes() | |
SecureRandom.hex() | |||
SecureRandom.uuid() | |||
SecureRandom.base64() |
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。