I'm trying to use the libsodium crypto library (a portable version of NaCl (nacl.cr.yp.to)) on Android but I can't figure out how to properly compile/use the Kalium-JNI language binding.
So far I successufully compiled libsodium as described on the libsodium website. In addition, I used the new android-arm compile script added 3 days ago. As a test I compiled the android-x86 version as well to compare the file sizes of the resulting library files. They differ so this seems to be working. As a next step I installed KaliumJNI using the newly generated android-arm libsodium files. No problems here.
In my little android-maven test application which basically is a "Hello World" archetype I'm simply trying to generate a new keypair:
import org.abstractj.kalium.keys.KeyPair;
KeyPair Alice = new KeyPair();
IntelliJ succesfully compiled my little program but when I try to run it on my emulator (or on my Nexus S) it crashes. First it crashed because it wasn't able to find the kaliumjni library so I added libtestjni.so (which is the .so library generated by KaliumJNI) to my project properties which fixed this problem. The next error message I got told me that libtestjni.so is not 32bit (I'm running a 64bit Ubuntu 12.04LTS). I don't see why it has to be 32bit but anyway I managed to set up a 32bit Ubuntu 12.04LTS VM and compiled android-arm libsodium and KaliumJNI again to generate a 32bit libtestjni.so file. But when I use this 32bit file in my original application (on my 64bit machine) I receive the following error:
java.lang.IllegalStateException: Could not execute method of the activity
at android.view.View$1.onClick(View.java:3823)
at android.view.View.performClick(View.java:4438)
at android.view.View$PerformClick.run(View.java:18422)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5017)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at android.view.View$1.onClick(View.java:3818)
at android.view.View.performClick(View.java:4438)
at android.view.View$PerformClick.run(View.java:18422)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5017)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.UnsatisfiedLinkError: dlopen failed: "/data/app-lib/IM.CRYPTO-1/libtestjni.so" has unexpected e_machine: 3
at java.lang.Runtime.loadLibrary(Runtime.java:364)
at java.lang.System.loadLibrary(System.java:526)
at org.abstractj.kalium.NaCl.<clinit>(NaCl.java:36)
at org.abstractj.kalium.keys.KeyPair.<init>(KeyPair.java:36)
at IM.CRYPTO.HelloAndroidActivity.buttonClick(HelloAndroidActivity.java:43)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at android.view.View$1.onClick(View.java:3818)
at android.view.View.performClick(View.java:4438)
at android.view.View$PerformClick.run(View.java:18422)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5017)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
at dalvik.system.NativeStart.main(Native Method)
I've spent hours to get to this point but right now I'm clueless where I should go from here. It seems that e_machine: 3 stands for some kind of architecture issue but I can't figure out where I went wrong. The application is compiled for Android 4.0 (Android API 14) and the emulator is configured to use arm and the same API 14 as well (The Nexus phone runs CM with Android 4.3.1). As mentioned before libsodium was compiled for arm as well.
Some more information:
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>IM.CRYPTO</groupId>
<artifactId>cryptolibAndroid</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>apk</packaging>
<name>cryptolibAndroid</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<platform.version> 4.0.1.2
</platform.version>
<android.plugin.version>3.6.0</android.plugin.version>
</properties>
<dependencies>
<dependency>
<groupId>com.google.android</groupId>
<artifactId>android</artifactId>
<version>${platform.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.abstractj.kalium</groupId>
<artifactId>kalium-jni</artifactId>
<version>1.0.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<pluginManagement>
<plugins>
<plugin>
<groupId>com.jayway.maven.plugins.android.generation2</groupId>
<artifactId>android-maven-plugin</artifactId>
<version>${android.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<undeployBeforeDeploy>true</undeployBeforeDeploy>
<attachJar>true</attachJar>
</configuration>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>com.jayway.maven.plugins.android.generation2</groupId>
<artifactId>android-maven-plugin</artifactId>
<configuration>
<sdk>
<platform>14</platform>
</sdk>
</configuration>
</plugin>
</plugins>
</build>
NaCl.java
(this class gets called to load testjni (KaliumJNI))
package org.abstractj.kalium;
public class NaCl {
public static Sodium sodium() {
return SingletonHolder.SODIUM_INSTANCE;
}
private static final String LIBRARY_NAME = "sodium";
private static final class SingletonHolder {
public static final Sodium SODIUM_INSTANCE = new Sodium();
}
private NaCl() {
}
static {
System.loadLibrary("testjni");
}
}
I'm grateful for any hints to point me into the right direction.
Please note that I have a little JAVA desktop application as well which uses libsodium + Kalium (NOT KaliumJNI) and runs without any problems.