SQLCipher 3.3.1-2 aar does not create .so files for x64 architecture

Hi,
I am using SQLCipher in my android app project (in Android Studio 2.0 preview) by adding following line in dependencies -
compile 'net.zetetic:android-database-sqlcipher:3.3.1-2@aar'

I am a medical doctor, and have very restricted information about programming. After going through many tutorials available on net / stackoverflow questions, I decided to work with NDK to secure password string of my pre-populated database encrypted with SQLCipher. (I know, this might be a childish way to secure string for you people, but this is the only thing, I could learn to protect my string which has to be on device for offline use, given my background is purely Medical / Non-programming.)
Anyways, using NDK, I created settings-jni.c file in my jni folder, which has following code -

#include <jni.h>
JNIEXPORT jstring JNICALL
Java_in_medicalguru_database_DBHelper_getDBPwd(JNIEnv *env, jobject instance) {
    return (*env)->NewStringUTF(env, "my_password_string");
}

In my DBHelper.java file I am getting my password as follows -

public  String DB_PASSWORD = getDBPwd();
static {
  System.loadLibrary("settings-jni");
}
public native String getDBPwd();

My app compiles fine (for the record, I am making universal app for all architecture, I am yet to learn to make app targeting specific architecture) and runs perfect on many devices I tested, e.g. Samsung Galaxy Grand, OnePlus One, Moto G2 etc. I also tested it on Emulator using “Visual Studio Emulator for Android”, because it works faster on my Windows 10 laptop.

Now comes the actual problem part. Recently, some of my user reported, that my app is continuously crashing soon after starting. On investigation, I found that these users are using x64 architecture mobiles. One of user also said that, earlier version of my app (which did not use NDK to encrypt password string), was working fine for him.

Here is the error log I received in my Google Play Developer Console -

java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/in.medicalguru-1/base.apk"],nativeLibraryDirectories=[/data/app/in.medicalguru-1/lib/arm64, /vendor/lib64, /system/lib64]]] couldn't find "libstlport_shared.so"
	at java.lang.Runtime.loadLibrary(Runtime.java:366)
	at java.lang.System.loadLibrary(System.java:988)
	at net.sqlcipher.database.SQLiteDatabase.loadLibs(Unknown Source)
	at net.sqlcipher.database.SQLiteDatabase.loadLibs(Unknown Source)
	at in.medicalguru.MainActivity.a(Unknown Source)
	at in.medicalguru.MainActivity.onCreate(Unknown Source)
	at android.app.Activity.performCreate(Activity.java:5990)
	at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)
	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2311)
	at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2420)
	at android.app.ActivityThread.access$900(ActivityThread.java:154)
	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1321)
	at android.os.Handler.dispatchMessage(Handler.java:102)
	at android.os.Looper.loop(Looper.java:135)
	at android.app.ActivityThread.main(ActivityThread.java:5292)
	at java.lang.reflect.Method.invoke(Native Method)
	at java.lang.reflect.Method.invoke(Method.java:372)
	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:904)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:699)

So I unzipped both versions of my app, and checked the list of libraries. I am attaching the screenshot of library structure of my final (unzipped) app, which uses NDK -

In this I noticed the difference that, because of me using the NDK, 4 folders are created extra - arm64-v8a, mips, mips64 and x86_64. These folders do NOT contain SQLCipher’s .so files. So as per my knowledge (I am saying again that I may be very wrong, but please correct me, if I am) this might be causing the app to crash on x64 mobiles,

If I am correct in diagnosing the cause of app crash, how can I correct it? There are two possible scenarios I could think of (but don’t know how to apply them) -

  1. Either include SQLCipher’s .so files for the mentioned 4 folders
  2. Or to restrict making .so files from my settings-jni.c file, for the mentioned 4 architectures.

I am completely clueless here, and stuck since days,
Any help would be appreciated.
[P.S. - I am really sorry for the long post, but I think, it was necessary to explain my problem.]

Thanks.
Regards,
Dr, Atul Tiwari

Hello @dr.atul

Thank you for your interest in SQLCipher.

Yes, Android uses a preferential loading routine for resolving native dependencies. On devices where SQLCipher for Android has not been built to target, such as arm64-v8a, mips, mips64, and x86_64, it will attempt to load all native libraries from the corresponding platform folder causing a runtime error you reported above due to the libraries being missing for that specific architecture.

One solution to this when using SQLCipher for Android is to only package your other 3rd party native libraries for the platforms that SQLCipher for Android support (i.e., armeabi, armeabi-v7a, and x86). Note, this will preclude your application from running on the MIPS platform, however should allow the application to run on various ARM and x86 derivative platforms. For example, on an arm64-v8a device, if no native libraries are provided for that platform, it will attempt to load the libraries from either the armeabi or armeabi-v7a folder instead.

N.B. Compiling the password to the encrypted database directly into a library or application is highly discouraged, extracting the password for the binary is a trivial process, thus limiting the level of security your application provides.

Hello @developernotes

Thank you for your prompt reply.

The same thing I thought, as mentioned in 2 of the suggested solutions in my original post. But at the time of asking this question, I was unaware of abiFilters command (I just learned about it). Now, I am trying to limit my 3rd party native libraries only 3 platforms supported by SQLCipher, with abiFilters.

N.B. - On the side-note, yes I am aware of the fact that binaries can disassembled very easily and retrieving password in binaries is very trivial process. But even after a lot of google search, I couldn’t find a better way - Where/How to store password string safely of a pre-populated encrypted database, without requiring any net connection. (my database is already 15 MB and growing, so I cant make it dynamically at installation time).
Only other way I could think of is to get password by api from web on 1st installation of app, and then save it in preferences for future use (when there is no net connection to retrieve password from net). But will it be more secure than using binaries? I have no idea.

Or can you provide a link or any idea about - How to secure password for offline use? (should I ask it as a separate question?)

Thanks.

Key management can be a challenging aspect to application development, often driven by the security requirements of your application. We touch on database key material and selection here.

@dr.atul You able to get solution for this. Even after to keep only three architecture-folder I’m facing same issue. Beside to use SQLCipher I’m using Temasys lib, they also support these. But same error I’m getting mentioned by @dr.atul.

Please Update.

But it does not work with card.io library, https://github.com/card-io/card.io-Android-SDK. Because Card.IO is built for working on arm64-v8a. If you remove this folder, it will not working.

Hi @vanhung1710

SQLCipher for Android does not include native libraries for 64-bit CPU’s, however will work on those devices with appropriate adjustments. Please take a look at this post for more details. Thanks!

The problem is that when we use CardIO on Samsung Galaxy S6 or S7, you must
include arm64-v8a then CardIO will work. But when we use CardIO with
SQLiteCipher, app will crash because of missing SQLite Cipher arm64-v8a. If
we remove arm64-v8a folder then CardIO does not work.