Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/359.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java SecureRandom在创建和重新设定种子时的正确用法_Java_Random_Thread Safety_Singleton - Fatal编程技术网

Java SecureRandom在创建和重新设定种子时的正确用法

Java SecureRandom在创建和重新设定种子时的正确用法,java,random,thread-safety,singleton,Java,Random,Thread Safety,Singleton,我们的业务需要生成随机临时密码。根据用例,此类呼叫的数量预计将非常低(约400个呼叫/天)。我们决定使用java.security.SecureRandom来实现加密的强随机性,这是根据互联网上的各种建议,并且在阅读了许多类似的文章之后 现在,我们已经编写了一个简单的随机化程序(内部使用SecureRandom),它应该在web应用程序中用作单例。然而,我们也会定期地想重新给它播种子,再一次按照关于SO的建议。为此,下面是一些实现相同功能的示例代码。请有人检查一下,让我们知道这是否是正确且合理有

我们的业务需要生成随机临时密码。根据用例,此类呼叫的数量预计将非常低(约400个呼叫/天)。我们决定使用
java.security.SecureRandom
来实现加密的强随机性,这是根据互联网上的各种建议,并且在阅读了许多类似的文章之后

现在,我们已经编写了一个简单的随机化程序(内部使用
SecureRandom
),它应该在web应用程序中用作
单例。然而,我们也会定期地想重新给它播种子,再一次按照关于SO的建议。为此,下面是一些实现相同功能的示例代码。请有人检查一下,让我们知道这是否是正确且合理有效的方法?另外,是否有一种方法可以避免代码中的
同步
,同时仍然保持线程安全性

导入java.security.*;
公共最终类随机化器{
私有静态最终随机发生器实例=新随机发生器();
私有静态最终字符串默认值\u CSPRNG\u ALGO=“SHA1PRNG”;
随机随机随机序列;
私人时间长;
公共静态最终随机化器getInstance()引发异常{
返回实例;
}
public int nextInt(int len)抛出运行时异常{
ReseedRandomasneed();
返回高级nextInt(len);
}
private Randomizer()引发RuntimeException{
试一试{
System.out.printf(“%s正在构造随机化器…%n”,Thread.currentThread());
重新创建SecureRandomInstance();
lastSeedTime=System.nanoTime();
}捕获(无算法异常){
抛出新的运行时异常(e);
}
}
/**
*TODO这里有没有避免同步开销的方法?我们真的
*只需要在重新设定种子时进行同步。
* 
*@抛出运行时异常
*/
private synchronized void reseederandomasneeded()引发RuntimeException{
如果(isItTimeToReseed()){
//TODO需要重新设定种子。现在只需获取一个新的SecureRandom。
试一试{
重新创建SecureRandomInstance();
}捕获(无算法异常){
抛出新的运行时异常(e);
}
}
}
私有布尔值isItTimeToReseed(){
布尔重设种子=假;
长currentTime=System.nanoTime();
长差=((currentTime-this.lastSeedTime)/(1000*1000*1000)/**60*60*24*/);
//System.out.printf(“%s当前时间:%d,上次重新设定种子时间:%d,差异:%d%n”,
//currentThread(),currentTime,lastSeedTime,差);
//测试的TODO,测试3秒的差异。
如果(差异>3){
重新设定种子=真;
this.lastSeedTime=当前时间;
}
返回重新设定种子;
}
private void recreateSecureRandomInstance()抛出NoSuchAlgorithmException{
sr=SecureRandom.getInstance(默认值为\u CSPRNG\u ALGO);
System.out.printf(“%s创建了一个新的SecureRandom实例:%s%n”,Thread.currentThread(),sr);
}
}

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

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


这是我唯一的建议。

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

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


这是我唯一能建议的。

关于同步位,您可能可以使用原子布尔值(或者一个带有一个许可证的信号量)。类似于
boolean reseed=isItTimeToReseed();如果(reseed&&atomicBoolean.compareAndSet(false,true)){recreate();atomicBoolean.set(false);}
-这可能会起作用,因为您的变量是可变的,所以可见性在这里不是一个问题。关于同步位,您可能会改用atomicBoolean(或具有一个许可证的信号量)。类似于
boolean reseed=isItTimeToReseed();如果(reseed&&atomicBoolean.compareAndSet(false,true)){recreate();atomicBoolean.set(false);}
-这可能有效,因为您的变量是易变的,所以可见性在这里不是问题。