用NDK调用Android手机自带的openssl库函数

目标: 目前很多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);

你可能感兴趣的:(Android)