How to deal with a slow SecureRandom generator?
Asked Answered
G

17

189

If you want a cryptographically strong random numbers in Java, you use SecureRandom. Unfortunately, SecureRandom can be very slow. If it uses /dev/random on Linux, it can block waiting for sufficient entropy to build up. How do you avoid the performance penalty?

Has anyone used Uncommon Maths as a solution to this problem?

Can anybody confirm that this performance problem has been solved in JDK 6?

Gulick answered 26/9, 2008 at 1:7 Comment(4)
It seems this is related to SecureRandom.generateSeed() slowness. There's a rejected defect explaining the slowness and a workaround: JDK-6521844 : SecureRandom hangs on Linux SystemsTubman
Check out /dev/urandom (not /dev/random) .. Consider just getting a random number generator seed from urandom if there is a blocking problem.Tripping
Windows related: #49323448Identic
@Tubman - The JDK-6521844 Link does not exist anymore...Huttan
D
95

If you want true random data, then unfortunately you have to wait for it. This includes the seed for a SecureRandom PRNG. Uncommon Maths can't gather true random data any faster than SecureRandom, although it can connect to the internet to download seed data from a particular website. My guess is that this is unlikely to be faster than /dev/random where that's available.

If you want a PRNG, do something like this:

SecureRandom.getInstance("SHA1PRNG");

What strings are supported depends on the SecureRandom SPI provider, but you can enumerate them using Security.getProviders() and Provider.getService().

Sun is fond of SHA1PRNG, so it's widely available. It isn't especially fast as PRNGs go, but PRNGs will just be crunching numbers, not blocking for physical measurement of entropy.

The exception is that if you don't call setSeed() before getting data, then the PRNG will seed itself once the first time you call next() or nextBytes(). It will usually do this using a fairly small amount of true random data from the system. This call may block, but will make your source of random numbers far more secure than any variant of "hash the current time together with the PID, add 27, and hope for the best". If all you need is random numbers for a game, though, or if you want the stream to be repeatable in future using the same seed for testing purposes, an insecure seed is still useful.

