我需要在项目中为 HttpClient 使用自定义OpenSSL库。
我为Android编译了 libcrypto.so 和 libssl.so ,并将文件放在jniLibs文件夹中。应用Heartbleed扫描仪看到它们。 System.loadLibrary("crypto")
和System.loadLibrary("ssl")
有效。
但现在我需要让 HttpClient 使用我的库而不是标准的SSL库。但我不知道哪种方式移动以及如何移动。
我使用的是OpenSSL 1.0.1h和Android Studio 1.0.2。
提前感谢您的建议。
答案 0 :(得分:1)
我为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.a
和libssl.a
)。您的包装器必须导出唯一的符号,例如My_OpenSSL_add_all_algorithms
和My_SSL_load_error_strings
。在内部,您的共享对象可以引用未修饰的名称OpenSSL_add_all_algorithms
和SSL_load_error_strings
。
所以你的共享对象看起来如此(也见GCC的Visibility page):
#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.a
和libssl.a
。只有标有DLL_PUBLIC
的函数才能通过JNI导出和调用。
我认为不需要#if __GNUC__ >= 4
因为Android提供的交叉编译工具是上面的GCC 4.0。事实上,我认为它目前是GCC 4.8。
在Android应用中为HttpClient更改OpenSSL库
这个问题更难解决。在共享包装器中提供更新的OpenSSL后,我不知道如何让Android HttpClient
使用它。
更糟糕的案例答案:您可能需要分叉Android并提供更新的OpenSSL。
一个可能更好的解决方案:翻录HttpClient
代码,将其放入您自己的软件包中,然后确保源代码的端口使用共享对象。