随机数安全
2016-07-01 本文已影响406人
WilsonMing
- apk被拉去阿里云检查,出来高危漏洞
使用SecureRandom时不要使用SecureRandom (byte[] seed)这个构造函数,会造成生成的随机数不随机。
建议通过/dev/urandom或者/dev/random获取的熵值来初始化伪随机数生成器PRNG高危
看到这个就想研究下随机数。
- 分类
- 真随机数,通过物理实验得出,比如掷钱币、骰子、转轮、使用电子元件的噪音、核裂变等
- 伪随机数,通过一定算法和种子得出。软件实现的是伪随机数
- 强伪随机数,难以预测的随机数
- 弱伪随机数,易于预测的随机数
- 结果对比
-
真随机数
RANDOM.ORG
-
真随机数
-
伪随机数
PHP rand() on Microsoft Windows
- Java产生随机数方法
- Math.random(),伪随机数
- java.util.Random 伪随机数(线性同余法生成)
- java.security.SecureRandom 真随机数
- 示例代码
package remdo;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.security.SecureRandom;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;
/**
* 测试1-100内的随机数,
*
* @author Wilson
*
*/
public class RamdonTest {
public static List<Integer> getMath(int bound) {
List<Integer> list=new ArrayList<>();
if (bound > 1) {
for (int i = 0; i < bound; i++) {
int mathInt = (int) Math.random() * bound;
list.add(mathInt);
}
}
return list;
}
public static List<Integer> getRandom(int bound) {
List<Integer> list=new ArrayList<>();
if (bound > 1) {
Random random = new Random();
for (int i = 0; i < bound; i++) {
int mathRandom = random.nextInt(bound);
list.add(mathRandom);
}
}
return list;
}
public static List<Integer> getSecureRandom(int bound) {
List<Integer> list=new ArrayList<>();
if (bound > 1) {
SecureRandom secureRandom = new SecureRandom();
for (int i = 0; i < bound; i++) {
//推荐
int mathRandom = secureRandom.nextInt(bound);
list.add(mathRandom);
}
}
return list;
}
public static void printTotal(List<Integer> list) {
Map<Integer, Integer> map = new HashMap<>();
for (Integer integer : list) {
int count=1;
if (map.containsKey(integer)) {
count=map.get(integer)+1;
}
map.put(integer, count);//插入新的数据
}
//遍历hashmap,遍历方式较list要麻烦一点,谁叫他功能更丰富
Iterator<Entry<Integer, Integer>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
Entry<Integer, Integer> entry = (Entry<Integer, Integer>) iterator.next();
System.out.println("随机数:" + entry.getKey() + ",被随机中的次数:" + entry.getValue() + "次");
}
}
public static void test() {
Random r = new Random(); //5000作为seed,默认使用当前时间作为seed
//固定种子,可是产生随机数是固定的,
r.setSeed(5000);
for (int i=0;i<5;++i)
{
System.out.println(+r.nextInt()*500);
}
}
public static void testSCR() {
SecureRandom r = new SecureRandom(); //5000作为seed,默认使用当前时间作为seed
//固定种子,可是产生的随机数是随机的
r.setSeed(5000);
for (int i=0;i<5;++i)
{
System.out.println(r.nextInt());
}
}
public static void main(String[] args) {
// RamdonTest.printTotal(RamdonTest.getMath(100));
// RamdonTest.printTotal(RamdonTest.getRandom(100));
// RamdonTest.printTotal(RamdonTest.getRandom(100));
// RamdonTest.printTotal(RamdonTest.getSecureRandom(1000));
// RamdonTest.test();
RamdonTest.testSCR();
//Random和SecureRandom对比,只要知道Random的种子就能预测到随机数结果,具体可对比test()和testSCR()产生随机数
}
}