2

我有一个用户案例,其中涉及生成一个用户输入网站以将交易链接到他们的帐户的数字。

所以我有以下代码生成一个随机的 12 位数字:

public String getRedemptionCode(long utid, long userId) {       
    long nano = System.nanoTime();      
    long temp = nano + utid + 1232;
    long redemptionCode = temp + userId + 5465;     
    if (redemptionCode < 0) {
        redemptionCode = Math.abs(redemptionCode);
    }       
    String redemptionCodeFinal = StringUtils.rightPad(String.valueOf(redemptionCode), 12, '1');
    redemptionCodeFinal = redemptionCodeFinal.substring(0, 12);
    return redemptionCodeFinal;
}

此方法接受由数据库生成的两个参数。

我需要了解的是:

  1. 这是随机的吗?我有一个测试该方法运行了 100 万次,而且它似乎总是随机的。

  2. 我可以将其减少到 8 个字符吗?

4

2 回答 2

3

不,它既不是唯一的,也不是随机的。

在高度熵/与其他值不相关的意义上,它不是“随机的”。

不确定性的唯一来源是System.nanoTime,因此所有熵都来自系统时钟的几个最低有效位。简单地添加类似1232和的数字5465不会使结果与后续结果的相关性降低。


这是随机的吗?我有一个测试该方法运行了 100 万次,而且它似乎总是随机的。

如果此代码在同一台机器上的多个线程中使用,或者在具有同步时钟的多台机器上使用,您将更快地看到重复。

由于熵低,您可能会很快随机看到重复项。 Math.se根据您生成的数量来解决可能性。


我可以将其减少到 8 个字符吗?

只有当你不失去熵。考虑两种截断时间戳的方法:

long time = ...;   // Least significant bits have randomness.
String s = "" + time;
// Cut off the right-most, most entropic bits
String bad = time.substring(0, 8);
// Cut off the left-most, least entropic bits
String better = time.substring(time.length() - 8);

由于这是从递增计数器进行的直接计算,因此可以多次尝试的攻击者可以预测所产生的值,而如果您使用java.util.SecureRandom.

于 2013-10-08T15:44:38.427 回答
2

这是随机的吗?

您在问,您的函数是否基于System.nanoTime()随机数生成器 ( RNG )?

RNG的定义是:生成器,生成没有任何模式的数字。

那么,您的函数返回的数字是否没有任何模式?

不,它们具有易于观察的模式,因为它们依赖于System.nanoTime()系统时钟)。

我可以将其减少到 8 个字符吗?

是的,你可以,但它仍然不是随机的。添加或填充也无济于事。

改为使用SecureRandom

于 2013-10-08T15:47:58.510 回答