我有一个用户案例,涉及生成用户输入网站以将交易链接到其帐户的号码。
所以我有以下代码生成一个随机的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;
}
此方法接受由DB生成的两个参数。
我需要了解的是:
这是随机的吗?我有一个测试,它运行这个方法100万次,它似乎总是随机的。
我可以将其减少到8个字符吗?
答案 0 :(得分: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);
由于这是一个来自增加计数器的简单计算,一个可以多次尝试的攻击者可以预测所产生的价值,使他们无法使用crypto-strong random number generator之类的java.util.SecureRandom
{{1}} }。
答案 1 :(得分:2)
这是随机的吗?
您问,您的功能是基于System.nanoTime()
随机数生成器(RNG)吗?
RNG的定义是:generator,它生成缺少任何模式的数字。
那么,你的函数返回的数字是否没有任何模式?
不,他们有一个易于观察的模式,因为它们依赖于System.nanoTime()
(system clock)。
我可以将其减少到8个字符吗?
是的,你可以,但它仍然不是随机的。添加或填充也无济于事。
改为使用SecureRandom
。