赞
踩
Java 8的SecureRandom API对原有的有几个变化
根据Oracle,已经做出了以下有趣的变化:
我们来看看这些变化,看看它们对应用程序的意义。请注意,这些详细信息仅适用于与SUN和SunMSCAPI Java加密扩展提供程序一起分发的Oracle JDK / JRE。
NativePRNG在Solaris / Linux / MacOS上的行为是sun.security.provider.NativePRNG.generateSeed()可能会阻塞,因为它使用/ dev / random,但是使用nextBytes(),nextLong()等获取输出将永远不会因为他们使用/ dev / urandom(这对于默认环境设置是正确的)。NativePRNG仍然是这样的,但现在有两个额外的实现:
在系统收集更多熵时,您不希望应用程序阻止的任何应用程序中,NativePRNGBlocking将会遇到问题。从它获取任何类型的输出可能会导致应用程序的线程挂起。在桌面应用程序中用于生成本地加密密钥(例如)是很好的,但在Web应用程序中几乎不可行。
请注意,NativePRNGBlocking在其熵使用方面可能会有些浪费。出于性能原因,它将从/ dev / random 一次读取nextBytes(),nextInt()等)的32字节数据。在100毫秒内未被使用的任何数据将被丢弃。因此,对nextBoolean()的每次调用都会给出一位输出,但是实现可能实际上会使用256位的熵来(并且大部分丢弃)。
此方法使用java.security文件中的securerandom.strongAlgorithms属性来选择一个SecureRandom实现。
如果您只是使用旧机制获得最高优先级的SecureRandom实现(即新的java.security.SecureRandom()),那么您将根据您的平台获得以下实现:
[表“2”未找到/]如果您使用SecureRandom.getInstanceStrong(),则使用以下默认值:
[表“3”未找到/]由于这种默认行为,您应该避免在可用性很重要的Solaris / Linux / MacOS上运行的任何服务器端代码中使用SecureRandom.getInstanceStrong()。
当为了加密而在Java中生成随机数时,许多开发人员经常使用java.security.SecureRandom
该类。虽然java.security.SecureRandom
该类旨在生成加密安全的随机数,但API中有几个细微之处,如果使用不当,则输出可以变得可预测。在Cigital,我们见证了一些这样的情况。以下是正确使用Java java.security.SecureRandom
类的指南。
首先,我们来看看java.security.SecureRandom
API的工作原理。本java.security.SecureRandom
类没有真正实现一个伪随机数生成器(PRNG)本身。它在其他类中使用PRNG实现来生成随机数。当java.security.SecureRandom
创建实例时,实际可以使用一些实际的PRNG 。PRNG是Java加密服务提供商(CSP)的一部分。在Sun的Java实现中,默认情况下使用SUN CSP。在Windows上,SUN CSP默认使用在sun.security.provider.SecureRandom中实现的SHA1PRNG。在Solaris和Linux上,SUN CSP默认是使用sun.security.provider.NativePRNG,它只提供操作系统提供的/dev/urandom
PRNG 的输出。但是,如果在Solaris / Linux上,则会修改JRE中的java.security配置文件,以便securerandom。/dev/urandom
源设置为除文件之外的其他东西: 然后在Windows上使用sun.security.provider.SecureRandom中实现的SHA1PRNG。当然,应用程序可以选择不使用默认值,并且可以随时指定由特定加密提供程序实现的特定PRNG。在Cigital的经验中,大多数Java应用程序java.security.SecureRandom
实际上使用了SUN CSP提供的SHA1PRNG。
现在,应用程序最终会sun.security.provider.SecureRandom
使用以下调用实现的SHA1PRNG 实例:
//以下将在Windows上创建SUN SHA1PRNG //默认配置和Sun JRE,以及Solaris / Linux //如果在java.security中修改securerandom.source SecureRandom sr1 = new SecureRandom(); //以下将创建SUN SHA1PRNG如果最高 //优先级CSP是SUN SecureRandom sr2 = SecureRandom.getInstance(“SHA1PRNG”); //以下将始终创建SUN SHA1PRNG SecureRandom sr3 = SecureRandom.getInstance(“SHA1PRNG”,“SUN”);
请注意,根据Sun的文档,java.security.SecureRandom
任何这些调用都不会返回返回的实例。如果在这些调用中的一个java.security.SecureRandom.nextBytes(byte[])
被调用之后,则使用由底层操作系统提供的安全机制(从Windows中的JRE 1.4.1开始,在Linux和Solaris中以JRE 1.4.2开始)种下PRNG。如果在调用之前java.security.SecureRandom.setSeed(long)
或java.security.SecureRandom.setSeed(byte[])
之后调用java.security.SecureRandom.nextBytes(byte[])
,则旁路内部播种机制,只有提供的种子才能生成随机数。
对于那些不熟悉加密PRNG的内部工作的人来说,他们的工作就是采取一个相对较小的随机种子,并使用它来产生对于不知道种子是什么的人来说似乎随机的确定性输出。PRNG试图确保输出不显示有关种子的任何信息,并且观察输出的人不能在不知道种子的情况下预测未来的输出。
通过绕过SHA1PRNG的内部安全播种机制,您可能会危及PRNG输出的安全性。如果您使用攻击者可能预测的任何内容(例如,创建PRNG实例的时间),那么使用java.security.SecureRandom
可能无法提供所需的安全级别。
最后,无论PRNG如何播种,不应无限期地使用PRNG。PRNG输出的长期安全性有两种方法:
java.security.SecureRandom
实例并创建一个新的实例。这将生成一个新的实例与一个新的种子。java.security.SecureRandom.setSeed
(java.security.SecureRandom.generateSeed(int)
)来定期向PRNG种子添加新的随机资料。 总之,使用时请注意以下几点java.security.SecureRandom
:
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG", "SUN");
java.security.SecureRandom.nextBytes(byte[])
在创建新的PRNG实例后,请始终立即调用。这将使PRNG牢牢扎根。如果出于测试目的,您需要可预测的输出,忽略此规则并且使用硬编码/可预测值播种PRNG可能是适当的。Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。