Changing Openssl Library in Android App for Httpclient

Changing OpenSSL library in Android app for HttpClient

I have compiled libcrypto.so and libssl.so for Android and put the files in a folder jniLibs...

This won't work.

Android utilizes OpenSSL 1.0.0 and provides it in /system. Zygote starts at boot and loads the down level version of OpenSSL (its like init - all Android processes are forked from it).

When your process is forked from Zygote, your 1.0.1 version is never loaded because 1.0.0 is already loaded from Zygote. You never know there's a problem because the down level version provides all the symbols you need (its binary compatible).

You need to write a wrapper shared object. The wrapper shared object must link against the static versions of OpenSSL 1.0.1 (libcrypto.a and libssl.a). Your wrapper must export unique symbols, like My_OpenSSL_add_all_algorithms and My_SSL_load_error_strings. Internally, your shared object can refer to the undecorated names, OpenSSL_add_all_algorithms and SSL_load_error_strings.

So your shared object would look like so (also see GCC's 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();
}
...

Then, compile with the -fvisibility=hidden flag and link against libcrypto.a and libssl.a. Only the functions marked with DLL_PUBLIC will be exported and callable through JNI.

I don't think the #if __GNUC__ >= 4 is needed because the cross compiler tools provided by Android are GCC 4.0 above. In fact, I think its currently GCC 4.8.


Changing OpenSSL library in Android app for HttpClient

This question is tougher. Once you provide the updated OpenSSL in your shared wrapper, I don't know how you would get Android's HttpClient to use it.

The worse case answer: you might need to fork Android and provide an updated OpenSSL.

A potentially better solution: rip the HttpClient code, put it in your own package, and then be sure you shared object is used by port of the source code.

Cannot load prebuilt OpenSSL library in Android project

Turned out that structure of my jniLibs was something like:

arm64-v8a
include
...
lib
libcrypto.so
libssl.so
x86
include
...
lib
...

opposed to:

arm64-v8a
include
...
libcrypto.so
libssl.so
x86
include
...
...

Which solves initial problem.

How to use Apache http-client 4.5.x used by external library on Android

You can not directly replace classes included in the Android framework. The only solution is to use a different namespace. This is why Spongy Castle uses org.spongycastle.* instead of org.bouncycastle.*, and the project you linked uses cz.msebera.android.httpclient.* instead of org.apache.http.*.

Unfortunately, this means that you have to change every reference to http-client in your library.

Since the release of Android Jetpack, the SDK includes Jetifier, a tool to translate
references in libraries bytecode at buildtime. There is a standalone version, and it can use custom mapping config.

In you case this would imply:

  • Create a custom config translating org.apache.http to cz.msebera.android.httpclient
  • Convert your standard Java library
  • Use the transformed library and the third party port of http-client

Another possible solution to convert the library would be to use Jar Jar.

How to pass unsafe HttpClient to Volley request in Android

I found and it is working for me, Please let me know anything wrong here. Here is the code need to add to make a call.

final String url = "YOUR URL";
RequestQueue queue = Volley.newRequestQueue(this, getHttpStack(url));
// prepare the Request
JsonObjectRequest getRequest = new JsonObjectRequest(Request.Method.GET, url, null,
new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
// display response
Log.e("test", "Response" + response.toString());
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.e("test", "Error.Response: " + error.getMessage());
}
}
);

queue.add(getRequest);

Here is the methods, need to add in code.

private HurlStack getHttpStack(String urlToValidate) {
URL url = null;
try {
url = new URL(urlToValidate);
} catch (MalformedURLException e) {
e.printStackTrace();
}
final String baseUrl = url.getAuthority();
return new HurlStack() {
@Override
protected HttpURLConnection createConnection(final java.net.URL url)
throws IOException {
HttpsURLConnection httpsURLConnection = (HttpsURLConnection) super
.createConnection(url);
try {
httpsURLConnection
.setSSLSocketFactory(handleSSLHandshake(httpsURLConnection));
httpsURLConnection.setHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
//return true;
HostnameVerifier hv =
HttpsURLConnection.getDefaultHostnameVerifier();
return hv.verify(baseUrl, session);
}
});
} catch (Exception e) {
e.printStackTrace();
}
return httpsURLConnection;
}
};
}

@SuppressLint("TrulyRandom")
public static SSLSocketFactory handleSSLHandshake(HttpsURLConnection connection) {
try {
TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}

@Override
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}

@Override
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
}};

SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String arg0, SSLSession arg1) {
Log.e("test", "RETURN TRUE: ");
return true;
}
});
sc.init(null, trustAllCerts, new java.security.SecureRandom());
SSLSocketFactory newFactory = sc.getSocketFactory();
connection.setSSLSocketFactory(newFactory);
} catch (Exception ignored) {
}

return connection.getSSLSocketFactory();

}

An HTTPS Client for Android that doesn't use native_ssl

This is a work around - not a solution.

We just could not afford spending any more resources on this issue...

We've dodged the bullet by splitting the upload procedure to 2 steps:
First step (which requires the Client-certificate) takes all the metadata and returns an upload token (expires in 30 seconds).
Second step does not require the certificate, but uses the upload token to perform upload (still over SSL).

Application crashes in loading C++ jni library dynamically linked with openss-1.0.1h

It looks like you have two problems. First is linking against OpenSSL; and second is actually finding the library in the APK.


I am using a C++ library, which is dynamically linked with openss-1.0.1 h libraries...

Here is your first problem. Android's equivalent of init is zygote. Zygote loads the platform's version of OpenSSL. When Zygote forks to start your app, you app gets the already linked version of OpenSSL, which is likely 0.9.8. Since your app is built against 1.0.1, you will crash at runtime because 0.9.8 and 1.0.0 are not binary compatible.

To resolve this, you have to build a wrapper shared object that links against the static version of the OpenSSL library. Then, when you need to make an OpenSSL call, you expose it through your wrapper. For example, you might have a GetSslContext that wraps the calls to OpenSSL's SSLv23_method, SSL_CTX_new, SSL_CTX_set_options, etc.

This avoids calling into Zygote's downlevel OpenSSL. Its also documented on the OpenSSL wiki at OpenSSL and Android.


"could not find libssl.so.1.0.0 needed by libABC.so"

Here is your second problem. First, create a wrapper shared object as described above. Second, place your shared objects in the proper directory. The shared wrapper should be placed in the lib/ directory. I believe you can also have specialized versions of the library in subdirectories. For example, lib/ would be a generic fallback, while lib/armv7-a/ would be a shared object built specifically for ARMv7a.

You can find the libraries at runtime with the ApplicationInfo class and its nativeLibDir method:

public String nativeLibraryDir

Full path to the directory where native JNI libraries are stored.

Also see Android's JNI Tips and the Native Libraries section.


 System.loadLibrary("ssl");
System.loadLibrary("crypto");

Related, libssl depends upon libcrypto, so it should be:

 static {
System.loadLibrary("crypto");
System.loadLibrary("ssl");
}

But you should probably avoid it and use a wrapper shared object.



Related Topics



Leave a reply



Submit