在Android应用中为HttpClient更改OpenSSL库

我需要在我的项目中为HttpClient使用自定义OpenSSL库。

我为Android编译了libcrypto.solibssl.so ,并将文件放在jniLibs文件夹中。 应用Heartbleed扫描仪看到它们。 System.loadLibrary("crypto")System.loadLibrary("ssl")有效。 但现在我需要让HttpClient使用我的库而不是标准的SSL库。 但我不知道哪种方式可以移动以及如何移动。

我使用的是OpenSSL 1.0.1h和Android Studio 1.0.2。

提前感谢您的建议。

我为Android编译了libcrypto.so和libssl.so,并将文件放在jniLibs文件夹中……

这不行。

Android使用OpenSSL 1.0.0并在/system 。 Zygote在启动时启动并加载低级版本的OpenSSL(它类似于init – 所有Android进程都是从它分叉的)。

当您的进程从Zygote分叉时,您的1.0.1版本永远不会加载,因为已经从Zygote加载了1.0.0。 你永远不会知道有问题,因为低级版本提供了你需要的所有符号(它的二进制兼容)。

您需要编写包装器共享对象。 包装器共享对象必须链接到OpenSSL 1.0.1的静态版本( libcrypto.alibssl.a )。 您的包装器必须导出唯一的符号,例如My_OpenSSL_add_all_algorithmsMy_SSL_load_error_strings 。 在内部,您的共享对象可以引用未修饰的名称, OpenSSL_add_all_algorithmsSSL_load_error_strings

所以你的共享对象看起来是这样的(另见GCC的Visibility页面 ):

 #if __GNUC__ >= 4 #define DLL_PUBLIC __attribute__ ((visibility ("default"))) #define DLL_LOCAL __attribute__ ((visibility ("hidden"))) #else #define DLL_PUBLIC #define DLL_LOCAL #endif DLL_PUBLIC void My_OpenSSL_add_all_algorithms() { return (void)OpenSSL_add_all_algorithms(); } DLL_PUBLIC void My_SSL_load_error_strings() { return (void)SSL_load_error_strings(); } ... 

然后,使用-fvisibility=hidden标志进行编译,并链接libcrypto.alibssl.a 。 只有标有DLL_PUBLIC的函数才能通过JNI导出和调用。

我认为不需要#if __GNUC__ >= 4 ,因为Android提供的交叉编译工具是GCC 4.0以上。 事实上,我认为它目前是GCC 4.8。


在Android应用中为HttpClient更改OpenSSL库

这个问题更难了。 在共享包装器中提供更新的OpenSSL之后,我不知道如何让Android的HttpClient使用它。

更糟糕的情况回答:你可能需要派Android并提供更新的OpenSSL。

一个可能更好的解决方案:删除HttpClient代码,将其放在您自己的包中,然后确保源代码的端口使用共享对象。