Setup
Java doesn't offer out-of-the-box support for the JCE Unlimited Strength Policy Files
This prevents users from using AES-256, the largest key size of a widely-used encryption standard
Not including the policy files leads to many problems:
Unexpected exceptions
Unsatisfying workarounds:
Just install them
Use a different implementation
Use reflection that may violate the Java License Agreement
Breakage after JRE updates
Confusion after installation
And more!
All this noise leads to broken and/or buggy programs
Question
Why are these not provided and treated like a black sheep?
As it turns out, it's not strict crypto export laws, but simply that no one got around to it yet.
In fact, it's been planned for a long time to not have to jump through these hoops.
In Java 9, the ceremony will be condensed down to a one-liner: Security.setProperty("crypto.policy", "unlimited");
Now Unlimited cryptography enabled by default in the JDK
The JDK uses the Java Cryptography Extension (JCE) Jurisdiction Policy files to configure cryptographic algorithm restrictions. Previously, the Policy files in the JDK placed limits on various algorithms. This release ships with both the limited and unlimited jurisdiction policy files, with unlimited being the default. The behavior can be controlled via the new 'crypto.policy' Security property found in the /lib/java.security file. Please refer to that file for more information on this property.
See: http://www.oracle.com/technetwork/java/javase/8u161-relnotes-4021379.html#JDK-8170157
The US has restrictions on the export of cryptographic technology:
https://en.wikipedia.org/wiki/Export_of_cryptography_from_the_United_States
They used to be very strict -- cryptography was classified as munitions, and you could only download the full strength products from the US and other whitelisted countries.
Restrictions have eased up a lot since then, but some remain, and full strength JCE can't be freely distributed everywhere like the JRE, so it's a separate package.
Related
I've been experimenting with the BouncyCastle API for Java and slowly working my way through their "Java Cryptography - Tools and Techniques" ebook. The book contains a short section titled "A Word About Entropy" which states the following:
What the JVM is using as an entropy source will vary, on Linux for example, it is normally set to “/dev/random” which may block. Usually installing
“rng-tools” or the nearest equivalent will deal with this as it will also
expose any underlying hardware supporting RNG generation to be used for
seeding “/dev/random”. With some virtual environments hardware RNG may
never be available, in that case it is important to find other ways of making entropy available to your JVM. Ways of doing this will vary with the environment you are using.
I might be misunderstanding what this excerpt is saying, but how exactly can I make entropy available to the JVM? The book isn't very specific about this other than stating that the "Ways of doing this will vary with the environment you are using". Is there some kind of Entropy SPI that I am unaware of which can be used to make a source of entropy available to the JVM? My question isn't how to generate entropy or retrieve it from the JVM, but rather, if I already know of and have access to a reliable source of entropy (Such as a file of random bits) how can I make this source of entropy available to the JVM so that it may be used for seeding in cases where other secure sources of entropy are unavailable?
This may vary depending on the JVM vendor but as per
Avoiding JVM Delays Caused by Random Number Generation for Sun/Oracle JVM one can set securerandom.source property in $JAVA_HOME/jre/lib/security/java.security file. This allows to change the source of entropy e.g. from /dev/random to /dev/urandom.
To add more entropy one can simply write to /dev/random. As per this answer this can potentially not be secure but:
It is also possible to write to /dev/random. This allows any user to mix random data into the pool.
I don't think your quote is an accurate reflection of at least the Oracle JVM. Here is the Javadoc for the NativePRNG class that is normally chosen by default.
public final class NativePRNG extends java.security.SecureRandomSpi
Native PRNG implementation for Solaris/Linux/MacOS. It obtains seed
and random numbers by reading system files such as the special device
files /dev/random and /dev/urandom. This implementation respects the
securerandom.source Security property and java.security.egd System
property for obtaining seed material. If the file specified by the
properties does not exist, /dev/random is the default seed source.
/dev/urandom is the default source of random numbers.
On some Unix platforms, /dev/random may block until enough entropy is
available, but that may negatively impact the perceived startup time.
By selecting these sources, this implementation tries to strike a
balance between performance and security.
As you can see, /dev/urandom and not /dev/random is the default source of entropy.
I'm a bit new to cryptography and i'm wondering why there is a Limit for the Key size in Java?
It's only possible to use bigger Keys with especially installing the unlimited strength jurisdiction policy file...
Basically because of politics. USA had an export restriction on encryption stronger than 40-bits back in the days, and even these days some governments don't allow strong encryption.
Oracle can distribute the default weak JCE version without being blocked by backwards governments, and make the policy files available as needed (those can then be blocked by the backwards governments).
My use case involves encrypting large amounts of sensitive data on the order of petabytes using AES with GCM in Java and I will need high throughput to make that task complete in reasonable time.
As was previously asked and answered on here, AES/GCM is still severely crippled in the latest JDK 8 (~17MB/s on my hardware). I'm happy to know that JEP 246 for adding significant hardware acceleration for GCM made it onto the roadmap for Java 9, however General Availability for the next major Java release has been pushed out to over a year away as of me writing this.
So far the fastest implementation I have found is the Bouncy Castle Provider, with no hardware acceleration and throughput on the order of 170MB/s. I know that my hardware supports acceleration by running benchmarks of the native libraries GnuTLS (gnutls-cli --benchmark-ciphers) and OpenSSL (openssl speed -evp aes-128-gcm), both clocking in at over 2GB/s for AES/GCM. Unfortunately I can't find a current Java wrapper around either of these. The closest I've come across is Apache JuiCE, built on OpenSSL, but it was abandoned over 8 years ago.
Has anyone come across a JCE Provider that supports hardware acceleration for AES/GCM that I could use in the near term, either commercial or open source?
Netty-tcnative provides an alternative SSL engine using JNI to interface with native OpenSSL. You should be able to access the crypto functions directly in a similar way. That said, JEP 246: Leverage CPU Instructions for GHASH and RSA is now part of Java 9, so you should be able to get similar performance without resorting to native code.
Why do people use bouncycastle instead of Java Cryptography Extension? What is the difference?
BouncyCastle has many more cipher suites and algorithms than the default JCE provided by Sun.
In addition to that, BouncyCastle has lots of utilities for reading arcane formats like PEM and ASN.1 that no sane person would want to rewrite themselves.
Bouncy Castle is Australian in origin, and therefore is not subject to the Export of cryptography from the United States.
It is useful if you are outside the United States and you need to manage key sizes grater than permitted by such that restriction. In that case you are not permitted to use software from United States for that.
On server or desktop, I don't see any reason to use BC unless you have to deal with some legacy ciphers or formats not supported by Sun JCE.
However, many JREs don't come with a JCE provider, like on mobile or embedded environments. BC comes handy in such cases.
I am looking for open source JCE libraries that implement some of the more esoteric encryption algorithms so that I can study their implementation. I would be especially interested in ones that implement Identity Based Encryption (IBE) as published by Stanford.
Cryptix (not sure what state its in at the moment but it was high quality when I used it last):
http://www.cryptix.org
http://sourceforge.net/projects/cryptix
GNU Classpath also has their own JCE implementation, however, whether they support IBE is another story.