Diminutive answered 26/9, 2008 at 1:39 Comment(16)
Uncommons Maths only downloads data from the Internet for seeding, it doesn't return that random data when generating random numbers.Tattle
Same with SecureRandom - the /dev/urandom is only for seeding.Elisa
Yep. When the questioner says "if you want a random number you use SecureRandom - this can be slow", I thought maybe he's using getSeed for everything and draining his entropy pool. The fix isn't to get JDK 6, it's to use SecureRandom the way it's intended ;-)Diminutive
@Dan Dyer - I've corrected my comment about Uncommon Maths. I did take a look at your page, so I knew that by "random numbers" I meant "for its seed" rather that "to return to the user". But you're quite right that isn't what I said...Diminutive
"it's widely available". Isn't it included with every compliant JDK? It's on the list of java security standard names... (docs.oracle.com/javase/8/docs/technotes/guides/security/…)Fosse
@Sean: I don't remember how all this works now (question was a long time ago and I don't really do Java any more). But the documentation says "supplied by the SUN provider". So presumably it's always in the JDK, but needn't necessarily be included in Java implementations other than Oracle's.Diminutive
@SteveJessop from the standard names document: "The JDK Security API requires and uses a set of standard names for algorithms, certificate and keystore types." The provider name can certainly be different with a non-Oracle JDK, but I read this as requiring that the algorithm names are standard and don't change, i.e. there will always be some implementation of SHA1PRNG on every Java platform.Fosse
@SeanReilly: fortunately it's a lot of years since I last had to run a TCK and argue with Sun whether failures actually mean that the implementation doesn't conform or just that the tests don't match the spec :-)Diminutive
@SeanReilly: Something appearing in the list of Standard Names doesn't imply it is actually implemented. For example, Sun/Oracle included various elliptic curve names in that list well before they actually had an implementation of them. SHA1PRNG in particular is not a standard -- it's proprietary to Sun/Oracle, so needn't be supported at all. Every Java environment I've seen does support it however.Buckles
@JamesKPolk: That is not what the spec says. The normative portion of the spec specifically says "requires", and therefore any implementation that didn't support a standard algorithm would not be an conforming implementation of this standard — and therefore not a conforming implementation of Java, Standard Edition. The providers vary a lot and should not be relied on by portable code, and of course every provider is not required to have an impl of every algorithm, but at least one implementation of every algorithm on the standard list has to be there.Fosse
@SeanReilly: where does the spec say that? I read it and I don't see anywhere it says that.Buckles
@JamesKPolk I had already quoted the line above. It's included here: docs.oracle.com/javase/8/docs/technotes/guides/security/… "The JDK Security API requires and uses a set of standard names for algorithms, certificate and keystore types. This specification establishes the following names as standard names." The emphasis is mine, but the spec specifically says "requires".Fosse
You're clearly deciding what that "requires" means by yourself, nowhere does it say it has to be implemented. It doesn't make sense to "require" SHA1PRNG to be implemented since it is proprietary and not documented. For example, the "ECIES" standard name has been a "required" name since Java 6 but has not been implemented by any Oracle/Sun provider in up to and including Java 8. So clearly you're interpretation doesn't align with Oracle/Sun's.Buckles
This answer is entirely wrong, you should not rely on "SHA1PRNG". At best you will create code that is non-portable. At worse you will get a relatively badly perforing RNG or even an insecure implementation on e.g. old versions of Android. See below why (comment too long):Shine
@SeanReilly The names are required, but the implementation of them is not. Please check the footnote on the implementation requirements: "No specific Configuration type, Policy type or SecureRandom algorithm is required; however, an implementation-specific default must be provided."Shine
OK, I will relent a bit. Using an application specific pseudo random number genarator (PRNG) such as SHA1PRNG may relieve the systems RNG somewhat. However, as it is by definition non-portable, you should at least make the algorithm name configurable and test on each system. Later Java versions may also have better NIST compatible PRNG's. Just using new SecureRandom() and configure the provider order should still be preferred to this approach. Also see the answer of Dan for alternative PRNG's.Shine
K
184

You should be able to select the faster-but-slightly-less-secure /dev/urandom on Linux using:

-Djava.security.egd=file:/dev/urandom

However, this doesn't work with Java 5 and later (Java Bug 6202721). The suggested work-around is to use:

-Djava.security.egd=file:/dev/./urandom

(note the extra /./)

Kashakashden answered 24/2, 2010 at 10:11 Comment(8)
Note that the Java Bug report says "Not a defect". In other words even though the default is /dev/urandom, Sun treats this as a magic string and uses /dev/random anyway, so you have to fake it out. When is a file: URL not a file: URL? Whenever Sun decides it's not :-(Archangel
Having just spent a bunch of time investigating this, it seems that the normal setting, even with file:/dev/urandom set in -Djava.security.egd or in securerandom.source in the java.security file, /dev/random/ is still read whenever SecureRandom.getSeed() (or setSeed() is called). The workaround with file:/dev/./urandom results in not reading /dev/random at all (confirmed with strace)Checkrow
/dev/urandom isn't less secure than /dev/random when implemented with a modern CSPRNG: en.wikipedia.org/wiki//dev/random#FreeBSDBarbiturate
I think the main fear of /dev/urandom/ is what happens if you use it to generate secrets on new hardware out of the box, which might be in a quite predictable state. /dev/urandom/ won't block for entropy even though that's one case where you should. The situation is even worse if the secret is persistent, like if the first thing your device does on first boot is generate a public-private key pair. Outside of those scary situations, a good /dev/urandom is better than using the common SecureRandom algorithms anyway.Diminutive
Isn't it automatic /dev/unrandom on linux also ?Intracardiac
Which one is correct ? -Djava.security.egd=file:/dev/./urandom or file:///dev/urandom @mattbKorean
I have a follow up question. #40383930. Is it ok to do so in production? Will this have any impact on security (like Session ID becoming predictable)?Pavid
@AarishRamesh file:///dev/urandom and file:/dev/./urandom have the same purpose, which is the path string to not be file:/dev/urandom. Therefore the bug is avoided, but the accessed device is in both cases /dev/urandom. As a quick do-it-yourself test you could try these: head -c 10 ///dev/urandom and head -c 10 /dev/./urandom. The latter is imho easier to read and less error prone.Earing
D
95

