栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

缓慢的SecureRandom初始化

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

缓慢的SecureRandom初始化

(注意:另请参阅本答案末尾的最新更新)

说明

原因是默认

SecureRandom
提供程序。

在Windows上,有2个

SecureRandom
提供程序可用:

- provider=SUN, type=SecureRandom, algorithm=SHA1PRNG- provider=SunMSCAPI, type=SecureRandom, algorithm=Windows-PRNG

在Linux上(在Alpine docker中使用Oracle JDK 8u162进行了测试):

- provider=SUN, type=SecureRandom, algorithm=NativePRNG- provider=SUN, type=SecureRandom, algorithm=SHA1PRNG- provider=SUN, type=SecureRandom, algorithm=NativePRNGBlocking- provider=SUN, type=SecureRandom, algorithm=NativePRNGNonBlocking

这些在

jre/lib/security/java.security
文件中指定。

security.provider.1=sun.security.provider.Sun...security.provider.10=sun.security.mscapi.SunMSCAPI

默认情况下,使用第一个

SecureRandom
提供程序。在Windows上,默认值是
sun.security.provider.Sun
,当使用JVM运行JVM时,此实现报告如下
-Djava.security.debug="provider,engine=SecureRandom"

Provider: SecureRandom.SHA1PRNG algorithm from: SUNprovider: Failed to use operating system seed generator: java.io.IOException: Required native CryptoAPI features not  available on this machineprovider: Using default threaded seed generator

而且默认的线程种子生成器非常慢。

您需要使用

SunMSCAPI
提供程序。

解决方案1:配置

重新配置供应商:

编辑

jre/lib/security/java.security

security.provider.1=sun.security.mscapi.SunMSCAPI...security.provider.10=sun.security.provider.Sun

我不知道这可以通过系统属性来完成。

也许是的,使用

-Djava.security.properties
(未经测试,请参阅此)

解决方案2:程序化

以编程方式重新排序提供者:

Optional.ofNullable(Security.getProvider("SunMSCAPI")).ifPresent(p->{    Security.removeProvider(p.getName());    Security.insertProviderAt(p, 1);});

JVM现在报告以下(

-Djava.security.debug="provider,engine=SecureRandom"
):

Provider: SecureRandom.Windows-PRNG algorithm from: SunMSCAPI

解决方案3:编程v2

受此想法的启发,以下代码仅插入了一个

SecureRandom
服务,该服务是从现有
SunMSCAPI
提供程序动态配置的,而无需明确依赖
sun.*
类。这也避免了与提供
SunMSCAPI
者所有服务的不分优先次序相关的潜在风险。

public interface WindowsPRNG {    static void init() {        String provider = "SunMSCAPI"; // original provider        String type = "SecureRandom"; // service type        String alg = "Windows-PRNG"; // algorithm        String name = String.format("%s.%s", provider, type); // our provider name        if (Security.getProvider(name) != null) return; // already registered        Optional.ofNullable(Security.getProvider(provider)) // only on Windows     .ifPresent(p-> Optional.ofNullable(p.getService(type, alg)) // should exist but who knows?  .ifPresent(svc-> Security.insertProviderAt( // insert our provider with single SecureRandom service          new Provider(name, p.getVersion(), null) {{   setProperty(String.format("%s.%s", type, alg), svc.getClassName());          }}, 1)));    }}

性能

<140 msec
(而不是
5000+ msec

细节

使用时有一个调用到

new SecureRandom()
调用堆栈中的某个地方
URL.openConnection("https://...")

它调用

getPrngAlgorithm()
(请参阅SecureRandom:880)

这将返回

SecureRandom
它找到的第一个提供程序。

出于测试目的,

URL.openConnection()
可以使用以下命令代替to :

new SecureRandom().generateSeed(20);

免责声明

我不知道由提供商重新订购引起的任何负面影响。但是,可能会有一些,特别是考虑默认提供者选择算法。

无论如何,至少从理论上讲,从功能的角度来看,这对于应用程序应该是透明的。

更新2019-01-08

Windows 10(版本1803):无法再在任何最新的JDK上重现此问题(已从旧oracle 1.7.0_72到openjdk“ 12-ea”
2019-03-19进行了全部测试)。

看来这是Windows问题,已在最新的操作系统更新中修复。相关更新可能在最近的JRE版本中也可能没有发生。但是,即使使用我最旧的JDK 7 update72安装程序,也绝对无法受影响,并且绝对未进行任何修补,但我无法重现原始问题。

使用此解决方案时,性能仍然会有少量提升(平均大约为350毫秒),但是默认行为不再遭受无法忍受的5秒以上的惩罚。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/435220.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号