目标: 目前很多Android手机已经自带了openssl库, 即libssl.so, libcrypto.so, 以下示例实现了APK通过NDK调用openssl库函数PKCS5_PBKDF2_HMAC(密钥生成算法)
1) 在android工程中创建 jni目录
2) 编辑AbcJni.java
package com.example;
public class AbcJni
{
public native byte[] hashKey(byte[] key, byte[] salt, int count);
static {
System.loadLibrary("abc-jni");
}
}
3) 编译成功(生成AbcJni.java, 例如在bin目录下), 利用AbcJni.class生成
javah -classpath bin/classes -d jni com.example.AbcJni
这样会在jni目录下生成一个com_example_AbcJni.h文件
4) 新建abc-jni.c文件, 实现上述的头文件函数
#include
#include
#include
#include
JNIEXPORT jbyteArray JNICALL Java_com_example_AbcJni_hashKey
(JNIEnv *env, jobject thiz, jbyteArray pass, jbyteArray salt, jint count)
{
jbyte* pJbytePass = (*env)->GetByteArrayElements(env, pass, NULL);
char* szBytePass = (char *)pJbytePass;
int iLenPass = (*env)->GetArrayLength(env, pass);
jbyte* pJbyteSalt = (*env)->GetByteArrayElements(env, salt, NULL);
char* szByteSalt = (char *)pJbyteSalt;
int iLenSalt = (*env)->GetArrayLength(env, salt);
int OUTSIZE = 64;
char buf[64];
memset( buf, 0, sizeof(buf) );
PKCS5_PBKDF2_HMAC(
szBytePass,
iLenPass,
szByteSalt,
iLenSalt,
count, EVP_sha512(), OUTSIZE, buf);
jbyteArray jarray = (*env)->NewByteArray(env, OUTSIZE);
(*env)->SetByteArrayRegion(env, jarray, 0, OUTSIZE,buf);
(*env)->ReleaseByteArrayElements(env, pass, pJbytePass, 0);
(*env)->ReleaseByteArrayElements(env, salt, pJbyteSalt, 0);
return jarray;
}
4) 编辑Android.mk, 文件, 内容如下:LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := abc-jni
LOCAL_SRC_FILES := abc-jni.c
LOCAL_LDLIBS := -lcrypto -lssl
include $(BUILD_SHARED_LIBRARY)
5) 下载一个最新的openssl源代码, 解压. 假如解压后目录为/my/src/openssl-1.0.1k/
注: Android的SDK/NDK目录并没有openssl相关的头文件及库文件, 所以我们需要从源码中获取头文件
6) 进入ndk中以下目录(我使用android 4.4, platform 19), 建立头文件目录的软链接
cd /opt/android-ndk/platforms/android-19/arch-arm/usr/include
ln -s /my/src/openssl-1.0.1k/include/openssl .
7) 从你的手机拷贝以下文件(在/system/lib, 需要root哦)到ndk的lib目录下:
例如, 我的手机如下:
[my]# pwd
/system/lib
[my]# ls -la libcrypto.so libssl.so
-rw-r--r-- root root 1249844 2013-02-09 03:36 libcrypto.so
-rw-r--r-- root root 224784 2013-02-09 03:36 libssl.so
ndk的目录是:
/opt/android-ndk/platforms/android-19/arch-arm/usr/lib
8) 回到你的android工程
cd jni
ndk-build
如果成功, 你会发现../libs目录多了一个子目录, 及libabc-jni.so文件
9) 最后你可以在你的Android java代码中调用AbcJni.java中的以下方法了:
byte[] hashKey(byte[] key, byte[] salt, int count);