If you want true random data, then unfortunately you have to wait for it. This includes the seed for a SecureRandom PRNG. Uncommon Maths can't gather true random data any faster than SecureRandom, although it can connect to the internet to download seed data from a particular website. My guess is that this is unlikely to be faster than /dev/random where that's available.

If you want a PRNG, do something like this:

SecureRandom.getInstance("SHA1PRNG");

What strings are supported depends on the SecureRandom SPI provider, but you can enumerate them using Security.getProviders() and Provider.getService().

Sun is fond of SHA1PRNG, so it's widely available. It isn't especially fast as PRNGs go, but PRNGs will just be crunching numbers, not blocking for physical measurement of entropy.

The exception is that if you don't call setSeed() before getting data, then the PRNG will seed itself once the first time you call next() or nextBytes(). It will usually do this using a fairly small amount of true random data from the system. This call may block, but will make your source of random numbers far more secure than any variant of "hash the current time together with the PID, add 27, and hope for the best". If all you need is random numbers for a game, though, or if you want the stream to be repeatable in future using the same seed for testing purposes, an insecure seed is still useful.

Diminutive answered 26/9, 2008 at 1:39 Comment(16)
Uncommons Maths only downloads data from the Internet for seeding, it doesn't return that random data when generating random numbers.Tattle
Same with SecureRandom - the /dev/urandom is only for seeding.Elisa
Yep. When the questioner says "if you want a random number you use SecureRandom - this can be slow", I thought maybe he's using getSeed for everything and draining his entropy pool. The fix isn't to get JDK 6, it's to use SecureRandom the way it's intended ;-)Diminutive
@Dan Dyer - I've corrected my comment about Uncommon Maths. I did take a look at your page, so I knew that by "random numbers" I meant "for its seed" rather that "to return to the user". But you're quite right that isn't what I said...Diminutive
"it's widely available". Isn't it included with every compliant JDK? It's on the list of java security standard names... (docs.oracle.com/javase/8/docs/technotes/guides/security/…)Fosse
@Sean: I don't remember how all this works now (question was a long time ago and I don't really do Java any more). But the documentation says "supplied by the SUN provider". So presumably it's always in the JDK, but needn't necessarily be included in Java implementations other than Oracle's.Diminutive
@SteveJessop from the standard names document: "The JDK Security API requires and uses a set of standard names for algorithms, certificate and keystore types." The provider name can certainly be different with a non-Oracle JDK, but I read this as requiring that the algorithm names are standard and don't change, i.e. there will always be some implementation of SHA1PRNG on every Java platform.Fosse
@SeanReilly: fortunately it's a lot of years since I last had to run a TCK and argue with Sun whether failures actually mean that the implementation doesn't conform or just that the tests don't match the spec :-)Diminutive
@SeanReilly: Something appearing in the list of Standard Names doesn't imply it is actually implemented. For example, Sun/Oracle included various elliptic curve names in that list well before they actually had an implementation of them. SHA1PRNG in particular is not a standard -- it's proprietary to Sun/Oracle, so needn't be supported at all. Every Java environment I've seen does support it however.Buckles
@JamesKPolk: That is not what the spec says. The normative portion of the spec specifically says "requires", and therefore any implementation that didn't support a standard algorithm would not be an conforming implementation of this standard — and therefore not a conforming implementation of Java, Standard Edition. The providers vary a lot and should not be relied on by portable code, and of course every provider is not required to have an impl of every algorithm, but at least one implementation of every algorithm on the standard list has to be there.Fosse
@SeanReilly: where does the spec say that? I read it and I don't see anywhere it says that.Buckles
@JamesKPolk I had already quoted the line above. It's included here: docs.oracle.com/javase/8/docs/technotes/guides/security/… "The JDK Security API requires and uses a set of standard names for algorithms, certificate and keystore types. This specification establishes the following names as standard names." The emphasis is mine, but the spec specifically says "requires".Fosse
You're clearly deciding what that "requires" means by yourself, nowhere does it say it has to be implemented. It doesn't make sense to "require" SHA1PRNG to be implemented since it is proprietary and not documented. For example, the "ECIES" standard name has been a "required" name since Java 6 but has not been implemented by any Oracle/Sun provider in up to and including Java 8. So clearly you're interpretation doesn't align with Oracle/Sun's.Buckles
This answer is entirely wrong, you should not rely on "SHA1PRNG". At best you will create code that is non-portable. At worse you will get a relatively badly perforing RNG or even an insecure implementation on e.g. old versions of Android. See below why (comment too long):Shine
@SeanReilly The names are required, but the implementation of them is not. Please check the footnote on the implementation requirements: "No specific Configuration type, Policy type or SecureRandom algorithm is required; however, an implementation-specific default must be provided."Shine
OK, I will relent a bit. Using an application specific pseudo random number genarator (PRNG) such as SHA1PRNG may relieve the systems RNG somewhat. However, as it is by definition non-portable, you should at least make the algorithm name configurable and test on each system. Later Java versions may also have better NIST compatible PRNG's. Just using new SecureRandom() and configure the provider order should still be preferred to this approach. Also see the answer of Dan for alternative PRNG's.Shine
T
35

