在Android应用中为HttpClient更改OpenSSL库

时间:2015-02-05 10:11:04

标签: java android openssl httpclient

我需要在项目中为 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。

提前感谢您的建议。

1 个答案:

答案 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.alibssl.a)。您的包装器必须导出唯一的符号,例如My_OpenSSL_add_all_algorithmsMy_SSL_load_error_strings。在内部,您的共享对象可以引用未修饰的名称OpenSSL_add_all_algorithmsSSL_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.alibssl.a。只有标有DLL_PUBLIC的函数才能通过JNI导出和调用。

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


  

在Android应用中为HttpClient更改OpenSSL库

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

更糟糕的案例答案:您可能需要分叉Android并提供更新的OpenSSL。

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