gpt4 book ai didi

Java SecureRandom 围绕创建和重新播种的正确用法

转载 作者:太空宇宙 更新时间:2023-11-04 07:48:53 26 4
gpt4 key购买 nike

我们有一个生成随机临时密码的业务需求。根据用例,此类调用的数量预计非常低(约 400 个调用/天)。根据互联网上的各种建议以及阅读了许多关于 SO 的类似帖子后,我们决定使用 java.security.SecureRandom 来实现加密强随机化。

现在,我们已经编写了一个简单的随机生成器(内部使用 SecureRandom),它应该在 Web 应用程序中用作单例。然而,我们也会定期重新播种它,再次按照 SO 的建议。为此,下面是一些实现相同目的的示例代码。有人可以审查一下并让我们知道这是否是正确且合理有效的方法吗?另外,有没有办法避免代码中的同步,同时仍然保持线程安全?:

import java.security.*;
public final class Randomizer {
private static final Randomizer INSTANCE = new Randomizer();

private static final String DEFAULT_CSPRNG_ALGO = "SHA1PRNG";

private volatile SecureRandom sr;
private volatile long lastSeedTime;

public static final Randomizer getInstance() throws Exception {
return INSTANCE;
}

public int nextInt(int len) throws RuntimeException {
reseedRandomAsNeeded();
return sr.nextInt(len);
}

private Randomizer() throws RuntimeException {
try {
System.out.printf("%s Constructing Randomizer...%n", Thread.currentThread());
recreateSecureRandomInstance();
lastSeedTime = System.nanoTime();
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}

/**
* TODO Is there a way to avoid the synchronization overhead here? We really
* only need to synchronize when the reseed happens.
*
* @throws RuntimeException
*/
private synchronized void reseedRandomAsNeeded() throws RuntimeException {
if (isItTimeToReseed()) {
// TODO Need to do a reseed. Just get a new SecureRandom for now.
try {
recreateSecureRandomInstance();
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
}

private boolean isItTimeToReseed() {
boolean reseed = false;
long currentTime = System.nanoTime();
long difference = ((currentTime - this.lastSeedTime) / (1000 * 1000 * 1000)/* *60 * 60 * 24*/);
// System.out.printf("%s Current time: %d, Last Reseed Time: %d, difference: %d%n",
// Thread.currentThread(), currentTime, lastSeedTime, difference);

// TODO For testing, test for just a 3 seconds difference.
if (difference > 3) {
reseed = true;
this.lastSeedTime = currentTime;
}

return reseed;
}

private void recreateSecureRandomInstance() throws NoSuchAlgorithmException {
sr = SecureRandom.getInstance(DEFAULT_CSPRNG_ALGO);
System.out.printf("%s Created a new SecureRandom instance: %s%n", Thread.currentThread(), sr);
}

}

最佳答案

您可以根据调用次数重新设定种子,而不是基于时间。

在类中维护一个计数器,并在每次调用随机生成器时增加它。当计数器达到某个阈值时,重新播种并将计数初始化为 0。例如,您可以每 100 万次调用重新设定种子。

这是我唯一能建议的。

关于Java SecureRandom 围绕创建和重新播种的正确用法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14838598/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com