I'm setting up a development environment on an ARM machine, with the following versions of Java and Maven, both installed via apt-get
:
(xenial)craig@localhost:~$ mvn -version
Apache Maven 3.3.9
Maven home: /usr/share/maven
Java version: 1.8.0_91, vendor: Oracle Corporation
Java home: /usr/lib/jvm/java-8-openjdk-armhf/jre
Default locale: en_US, platform encoding: ANSI_X3.4-1968
OS name: "linux", version: "3.14.0", arch: "arm", family: "unix"
(xenial)craig@localhost:~$ java -version
openjdk version "1.8.0_91"
OpenJDK Runtime Environment (build 1.8.0_91-8u91-b14-0ubuntu4~16.04.1-b14)
OpenJDK Zero VM (build 25.91-b14, interpreted mode)
However, when I run a mvn clean install
on my project, it fails attempting to download a POM file that does exist. (I can visit it in my browser.)
The stacktrace is quite large, but the root seems to be:
Caused by: java.lang.IllegalStateException
at sun.security.ec.ECDHKeyAgreement.deriveKey(Native Method)
at sun.security.ec.ECDHKeyAgreement.engineGenerateSecret(ECDHKeyAgreement.java:130)
at sun.security.ec.ECDHKeyAgreement.engineGenerateSecret(ECDHKeyAgreement.java:163)
at javax.crypto.KeyAgreement.generateSecret(KeyAgreement.java:648)
at sun.security.ssl.ECDHCrypt.getAgreedSecret(ECDHCrypt.java:101)
at sun.security.ssl.ClientHandshaker.serverHelloDone(ClientHandshaker.java:1067)
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:348)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:979)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:914)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403)
There unfortunately isn't much more to it - Maven fails with:
Caused by: org.eclipse.aether.resolution.ArtifactDescriptorException: Failed to read artifact descriptor for org.jacoco:jacoco-maven-plugin:jar:0.7.6.201602180812
And the stack ends with the exception thrown in deriveKey()
. Am I missing some crypto library on my machine?
This is a fresh install of Xenial (16.04 LTS).
While installing the Oracle JRE is the easy way out, here are the instructions in case you want to use the OpenJDK Zero VM specifically, be it with Maven, SSL, the ECDH key agreement or any other crypto method that's implemented in native code in the OpenJDK default crypto provider.
I've assumed that the
ECDHKeyAgreement.deriveKey
method fails because it is a native method and the OpenJDK Zero VM as packaged in Ubuntu for Raspberry Pi just can't handle it; I'm not equipped to debug that failure.Ubuntu packages the BouncyCastle crypto provider which is implemented in pure Java. You need to install it the usual way:
(this also installs the docs)
Then follow the instructions in
/usr/share/doc/libbcprov-java/README.Debian
to make it the default crypto provider. Specifically, you need to make a link to the provider jar from the ext directory of the JRE, so do aupdate-java-alternatives -l
followed by (in my case - I've been using the defaults provided in Ubuntu 16.04 Raspberry Pi server install - the specific JRE directory may change in time):Then edit the
/usr/lib/jvm/java-1.8.0-openjdk-armhf/jre/lib/security/java.security
file (invoking the editor withsudo
), adding the line:...where the crypto providers are listed, and adding 1 to the priority of the ones already there, so that the list looks similar to this:
Crypto in Java should now work, albeit very slowly. Here's an example program I've used to confirm that it does, if you don't want to use Maven for that:
Point it at any https URL (e.g.
java URLGet https://www.google.com/
) to confirm that Java can handle SSL.