On Linux, the default implementation for SecureRandom is NativePRNG (source code here), which tends to be very slow. On Windows, the default is SHA1PRNG, which as others pointed out you can also use on Linux if you specify it explicitly.

NativePRNG differs from SHA1PRNG and Uncommons Maths' AESCounterRNG in that it continuously receives entropy from the operating system (by reading from /dev/urandom). The other PRNGs do not acquire any additional entropy after seeding.

AESCounterRNG is about 10x faster than SHA1PRNG, which IIRC is itself two or three times faster than NativePRNG.

If you need a faster PRNG that acquires entropy after initialization, see if you can find a Java implementation of Fortuna. The core PRNG of a Fortuna implementation is identical to that used by AESCounterRNG, but there is also a sophisticated system of entropy pooling and automatic reseeding.

Tattle answered 26/9, 2008 at 11:1 Comment(3)
This link is not working.uncommons-maths.dev.java.net/nonav/api/org/uncommons/maths/…. Is there anywhere I can see this?Hymeneal
@Unni Just updated the link. Please note that the performance claims I made in this answer might not be valid any more. I think things may have got better in recent versions of Java and there can be differences in performance between platforms (i.e. Windows vs. Liux).Tattle
I was just running one example of SecureRandom with a MessageDigest and made a hexencoded it.The entire operation in my windows 7 PC took 33 milliseconds.Is it an issue.I used SHA1PRNG.SecureRandom prng = SecureRandom.getInstance("SHA1PRNG"); String randomNum = new Integer( prng.nextInt() ).toString();MessageDigest sha = MessageDigest.getInstance("SHA-1");result = sha.digest( randomNum.getBytes() ); str = hexEncode(result);Hymeneal
C
31

Many Linux distros (mostly Debian-based) configure OpenJDK to use /dev/random for entropy.

/dev/random is by definition slow (and can even block).

From here you have two options on how to unblock it:

  1. Improve entropy, or
  2. Reduce randomness requirements.

Option 1, Improve entropy

To get more entropy into /dev/random, try the haveged daemon. It's a daemon that continuously collects HAVEGE entropy, and works also in a virtualized environment because it doesn't require any special hardware, only the CPU itself and a clock.

On Ubuntu/Debian:

apt-get install haveged
update-rc.d haveged defaults
service haveged start

On RHEL/CentOS:

yum install haveged
systemctl enable haveged
systemctl start haveged

Option 2. Reduce randomness requirements

If for some reason the solution above doesn't help or you don't care about cryptographically strong randomness, you can switch to /dev/urandom instead, which is guaranteed not to block.

To do it globally, edit the file jre/lib/security/java.security in your default Java installation to use /dev/urandom (due to another bug it needs to be specified as /dev/./urandom).

