How to use ECC with OpenJDK
Everyone who ever tried to use Elliptic Curve Cryptography (ECC) in Java with an OpenJDK was either forced to use Bouncy Castle or fumble with the SunEC provider. The SunEC provider offers the following algorithms according to the documentation (quote):
AlgorithmParameters | EC |
KeyAgreement | ECDH |
KeyFactory | EC |
KeyPairGenerator | EC |
Signature | NONEwithECDSA SHA1withECDSA SHA256withECDSA SHA384withECDSA SHA512withECDSA |
Unfortunately, this provider is not shipped with OpenJDK. But anyone who really would like to try the Java builtin ECC functionility would possibly try to simply add the sunec.jar (which contains the provider) to the jre/lib/ext/ folder. But, when trying to use the provider these guys will definitely rub their eyes in amazement. Things are different than they seem at first…
Let’s assume we added the library to the correct folder, our OpenJDK notices it and we could successfully compile the following code without any exceptions:
package eccprovidertest; import java.security.Provider; import java.security.Provider.Service; import java.security.Security; import sun.security.ec.SunEC; /** * ECC Provider Test. * @author Christopher Meyer - christopher.meyer@rub.de * @version 0.1 * Oct 23, 2013 */ public class ECCProviderTest { /** * @param args the command line arguments */ public static void main(final String[] args) { Provider sunEC = new SunEC(); Security.addProvider(sunEC); for(Service service : sunEC.getServices()) { System.out.println(service.getType() + ": " + service.getAlgorithm()); } } }
If we finally run it with an OpenJDK (java version “1.7.0_25”) we get the following output:
KeyFactory: EC AlgorithmParameters: EC
Wow! This is not a very useful provider….. Where are the promised algorithms? Let’s try to run the code, just for fun, with the Oracle JDK:
KeyFactory: EC AlgorithmParameters: EC Signature: NONEwithECDSA Signature: SHA1withECDSA Signature: SHA256withECDSA Signature: SHA384withECDSA Signature: SHA512withECDSA KeyPairGenerator: EC KeyAgreement: ECDH
Surprise, surprise! That’s the moment when you start rubbing your eyes! Here are the algorithms, but why are they only available when using the Oracle JDK?
The reason for this is hidden in the provider’s code. The following lines are taken from sun.security.ec.SunEC:
private static final long serialVersionUID = -2279741672933606418L; // flag indicating whether the full EC implementation is present // (when native library is absent then fewer EC algorithms are available) private static boolean useFullImplementation = true; static { try { AccessController.doPrivileged(new PrivilegedAction() { public Void run() { System.loadLibrary("sunec"); // check for native library return null; } }); } catch (UnsatisfiedLinkError e) { useFullImplementation = false; } } public SunEC() { super("SunEC", 1.7d, "Sun Elliptic Curve provider (EC, ECDSA, ECDH)"); // if there is no security manager installed, put directly into // the provider. Otherwise, create a temporary map and use a // doPrivileged() call at the end to transfer the contents if (System.getSecurityManager() == null) { SunECEntries.putEntries(this, useFullImplementation); } else { Map<Object, Object> map = new HashMap<Object, Object>(); SunECEntries.putEntries(map, useFullImplementation); AccessController.doPrivileged(new PutAllAction(this, map)); } }
Additionally, the following can be found in SunECEntries class, after some entries have been added to the list:
/* * Register the algorithms below only when the full ECC implementation * is available */ if (!useFullImplementation) { return; }
Ok, this explains the behaviour. The algorithms are only present if a native library could be successfully loaded (either libsunec.so or sunec.dll on Windows machines). This library is obviously missing in our case (since we only copied the sunec.jar file).
Unfortunately, if we had read the provider documentation we would know about that:
“[…] The Java classes are packaged into the signed sunec.jar in the JRE extensions directory and the C++ and C functions are packaged into libsunec.so or sunec.dll in the JRE native libraries directory. If the native library is not present then this provider is registered with support for fewer ECC algorithms (KeyPairGenerator, Signature and KeyAgreement are omitted).”
Unfortunately, it was our own, hasty zest for action which has cost us valuable time of our developer-life. Take away: Reading JavaDocs is sometimes really helpful….(, but not as educative as the painstaking debugging).