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).
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.
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.
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 need to store some sensitive data by encrypting it with atleast 128 bit key. I investigated into javax.crypto package and found that there are certain Cipher names, like
PBEWithMD5AndDES or PBEWithSHA1AndDESede which provides encryption upto 56 bit and 80 bit (http://en.wikipedia.org/wiki/DESede).
I referred other guys posts but those are mainly using RSA and in my understanding RSA is generally suitable for encrypting the communication data (with private-public key pair). My need is different, I just want to store the data and retrieve it back by decrypting it. Therefore I don't need any private-public key pairs.
Please let me know if you have any idea about this.
Use Advanced Encryption Standard (AES). It supports Key lengths of 128, 192, or 256 bits.
The algorithm is simple. The Sun Java website has a section explaining how to do AES encryption in Java.
From Wikipedia...
... the Advanced
Encryption Standard (AES), also known
as Rijndael, is a block cipher adopted
as an encryption standard by the U.S.
government. It has been analyzed
extensively and is now used worldwide,
as was the case with its
predecessor, the Data Encryption
Standard (DES)...
So as a rule of thumb you are not supposed to use DES or its variants because it is being phased out.
As of now, it is better to use AES. There are other options like Twofish, Blowfish etc also. Note that Twofish can be considered as an advanced version of Blowfish.
I have had good success in the past with http://www.bouncycastle.org/ (they have a C# version as well).
You need to download and install the unlimited strength JCE policy file for your JDK. For JDK 6, it is on http://java.sun.com/javase/downloads/index.jsp at the very bottom.
Combining 3 different replies gives what I think is the correct answer.
Download encryption libraries from Bouncycastle then you need to download the "Unlimited Strength Jurisdiction Policy" from Oracle (the files are at the bottom of the download page). Make sure you read the Readme-file on how to install it.
Once you have done this, and using the sample code supplied with the Bountycastle package you should be able to encrypt your data. You can go with a tripple DES implementation, which will give you 112 bits key (often referred to as 128 bit, but only 112 of them are actually secure), or as previously stated, you can use AES. My money would be on AES.
I'm not a crypto expert by any means (so take this suggestion with a grain of salt), but I have used Blowfish before, and I think you can use it for what you need. There is also a newer algorithm by the same guy called Twofish.
Here is a website with a Java implementation, but be careful of the license (it says free for non-commercial use). You can find that link also from Bruce Schneier's website (the creator of both algorithms).
Thanks Michael, after trying out many things in JCE, I finally settled for bouncycastle.
JCE supports AES for encryption and PBE for password based encryption but it does not support combination of both. I wanted the same thing and that I found in bouncycastle.
The example is at : http://forums.sun.com/thread.jspa?messageID=4164916