Like this:

#securerandom.source=file:/dev/random
securerandom.source=file:/dev/./urandom

Then you won't ever have to specify it on the command line.


Note: If you do cryptography, you need good entropy. Case in point - android PRNG issue reduced the security of Bitcoin wallets.

Charterhouse answered 3/11, 2017 at 13:43 Comment(1)
Upvoted your answer, but "/dev/random is by definition slow (and can even block)" is wrong; it entirely depends on system configuration. Newer machines may have e.g. a fast RNG in the CPU that may be used, and BSD machines generally have the same implementation for /dev/random and /devl/urandom. Still, you should probably not rely on /dev/random being fast, necessarily. On VM's you may want to install the client toolset on the client VM so that is can use the RNG of the host OS.Shine
B
18

I had a similar problem with calls to SecureRandom blocking for about 25 seconds at a time on a headless Debian server. I installed the haveged daemon to ensure /dev/random is kept topped up, on headless servers you need something like this to generate the required entropy. My calls to SecureRandom now perhaps take milliseconds.

Byplay answered 20/5, 2015 at 19:40 Comment(1)
apt-get install haveged then update-rc.d haveged defaultsStringhalt
F
12

If you want truly "cryptographically strong" randomness, then you need a strong entropy source. /dev/random is slow because it has to wait for system events to gather entropy (disk reads, network packets, mouse movement, key presses, etc.).

A faster solution is a hardware random number generator. You may already have one built-in to your motherboard; check out the hw_random documentation for instructions on figuring out if you have it, and how to use it. The rng-tools package includes a daemon which will feed hardware generated entropy into /dev/random.

If a HRNG is not available on your system, and you are willing to sacrifice entropy strength for performance, you will want to seed a good PRNG with data from /dev/random, and let the PRNG do the bulk of the work. There are several NIST-approved PRNG's listed in SP800-90 which are straightforward to implement.

Fleshly answered 26/9, 2008 at 17:48 Comment(3)
Good point, but my code is part of a commercial application. I don't have any control over the server environment. I think the target servers are always without mouse and keyboard and rely entirely on disk and network I/O for entropy, which is probably the root problem.Gulick
I discovered that /dev/random was dependent on system events, so as a temporary workaround, I just moved my mouse back and forth while my test ran....Furnivall
That 82802 hub for the i820 chipset was painfully slow (RIP). I'm amazed you could gather anything useful from it. I think I spent more time blocking on it rather than collecting octets.Nagoya
E
10

According to the documentation, the different algorithms used by SecureRandom are, in order of preference:

  • On most *NIX systems (including macOS)
    1. PKCS11 (only on Solaris)
    2. NativePRNG
    3. DRBG
    4. SHA1PRNG
    5. NativePRNGBlocking
    6. NativePRNGNonBlocking
  • On Windows systems
    1. DRBG
    2. SHA1PRNG
    3. Windows-PRNG

Since you asked about Linux, I will ignore the Windows implementation, as well as PKCS11 which is only really available on Solaris, unless you installed it yourself — and if you did, you probably wouldn't be asking this question.

According to that same documentation, what these algorithms use are

NativePRNG

generateSeed() uses /dev/random
nextBytes() uses /dev/urandom

NativePRNGBlocking

generateSeed() and nextBytes() use /dev/random

NativePRNGNonBlocking

generateSeed() and nextBytes() use /dev/urandom

DRBG

Supported mechanisms and algorithms:

  • Hash_DRBG and HMAC_DRBG with SHA-224, SHA-512/224, SHA-256, SHA-512/256, SHA-384, and SHA-512.
  • CTR_DRBG with AES-128, AES-192, and AES-256.
SHA1PRNG

Initial seeding is currently done via a combination of system attributes and the java.security entropy gathering device.


That means if you use SecureRandom random = new SecureRandom(), it goes down that list until it finds one that works, which will typically be NativePRNG. And that means that it seeds itself from /dev/random (or uses that if you explicitly generate a seed), then uses /dev/urandom for getting the next bytes, ints, double, booleans, what-have-yous.

