为 HttpClient 在 Android 应用程序中更改 OpenSSL 库
Changing OpenSSL library in Android app for HttpClient
我需要在我的项目中为 HttpClient 使用自定义 OpenSSL 库。
我已经为 Android 编译了 libcrypto.so 和 libssl.so 并将文件放入一个文件夹 jniLibs。应用程序 Heartbleed Scanner 会看到它们。 System.loadLibrary("crypto")
和 System.loadLibrary("ssl")
有效。
但是现在我需要让 HttpClient 使用我的库而不是标准的 SSL 库。但我不知道该走哪条路,该怎么做。
我使用 OpenSSL 1.0.1h 和 Android Studio 1.0.2。
提前感谢您的建议。
I have compiled libcrypto.so and libssl.so for Android and put the files in a folder jniLibs...
这行不通。
Android 利用 OpenSSL 1.0.0 并在 /system
中提供。 Zygote 在启动时启动并加载 OpenSSL 的低级别版本(它像 init
- 所有 Android 进程都是从它派生的)。
当您的进程从 Zygote 分叉时,您的 1.0.1 版本永远不会加载,因为 1.0.0 已经从 Zygote 加载。你永远不知道有问题,因为下级版本提供了你需要的所有符号(它的二进制兼容)。
您需要编写一个包装器共享对象。包装器共享对象必须 link 针对 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
标志和 link 对 libcrypto.a
和 libssl.a
进行编译。只有标有 DLL_PUBLIC
的函数将通过 JNI 导出和调用。
我认为不需要#if __GNUC__ >= 4
因为Android提供的交叉编译工具是GCC 4.0以上。事实上,我认为它目前是 GCC 4.8。
Changing OpenSSL library in Android app for HttpClient
这个问题比较难。在您的共享包装器中提供更新的 OpenSSL 后,我不知道您将如何让 Android 的 HttpClient
使用它。
最坏情况的答案:您可能需要分叉 Android 并提供更新的 OpenSSL。
一个可能更好的解决方案:撕下 HttpClient
代码,将其放入您自己的包中,然后确保您的共享对象被源代码的端口使用。
我需要在我的项目中为 HttpClient 使用自定义 OpenSSL 库。
我已经为 Android 编译了 libcrypto.so 和 libssl.so 并将文件放入一个文件夹 jniLibs。应用程序 Heartbleed Scanner 会看到它们。 System.loadLibrary("crypto")
和 System.loadLibrary("ssl")
有效。
但是现在我需要让 HttpClient 使用我的库而不是标准的 SSL 库。但我不知道该走哪条路,该怎么做。
我使用 OpenSSL 1.0.1h 和 Android Studio 1.0.2。
提前感谢您的建议。
I have compiled libcrypto.so and libssl.so for Android and put the files in a folder jniLibs...
这行不通。
Android 利用 OpenSSL 1.0.0 并在 /system
中提供。 Zygote 在启动时启动并加载 OpenSSL 的低级别版本(它像 init
- 所有 Android 进程都是从它派生的)。
当您的进程从 Zygote 分叉时,您的 1.0.1 版本永远不会加载,因为 1.0.0 已经从 Zygote 加载。你永远不知道有问题,因为下级版本提供了你需要的所有符号(它的二进制兼容)。
您需要编写一个包装器共享对象。包装器共享对象必须 link 针对 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
标志和 link 对 libcrypto.a
和 libssl.a
进行编译。只有标有 DLL_PUBLIC
的函数将通过 JNI 导出和调用。
我认为不需要#if __GNUC__ >= 4
因为Android提供的交叉编译工具是GCC 4.0以上。事实上,我认为它目前是 GCC 4.8。
Changing OpenSSL library in Android app for HttpClient
这个问题比较难。在您的共享包装器中提供更新的 OpenSSL 后,我不知道您将如何让 Android 的 HttpClient
使用它。
最坏情况的答案:您可能需要分叉 Android 并提供更新的 OpenSSL。
一个可能更好的解决方案:撕下 HttpClient
代码,将其放入您自己的包中,然后确保您的共享对象被源代码的端口使用。