在android项目中使用libcryto.so和libssl.so?

时间:2014-03-20 11:21:14

标签: android android-ndk openssl java-native-interface

我开始使用Android NDK。我想基于openssl libary构建一个RSA示例。 首先,我在guardianproject中使用ndk-build构建了libssl.so和libcrypto.so库。 接下来,我创建了一个新的示例项目来集成libary(libss.so& lybcryto.so)。我在post

中也遵循相同的规定

我的应用目录

TrialApp
|
|-->Activity.java (includes System.LoadLibrary calls)
|
|-->jni
    |-->TestJNI2.cpp
    |
    |-->Android.mk
    |
    |-->includes
    |   |
    |   |-->openssl (dir containing *.h files)
    |
    |-->precompiled
       |-->libssl.so
       |-->libcrypto.so

我的android.mk:

LOCAL_PATH := $(call my-dir)

# Prebuilt libssl
include $(CLEAR_VARS)
LOCAL_MODULE := ssl
LOCAL_SRC_FILES := precompiled/libssl.so
include $(PREBUILT_SHARED_LIBRARY)

# Prebuilt libcrypto
include $(CLEAR_VARS)
LOCAL_MODULE := crypto
LOCAL_SRC_FILES := precompiled/libcrypto.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)

c_includes := $(LOCAL_PATH)
cf_includes := includes/openssl

cf_includes := $(addprefix -Ijni/,$(cf_includes))

export_c_includes := $(c_includes)

LOCAL_MODULE := security
LOCAL_SRC_FILES := TestJNI2.cpp
LOCAL_CFLAGS += $(cf_includes)
LOCAL_EXPORT_C_INCLUDES := $(export_c_includes)
LOCAL_LDLIBS := -llog
LOCAL_LDLIBS += $(LOCAL_PATH)/precompiled/libssl.so
LOCAL_LDLIBS += $(LOCAL_PATH)/precompiled/libcrypto.so

include $(BUILD_SHARED_LIBRARY)

TestJNI2.cpp

/* OpenSSL headers */

#include "openssl/bio.h"
#include "openssl/ssl.h"
#include "openssl/err.h"

/* Initializing OpenSSL */

void init_openssl(void){
    SSL_load_error_strings();
    ERR_load_BIO_strings();
    OpenSSL_add_all_algorithms();
}

然后,当我使用ndk-build构建时,总会遇到类似这样的问题

/data/workspace/TestJNI2/jni/TestJNI2.cpp:3:25: error: openssl/bio.h: No such file or directory
/data/workspace/TestJNI2/jni/TestJNI2.cpp:4:25: error: openssl/ssl.h: No such file or directory
/data/workspace/TestJNI2/jni/TestJNI2.cpp:5:25: error: openssl/err.h: No such file or directory
/data/workspace/TestJNI2/jni/TestJNI2.cpp: In function 'void init_openssl()':
/data/workspace/TestJNI2/jni/TestJNI2.cpp:10: error: 'SSL_load_error_strings' was not declared in this scope
/data/workspace/TestJNI2/jni/TestJNI2.cpp:11: error: 'ERR_load_BIO_strings' was not declared in this scope
/data/workspace/TestJNI2/jni/TestJNI2.cpp:12: error: 'OpenSSL_add_all_algorithms' was not declared in this scope
make: *** [/data/workspace/TestJNI2/obj/local/armeabi/objs/security/TestJNI2.o] Error 1

任何人都可以帮助我吗?或者如何在openssl lib上构建一个示例RSA algorthim?

2 个答案:

答案 0 :(得分:6)

您应该在脚本中为libssl和libcrypto构建静态库。如果不能,请重命名这些库(您可以在构建之后执行此操作,同时复制到precompiled目录)。原因是系统自带(可能是不同的)这些共享库版本,加载器将使用/system/lib/libssl.so/system/lib/libcrypto.so而不是您的私有副本。

关于 Android.mk 文件,我稍微为您清理了一下(请注意,我没有更改预建的 LOCAL_MODULE 的名称,但更改了名称 LOCAL_MODULE 你最终构建了,因为security太通用了,也可能碰巧匹配某个设备上的系统库):

LOCAL_PATH := $(call my-dir)

# Prebuilt libssl
include $(CLEAR_VARS)
LOCAL_MODULE := ssl
LOCAL_SRC_FILES := precompiled/libPrivateSsl.so
include $(PREBUILT_SHARED_LIBRARY)

# Prebuilt libcrypto
include $(CLEAR_VARS)
LOCAL_MODULE := crypto
LOCAL_SRC_FILES := precompiled/libPrivateCrypto.so
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)

LOCAL_MODULE := PrivateSecurity
LOCAL_C_INCLUDES := includes
LOCAL_SRC_FILES := TestJNI2.cpp
LOCAL_LDLIBS := -llog
LOCAL_SHARED_LIBRARIES := ssl crypto

include $(BUILD_SHARED_LIBRARY)

不要忘记你的Java应该首先加载依赖项:

{
    System.loadLibrary("PrivateSsl");
    System.loadLibrary("PrivateCrypto");
    System.loadLibrary("PrivateSecurity");
}

答案 1 :(得分:4)

  

我是Android NDK的初学者。我想基于openssl libary构建一个RSA示例。

你可以,但你必须要小心。以下是Alex告诉您在脚本中为libssllibcrypto使用静态库的原因。

主Android进程为zygote。它与Linux中的init类似。 Zygote在启动时加载OpenSSL,并加载版本0.9.8。如果你链接到OpenSSL 1.0.1,那么你将得到神秘的运行时崩溃。崩溃是由于Android加载器使用的是0.9.8版本的库(已经从Zygote映射),而不是你的OpenSSL版本。

可以使用共享对象,但您的共享对象必须是libssllibcrypto静态版本的包装。

如果您使用Android的构建系统,那么您可以在OpenSSL的wiki上找到纯粹从命令行构建的其他说明。 Wiki页面包括设置envrionment和交叉编译。请参阅FIPS Library and Android

需要注意的另一件事是:务必使用-mfloat-abi=softfp进行构建。股票OpenSSL在交叉编译时错过了。您需要它来确保浮点数在堆栈上传递,并且通过浮点寄存器。否则,你的所有浮点数都会神秘地具有0.0f值(就像RAND_add中用于估计熵的浮点数一样。)