Since /dev/random is blocking (it blocks until it has enough entropy in the entropy pool), that may impede performance.

One solution to that is using something like haveged to generate enough entropy, another solution is using /dev/urandom instead. While you could set that for the entire jvm, a better solution is doing it for this specific instance of SecureRandom, by using SecureRandom random = SecureRandom.getInstance("NativePRNGNonBlocking"). Note that that method can throw a NoSuchAlgorithmException if NativePRNGNonBlocking is unavailable, so be prepared to fall back to the default.

SecureRandom random;
try {
    random = SecureRandom.getInstance("NativePRNGNonBlocking");
} catch (NoSuchAlgorithmException nsae) {
    random = new SecureRandom();
}

Also note that on other *nix systems, /dev/urandom may behave differently.


Is /dev/urandom random enough?

Conventional wisdom has it that only /dev/random is random enough. However, some voices differ. In "The Right Way to Use SecureRandom" and "Myths about /dev/urandom", it is argued that /dev/urandom/ is just as good.

The users over on the Information Security stack agree with that. Basically, if you have to ask, /dev/urandom is fine for your purpose.

Englishry answered 1/10, 2019 at 10:6 Comment(1)
thanks for the awesome update! the main difference "u" offers is just not blocking due to entropy. some funny aspects around the english words we collectivity chose for the ideas here: they're both equally "secure" for all practical purposes because of our own ignorance around what random even means; blocking to gather entropy makes it more random, not more secure at all; if you want to throw a dice with better entropy than throwing an actual dice, use the blocking one, if you want to deal with bank transactions, better not block it; the only thing "pseudo" about either is legacy wording.Moazami
I
7

Using Java 8, I found that on Linux calling SecureRandom.getInstanceStrong() would give me the NativePRNGBlocking algorithm. This would often block for many seconds to generate a few bytes of salt.

I switched to explicitly asking for NativePRNGNonBlocking instead, and as expected from the name, it no longer blocked. I have no idea what the security implications of this are. Presumably the non-blocking version can't guarantee the amount of entropy being used.

Update: Ok, I found this excellent explanation.

In a nutshell, to avoid blocking, use new SecureRandom(). This uses /dev/urandom, which doesn't block and is basically as secure as /dev/random. From the post: "The only time you would want to call /dev/random is when the machine is first booting, and entropy has not yet accumulated".

SecureRandom.getInstanceStrong() gives you the absolute strongest RNG, but it's only safe to use in situations where a bunch of blocking won't effect you.

Interatomic answered 30/11, 2016 at 10:20 Comment(1)
I'd only allow getInstanceStrong() for long term keys, such as those for TLS certificates. And even then I would rather use new SecureRandom() or a FIPS compliant key pair generator or random number generator. So yes, this provides an answer, if /dev/urandom doesn't block : in the end it still relies on system entropy after all; but it is very good advice in general. If /dev/urandom blocks you may have to fix the source of the issue rather than your Java application.Shine
D
6

The problem you referenced about /dev/random is not with the SecureRandom algorithm, but with the source of randomness that it uses. The two are orthogonal. You should figure out which one of the two is slowing you down.

Uncommon Maths page that you linked explicitly mentions that they are not addressing the source of randomness.

You can try different JCE providers, such as BouncyCastle, to see if their implementation of SecureRandom is faster.

A brief search also reveals Linux patches that replace the default implementation with Fortuna. I don't know much more about this, but you're welcome to investigate.

I should also mention that while it's very dangerous to use a badly implemented SecureRandom algorithm and/or randomness source, you can roll your own JCE Provider with a custom implementation of SecureRandomSpi. You will need to go through a process with Sun to get your provider signed, but it's actually pretty straightforward; they just need you to fax them a form stating that you're aware of the US export restrictions on crypto libraries.

Deicide answered 26/9, 2008 at 1:26 Comment(1)
Those different JCE providers are only of use if they use another source of entropy which basically means they have to use a specific piece of hardware, such as an HSM. Otherwise they are just as likely to experience slowdowns, depending on how much entropy they extract from the system.Shine
F
5

