随机数安全

  • 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 getMath(int bound) {
        List 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 getRandom(int bound) {
        List 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 getSecureRandom(int bound) {
        List 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 list) {
        Map 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> iterator = map.entrySet().iterator();  
        while (iterator.hasNext()) {  
            Entry entry = (Entry) 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()产生随机数
    }
}

  • 参考资料
    • 随机数安全
    • 伪随机数的安全

你可能感兴趣的:(随机数安全)