Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java keytool / the security of generated keys with java (in general)

We are using the keytool bundled with the java installation to generate keys to do an asymmetric RSA encryption. In the light of recent events somebody asked me whats happening under the hood of the java keytool. Especially regarding the randomness of the resulting numbers. (e.g. "huh why isn't there any random user input taken like mouse movements or keyboard input?"

So what are the 'randomness sources' of the java keytool to create its keys?

I did a quick research myself however the only information I found was a post from 2000:

  • The keytool.exe uses the SecureRandom as basis of its random numbers.
  • The Sun provider for SecureRandom follows the IEEE P1363 standard,
  • the Sun SecureRandom provider complies with NIST's FIPS PUB 140-1 section 4.11.
  • The Sun provider for SecureRandom mixes in other sources of entropy with the results from the thread contention process. Among other things this includes the current time, the state of the VM's memory usage, system properties, and file system activity.
  • The algorithm can perform poorly in the absence of a JIT and so we are considering supplying an alternative provider which will take advantage of platform specific support for an entropy gathering device such as /dev/random or the Pentium III thermal-noise RNG.

But this was back in 2K so may be someone of you could shed some light on that and provide an update to the above (different in Java7?). Depending on your answer I would be interessted if you would advise to switch to another provider like bouncycastle...

Update: I now assume that the keytool is using java.security.SecureRandom (and thus the default provider) as a base for its random numbers. I found another interessting article, which pointed me to the file which controls the configuration of the SecureRandom API JAVA_HOME/lib/security/java.security

In there it states the following:

Select the source of seed data for SecureRandom. By default an attempt is made to use the entropy gathering device specified by the securerandom.source property. If an exception occurs when accessing the URL then the traditional system/thread activity algorithm is used. On Solaris and Linux systems, if file:/dev/urandom is specified and it exists, a special SecureRandom implementation is activated by default. This "NativePRNG" reads random bytes directly from /dev/urandom. On Windows systems, the URLs file:/dev/random and file:/dev/urandom enables use of the Microsoft CryptoAPI seed functionality.

securerandom.source=file:/dev/urandom

Since we are on a windows system I assume that the Microsoft CryptoAPI is used. Since Win7 is used it is the CNG (CryptoAPI Next Generation). Does anybody know what 'use of the Microsoft CryptoAPI seed functionality.' means? The most probable method seems to be: CryptGenRandom function

Update: Oracle seem to have improved some issues with Java 8.

like image 402
Lonzak Avatar asked Oct 01 '13 15:10

Lonzak


2 Answers

I wanted to share my findings here:

  1. keytool.exe uses the SecureRandom as basis of its random numbers, as can be seen in its sourcecode: Keytool and CertAndKeyGen.

  2. Normally, as the SecureRandom API states: "A cryptographically strong random number minimally complies with the statistical random number generator tests specified in FIPS 140-2, Security Requirements for Cryptographic Modules, section 4.9.1." Thus all implementations of SecureRandom should be in compliance with FIPS-140-2.

  3. The configuration of the Security Providers (thus also for SecureRandom) is done in JAVA_HOME/lib/security/java.security. The default is (top of the list): security.provider.1=sun.security.provider.Sun

  4. When not changing 3.) on Linux, the default implementation for SecureRandom is NativePRNG, while on Windows the default is SHA1PRNG. In our case it is a windows pc generating the keys thus it is SHA1PRNG.

  5. When looking at the implementation the following stands out:

    "Note that if a seed is not provided, we attempt to provide sufficient seed bytes to completely randomize the internal state of the generator (20 bytes). However, our seed generation algorithm has not been thoroughly studied or widely deployed."

  6. The SeedGenerator (singleton across all SHA1PRNG SecureRandom objects) has the following order for its "seed sources":

    • NativeSeedGenerator() (/dev/random on linux, on windows MS CryptoAPI is used)
    • URLSeedGenerator(url) if property “securerandom.source” is something else
    • ThreadedSeedGenerator fallback
  7. Now the following problems have been found with SHA1PRNG:

    • Inconsistencies
    • Statistical bias I (pp.152, french, use translator if n.)

      "A black box test with a generated file of 500MB, however, showed the existence of statistical biases of the output by an order of 15."

    • Statistical bias II (pp.1)

      "The experimental results in this paper show that sequences produced by pseudorandom generators SHA1PRNG (in Java) could be distinguished from uniformly chosen sequences with a high probability"

    • Poor variance (page 12) and limited state size (p.9)

      "The random bytes had grave difficulties with the STS tests, failing Monobit, Runs and the first eight Serial tests. This indicates poor variance in single bits and tuples up to eight bits." AND "In Java adding more entropy (>160bit) to an instance will not enhance security. This limitation is alarming, since it renders the PRNGs useless for key generation > 160 bit (as e.g., in AES' case)."

The result is:

  • The default implementation for all java windows installation is SHA1PRNG
  • SHA1PRNG behaves highly erratic
  • SHA1PRNG is highly proprietary - it does not comply with FIPS-140-2 (as it should be).
  • Unfortunately (to quote the implementors) "our seed generation algorithm has not been thoroughly studied". But with the wide distribution of java it is now widely deployed and used.

Thus the Java keygeneration mechanism (at least on windows) can be assumed as broken. As a consequence most of the authors advise to use some piece of hardware like an HSM / TRNG.

like image 119
Lonzak Avatar answered Sep 29 '22 16:09

Lonzak


It seems that, besides details of the high level API documented here, the implementation is probably platform (Windows/Linux) AND JDK implementation (OpenJDK/OracleJDK) specific. You can see the source code of the OpenJDK implementation of NativePRNG (used on Linux) here.

Perhaps consider using the bouncycastle provider just for improved transparency and consistency across platforms.

like image 20
Keith Avatar answered Sep 29 '22 16:09

Keith