Update #6: JEP 123: SecureRandom Draft and Implementation.
bradford.wetmore at oracle.com
Wed Apr 10 16:28:34 PDT 2013
Fixed some stupidness in the tests.
Also, ignore the make/sun/splashscreen change. That will be fixed
elsewhere, but I needed it to be able to build using the old system.
On 4/10/2013 3:07 PM, Brad Wetmore wrote:
> Hi Florian,
> > I wonder if this change to src/share/lib/security/java.security-linux
> > -securerandom.source=file:/dev/urandom
> > +securerandom.source=file:/dev/random
> > causes the return of the blocking behavior.
> Welcome to my "can of worms."  I hope everything I've said below is
> correct, and haven't made any typos!
> > In the past, I saw
> > /dev/random-related blocking during server start-up because too many
> > SecureRandom instances needed seeding. If I follow the code
> > correctly,
> If you came to this code fresh and understood it all in 7 hours, I would
> either give you a medal, or hand in my badge. :) It's really twisted
> > seeding of non-strong generators now uses /dev/random again, which is
> > subject to blocking.
> Given the long history of the JDK and concerns about backwards
> compatibility, our SecureRandom implementations have become *REALLY*
> hard to understand. Trying to make sense of all this, and now cleaning
> it up, was actually more than 1/2 of the project. It took me a couple
> weeks of intense code scrutiny/archeology, and then needed to write a
> wiki page just to keep my head wrapped around it. Likely the most
> confusing issue I've ever worked on.
> In a nutshell, the current implementation of SHA1PRNG does indeed read
> from /dev/random while seeding itself and supplying bytes via
> generateSeed(), which is in opposition to the documented behavior of the
> security properties: Remember the infamous "file:/dev/./urandom"
> workaround for SHA1PRNG?  (sigh...)
> I'll try to simplify as much as I can. I'll be including parts of this
> for the JDK 8 Oracle's Provider Impl page.
> In the current environment, here's our current list of providers, in
> default preference order.
> As you probably know, "new SecureRandom()" obtains the first
> implementation in the list, unless you call
> "SecureRandom.getInstance("alg") or SecureRandom.getInstance("alg",
> "provider"), which gets a specific algorithm, either most preferred
> version or by a specific provider, respectively.
> The securerandom.source/java.security.egd currently only affects
> SHA1PRNG, but there's a slight wrinkle in that certain property values
> promote NativePRNG ahead of SHA1PRNG in the list of algorithms in the
> SUN provider. More on this later.
> Current behavior:
> does not use securerandom.source/java.security.egd at all
> engineGenerateSeed: always reads from /dev/random
> engineNextBytes: always reads from /dev/urandom
> Since this is a real PRNG , SHA1PRNG requires a very strong seed
> (initial) value, as strong as possible. If not initially seeded by the
> user via setSeed, SHA1PRNG will call SeedGenerator.getSystemEntropy +
> SeedGenerator.generateSeed() to generate a strong seed for itself.
> There are three seed generators which have SeedGenerator as their parent:
> ThreadedSeedGenerator was the original Seeder which uses
> system load to generate seed values, and is only used as a
> last resort. (SLOW!)
> URLSeedGenerator takes a URL and reads from it.
> NativeSeedGenerator uses /dev/random.
> When the SeedGenerator class initializes, if the properties
> (securerandom.source/java.security.egd) resolve to either the exact
> strings "file:/dev/random" or "file:/dev/urandom", it will use
> NativeSeedGenerator (/dev/random). (Yeah, try explaining that to
> customers!) If the properties resolve to any other URL, then we use
> URLSeedGenerator with that URL. Note, this is why the infamous
> workaround "file:///dev/urandom" or "file:/dev/./urandom" works.  As
> someone once said, this has got to be the most confusing workaround in
> the history of the JDK. I would agree! :) If neither SeedGenerator is
> available, then we use ThreadedSeedGenerator as the last resort.
> Once seeded, then later calls to this SHA1PRNG SecureRandom instance are:
> engineGenerateSeed: always reads from SeedGenerator
> engineNextBytes: Number generation using the current state as
> input into SHA1.
> So even though the EGD properties point to file:/dev/urandom, it's not
> correct when it comes to the seeder.
> Back in JDK 5, adding NativePRNG was the "workaround" for this problem.
> When setting up the default order of implementations in the SUN
> provider, if the properties URL is "file:/dev/urandom", then NativePRNG
> becomes the most preferred provider (over SHA1PRNG). So for those Linux
> implementations which just asked for the "most preferred" (i.e. new
> SecureRandom()), they get an instance of NativePRNG which uses
> /dev/urandom for nextBytes. (Note well:
> NativeSeedGenerator.generateSeed() still reads from /dev/random).
> So since you're not seeding a SHA1PRNG, using NativePRNG.nextBytes()
> makes it appear as though there is no more stalling, as long as you only
> call nextBytes() and not generateSeed(). But if you specifically asked
> for SHA1PRNG (which a lot of customers had baked into their code), you
> still go through the above, and will stall when SHA1PRNG tried to seed
> (Again, try to explain this to customers. We've had many escalations
> over the years!)
> Didn't touch. Their behavior doesn't allow have the concept of a EGD.
> New Behavior:
> So, what do my change do?
> . Corrects the java.security files to reflect the new implementation,
> and corrects vagueness/long-standing errors. In particular, the
> security property default becomes "file:/dev/random" which matches the
> old AND new implementations, which is what triggered this long discussion!
> . SUN provider: If the properties are *EITHER* "file:/dev/random" or
> "file:/dev/urandom", then it promotes NativePRNG ahead of SHA1PRNG in
> the list of preferred impls. If it's not one of those, then SHA1PRNG is
> preferred over NativePRNG.
> . NativePRNG: Now respects the seeder properties. If the property
> isn't "file:/" or doesn't exist, we'll fall back to /dev/random.
> . Adds blocking and nonblocking variants of NativePRNG:
> NativePRNGBlocking/NativePRNGJNonBlocking. The
> generateSeed()/nextBytes() methods both use /dev/random or /dev/urandom,
> . NativeSeedGenerator: essentially, this becomes the same as a
> URLSeedGenerator. Instead of only using "/dev/random", it will the
> specified value of "file:/dev/random" or "file:/dev/urandom"
> . Adds SecureRandom.getStrongSecureRandom. Uses a security property to
> specify the strongest impl(s) on this system. See the API for more
> . Minor style cleanups
> I hope this is clear.
>  https://www.google.com/search?q=define%3A+can+of+worms
>  http://en.wikipedia.org/wiki/Pseudorandom_number_generator
More information about the security-dev