有人说使用Random作为token的随机数生成器会产生安全问题,为什么说Random不安全?
因为如果可以得到Random对象产生的两个连续随机数,就可以预测该Random对象下一个将要生成的随机数。下面是通过Random产生的两个连续int随机值,来预测下一个int随机值的代码。
1public static void main(String[] args) {
2 Random random = new Random();
3 int r1 = random.nextInt();
4 int r2 = random.nextInt();
5 long seed = getPreviousSeed(r1, r2);
6 int nextInt = nextInt(seed);
7 System.out.println(random.nextInt() + ", " + nextInt);
8}
9
10private static final long multiplier = 0x5DEECE66DL;
11private static final long addend = 0xBL;
12private static final long mask = (1L << 48) - 1;
13
14public static int nextInt(long seed) {
15 return (int) (((seed * multiplier + addend) & mask) >>> 16);
16}
17
18public static long getPreviousSeed(int r1, int r2) {
19 long oldSeed = ((long) r1 << 16);
20 for (int i = 0; i < (2 << 16); i++) {
21 long nextSeed = (oldSeed * multiplier + addend) & mask;
22 if ((int) (nextSeed >>> 16) == r2) {
23 return nextSeed;
24 }
25 oldSeed++;
26 }
27 throw new RuntimeException("Not found");
28}
输出结果如下
-1278875695, -1278875695
每个人输出结果不同,但是两个值应该是相等的,在对安全性要求比较高的业务场景应该使用SecureRandom来替代Random。更多详细的内容可以参考随机数生成器Random的安全性问题。
内容