There is a tool (on Ubuntu at least) that will feed artificial randomness into your system. The command is simply:

rngd -r /dev/urandom

and you may need a sudo at the front. If you don't have rng-tools package, you will need to install it. I tried this, and it definitely helped me!

Source: matt vs world

Furnivall answered 28/8, 2012 at 12:35 Comment(3)
This is somewhat dangerous because it fully disables the Linux kernel’s entropy level estimation, system-wide. I think for testing purposes (reads: Jenkins running an app’s testsuite) using /dev/./urandom is fine, but in production, it’s not.Cannikin
This is actually the only solution that worked for me. I had a “not enough entropy” problem when building an Android project with Gradle on Jenkins CI, and passing a parameter to the build did not help.Ignorance
I had to combine sudo rngd -r /dev/urandom with sudo apt install rng-tools in xenialJus
P
5

I faced same issue. After some Googling with the right search terms, I came across this nice article on DigitalOcean.

haveged is a potential solution without compromising on security.

I am merely quoting the relevant part from the article here.

Based on the HAVEGE principle, and previously based on its associated library, haveged allows generating randomness based on variations in code execution time on a processor. Since it's nearly impossible for one piece of code to take the same exact time to execute, even in the same environment on the same hardware, the timing of running a single or multiple programs should be suitable to seed a random source. The haveged implementation seeds your system's random source (usually /dev/random) using differences in your processor's time stamp counter (TSC) after executing a loop repeatedly

How to install haveged

Follow the steps in this article. https://www.digitalocean.com/community/tutorials/how-to-setup-additional-entropy-for-cloud-servers-using-haveged

I have posted it here

Pavid answered 17/11, 2016 at 5:50 Comment(0)
P
4

I haven't hit against this problem myself, but I'd spawn a thread at program start which immediately tries to generate a seed, then dies. The method which you call for randoms will join to that thread if it is alive so the first call only blocks if it occurs very early in program execution.

Pat answered 26/9, 2008 at 1:11 Comment(1)
It's a rather extreme hack, but it might work; it is not said that the used PRNG may not use additional seed material which could still lead to blocking. Using a different random number providing or fixing the entropy in the system should be strongly preferred. As it may at least provide a temporary solution, I've none-the-less voted up the answer.Shine
B
3

My experience has been only with slow initialization of the PRNG, not with generation of random data after that. Try a more eager initialization strategy. Since they're expensive to create, treat it like a singleton and reuse the same instance. If there's too much thread contention for one instance, pool them or make them thread-local.

Don't compromise on random number generation. A weakness there compromises all of your security.

I don't see a lot of COTS atomic-decay–based generators, but there are several plans out there for them, if you really need a lot of random data. One site that always has interesting things to look at, including HotBits, is John Walker's Fourmilab.

Body answered 26/9, 2008 at 3:38 Comment(5)
I've always wondered about this, since hadronic tau decay products nearly attain the ideal of a randomized source I just cannot get rid of my wish to use that rather than algorithmic tools. For op's purpose, I decided long ago that some front-end time is endemic to all secure tools. If one is going to need a randomizer, that can be called in the constructor and just remember to construct one at page load time, it's buried under the avl swap-in and even as picky as I am it goes un-noticed.Paction
Intel 8xx chipsets (and probably many others) have a hardware RNG that uses thermal noise, a truly unpredictable quantum effect. Trusted Platform Modules can contain hardware RNGs too, but unfortunately, the one in my laptop does not.Body
It depends on the specific RNG if it seeds once or if it reseeds after a while. NIST specifies PRNG's that reseed, but many software implementations do not. Restructuring the code around a singleton is a horrible idea, especially on multithreaded implementations; it is better to fix the source of the problem: the slow seeding due to lack of entropy. If you use a singleton, use it to provide seeds for other SecureRandom implementations that are entirely deterministic. This kind of design probably requires quite some knowledge though.Shine
@MaartenBodewes Those are good points. If the implementation is one that blocks, waiting for system entropy, I think that treating it as a singleton in your application is not a horrible idea since the underlying source is effectively a singleton. But using that one instance to seed others is a good suggestion, even if complex. I am not sure, but I think that the Sun (and then Oracle) provider for SecureRandom has changed a couple of times in the last 10 years in its entropy gathering.Body
I'm very sure that it has changed quite a few times, so much so that I will not try and put all the changes in this comment :). It is less likely that a slow SecureRandom is still an issue, but low entropy in a system will always be issue. Using a singleton will create strongly coupled code, which is a design anti-pattern. It should therefore be used with extreme care; you'd preferably have to reverse all the references in the code if you would fix the issue.Shine
A
3

