On 12/04/2014 10:40 AM, Paul Sandoz wrote:
Hi,

I think we may be over-rotating a little on this.

There is already a mechanism to create a cryptographically strong seed by 
setting a system property and using SecureRandom. That has a high 
initialization cost, but i think under those circumstances that cost is 
acceptable (it may well be possible to reduce that cost but i consider that to 
be a separate issue).

For the default case what we need is something with low initialization cost 
that is *good enough* for the majority of cases e.g. documents the lower bound 
of cryptographic strength.

I like Doug's approach to hide this under TLR, i think that fits well with the "good 
enough" aspect (cross seeding can be documented as an @implNote). But I still 
marginally prefer a public static method as well, and SecureRandom seems an appropriate 
choice (although it could easily be exposed on System or Runtime).

Paul.

Right. I think the cleanest is to provide an internal public API (modules will effectively hide it from user code) and then expose it if desired by delegation or just use it internally. For JDK8u, the approach to disable the API for user code could use similar trick as Unsafe. If anyone wants to bother with reflection, let him do it. We can't prevent that in JDK8 no matter how deep the implementation is buried.

Here's the 3rd iteration of SystemRandom:

http://cr.openjdk.java.net/~plevart/jdk9-dev/SystemRandom/webrev.03/

I managed to make LoadLibrary work (I used LoadLibraryA - the ANSI variant).

The API is back to getBytes() instance method and a getInstance() static method that lazily initializes a singleton instance. This way the initialization is clearly separated from use. Initialization is expected to fail if the system does not support the interface (/dev/urandom or ADVAPI32!RtlGenRandom), but use should always succeed unless there's something wrong with the state of the operating system (testing will show if my assumptions are correct).

The enclosed test results (on 64 bit Linux, i7 PC):

SystemRandomTest... (8 bytes / invocation)
1st invocation: 116368 ns, result: [47, -68, 15, -28, 76, -11, -70, -10]
Following 1000000 invocations: 0.624066896 s, (624 ns/invocation)

On 32 bit Windows 7 (VirtualBox guest on the same Linux host):

SystemRandomTest... (8 bytes / invocation)
1st invocation: 1329219 ns, result: [31, -5, 62, -34, -82, -69, 69, 80]
Following 1000000 invocations: 1.137231408 s, (1137 ns/invocation)


The initialization latency on Windows is higher that with code in webrev.02, but sill lower that when using MS Crypto API. I think that's because now the ADVAPI32.DLL is loaded lazily as part of singleton initialization, in webrev.02 it was loaded as part of libjava.dll, since it was linked with it, so the measurement did not include the ADVAPI32.DLL loading time.

We can now play in Java and use a strategy that releases the singleton after some time (thinking WeakReference) and ADVAPI32.DLL will be effectively unloaded and unmapped from the process address space. The same goes with UNIX variant and it's file descriptor open from /dev/urandom file...

I think webrev.03 is ready for testing.

Regards, Peter


On Dec 4, 2014, at 9:20 AM, Peter Levart <peter.lev...@gmail.com> wrote:

On 12/04/2014 12:32 AM, Martin Buchholz wrote:
On Wed, Dec 3, 2014 at 2:15 PM, Doug Lea <d...@cs.oswego.edu> wrote:

No public API because systemSeed need only be implemented
inside TLR, for its initial seed. Then the others can get their seeds
using ThreadLocalRandom.current().nextLong(), unless
java.util.secureRandomSeed is set (which I didn't illustrate above).
In other words, across all non-secure generators, you only need
one system-generated seed.
That's good enough for seeding other non-cryptographically secure
PRNGs, but if you want each caller to get a
cryptographically secure random number, you need to avoid correlations
between them that would arise when you use a non-CS PRNG to generate
them from a single CS seed.
Unless java.util.Random is retrofitted to allocate new cryptographically secure 
seed for each new instance. In such case expression:

    new java.util.Random().nextLong()

...could be used to gather secure seed. Perhaps even SplittableRandom could 
allocate new seed from secure source for each new instance (only in public 
constructor - not when it is split()ed)...

What makes those workarounds unsuitable is failure mode. Gathering secure seed 
is inherently coupled with possible failure which must be communicated 
explicitly to the consumer. But one must not be bothered with failure in 
situations where security is not a necessary ingredient.

So for  non-CS PRNGs, cross-seeding is a possible solution, but it's nicer for 
all of them to just use a common (internal) API.

As far as public API is concerned, there already is one: 
SecureRandom.generateSeed(). It's as good as SystemRandom (uses same primary 
means) and has a nice cross-platform fallback (ThreadedSeedGenerator). It's 
only drawback is that it comes with all the baggage of security providers (Java 
and MS Crypto API on Windows). But that's ok for user code perhaps.

So what we have here is two desires:
- we want a resource-friendly / with as little dependencies as possible way to 
generate some unique seed, with implicit fall-back which need not be secure
- we want a resource-friendly / with as little dependencies as possible way to 
generate secure random bytes that can be pseudo-random, but still secure, with 
explicit failure mode

I'll try to address this dichotomy in the next iteration of the API.

Regards, Peter

P.S. Is anyone interested in generating truly random bytes?

http://www.cryptography.com/public/pdf/Intel_TRNG_Report_20120312.pdf

https://software.intel.com/en-us/tags/35970


Reply via email to