It sounds like you should be clearer about your RNG requirements. The strongest cryptographic RNG requirement (as I understand it) would be that even if you know the algorithm used to generate them, and you know all previously generated random numbers, you could not get any useful information about any of the random numbers generated in the future, without spending an impractical amount of computing power.

If you don't need this full guarantee of randomness then there are probably appropriate performance tradeoffs. I would tend to agree with Dan Dyer's response about AESCounterRNG from Uncommons-Maths, or Fortuna (one of its authors is Bruce Schneier, an expert in cryptography). I've never used either but the ideas appear reputable at first glance.

I would think that if you could generate an initial random seed periodically (e.g. once per day or hour or whatever), you could use a fast stream cipher to generate random numbers from successive chunks of the stream (if the stream cipher uses XOR then just pass in a stream of nulls or grab the XOR bits directly). ECRYPT's eStream project has lots of good information including performance benchmarks. This wouldn't maintain entropy between the points in time that you replenish it, so if someone knew one of the random numbers and the algorithm you used, technically it might be possible, with a lot of computing power, to break the stream cipher and guess its internal state to be able to predict future random numbers. But you'd have to decide whether that risk and its consequences are sufficient to justify the cost of maintaining entropy.

Edit: here's some cryptographic course notes on RNG I found on the 'net that look very relevant to this topic.

Arresting answered 23/12, 2008 at 14:27 Comment(1)
"Fortuna (one of its authors is Bruce Schneier, an expert in cryptography)" -- and the other one is Niels Ferguson, an expert in cryptography :-)Diminutive
W
2

Use the secure random as initialization source for a recurrent algorithm; you could use then a Mersenne twister for the bulk work instead of the one in UncommonMath, which has been around for a while and proven better than other prng

http://en.wikipedia.org/wiki/Mersenne_twister

Make sure to refresh now and then the secure random used for the initialization, for example you could have one secure random generated per client, using one mersenne twister pseudo random generator per client, obtaining a high enough degree of randomization

Whitesmith answered 26/9, 2008 at 12:36 Comment(1)
This answer is wrong: the Mersenne twister is not a secure random number generator. It would be a good algorithm for Random, but not for SecureRandom.Shine
M
2

If your hardware supports it try using Java RdRand Utility of which I'm the author.

Its based on Intel's RDRAND instruction and is about 10 times faster than SecureRandom and no bandwidth issues for large volume implementation.


Note that this implementation only works on those CPU's that provide the instruction (i.e. when the rdrand processor flag is set). You need to explicitly instantiate it through the RdRandRandom() constructor; no specific Provider has been implemented.

Mikiso answered 15/9, 2013 at 18:38 Comment(3)
You might want to read people.umass.edu/gbecker/BeckerChes13.pdf and be sure to never use only Intel RDRAND data. Always mix it with some other unpredictable data, such as the output of an aRC4 stream cipher (seeded from /dev/urandom and with the first few KiB of output thrown away for their known bias).Cannikin
+1 mirabilos. I think RDRAND is a good source, but its a bit untrustworthy. It definitely needs to be one input of many into a collector (no offense to David Johnston).Nagoya
I've voted up, fixed the link and provided some background info. If you don't agree please roll back the edit.Shine
B
1

Something else to look at is the property securerandom.source in file lib/security/java.security

There may be a performance benefit to using /dev/urandom rather than /dev/random. Remember that if the quality of the random numbers is important, don't make a compromise which breaks security.

Beaubeauchamp answered 3/10, 2008 at 23:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.