I am currently working on a project where I am sending data via an https call to our server api. The base URL for the project supports ssl (Our url api endpoint starts with https://api.....). I am using Retrofit 2 and OkHttp3 and am setting up the client like this:
public static void buildClient(){
//Misc code here.... not showing for security reasons.
OkHttpClient client = RetrofitClient.configureClient(new OkHttpClient());
//I make calls here to update interceptors, timeouts, etc.
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create(new Gson()))
.client(client)
.build();
}
//Setup the ssl stuff here
public static OkHttpClient configureClient(final OkHttpClient client) {
final TrustManager[] certs = new TrustManager[]{new X509TrustManager() {
@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
@Override
public void checkServerTrusted(final X509Certificate[] chain,
final String authType)
throws CertificateException {
}
@Override
public void checkClientTrusted(final X509Certificate[] chain,
final String authType)
throws CertificateException {
}
}};
SSLContext ssl = null;
try {
ssl = SSLContext.getInstance("TLS");
ssl.init(null, certs, new SecureRandom());
} catch (final java.security.GeneralSecurityException ex) {
}
try {
final HostnameVerifier hostnameVerifier = new HostnameVerifier() {
@Override
public boolean verify(final String hostname,
final SSLSession session) {
return true;
}
};
client.setHostnameVerifier(hostnameVerifier);
client.setSslSocketFactory(ssl.getSocketFactory());
} catch (final Exception e) {
}
return client;
}
So after this, we are all set.
Now, here's what I know:
1) I am sending via HTTPS because if I were not, the server would throw an error, which it is not.
2) My code is working just fine in that it is communicating with the server and the app will work.
The problem here is that the actual Body data is not being encrypted. Here are 2 photo examples to show what I mean.
1)
2)
The first image shows proper obfuscation of the actual body data in that the data is being converted to encrypted 'stuff' while the second shows plain text. The second one is me sending a POST call to the server with an object.
My question is, how do I go about replicating this so that my body text is hidden / encrypted like the other?
Notes:
1) I am using obfuscation via Proguard
2) I to have minifyEnabled set to true
3) How I found this out is via a packet sniffer
Anyone have any ideas how to accomplish this? Or can anyone point me in the right direction as to what this is called specifically?
Thanks.
EDIT:
So, it looks like I was not understanding a key component here.
Short answer is, the call is already encrypted and is sending Https.
Long answer is, I have been comparing my data calls to ones like these:
1)
2)
Where I just assumed that These were encrypted, while mine was not. It turns out that the calls I am sending are encrypted just fine, as are these, but this data is zipped / compressed, which makes it unreadable to the eye, which is what made me think that it was what encrypted data looked like from a packet sniffer.
This means your @GET or @DELETE should not have @Body parameter. You can use query type url or path type url or Query Map to fulfill your need. Else you can use other method annotation.
Understanding Okio's okhttp3 and retrofit Okio-okhttp3 is a library that works in conjunction with java.io and java. nio to make data access, storage, and processing considerably easier. It started as a component of OkHttp. Retrofit is a type-safe REST client for Java and Android application development.
OkHttp is a pure HTTP/SPDY client responsible for any low-level network operations, caching, requests and responses manipulation. In contrast, Retrofit is a high-level REST abstraction build on top of OkHttp. Retrofit is strongly coupled with OkHttp and makes intensive use of it.
Retrofit is a type-safe REST client for Android, Java and Kotlin developed by Square. The library provides a powerful framework for authenticating and interacting with APIs and sending network requests with OkHttp.
Your question is: Why I use HTTPS but the Packet Capture or Charles can view all of the SSL / HTTPS traffic between the client and the Internet?
Because the Packet Capture(the VPN proxy) or Charles cheated your client as an intermediary:
Your client <-->
Packet Capture/Charles <-->
Your target server.
So the proxy tool can view all your HTTPS content(In fact they are indeed encrypted).
Solution:
You can refer the OkHttp wiki: https://github.com/square/okhttp/wiki/HTTPS
and set a Certificate pinning for your HTTPS checking. For example:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final TextView textView = (TextView) findViewById(R.id.text);
ConnectionSpec spec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
.tlsVersions(TlsVersion.TLS_1_2)
.cipherSuites(
CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256)
.build();
OkHttpClient client = new OkHttpClient.Builder()
.connectionSpecs(Collections.singletonList(spec))
.certificatePinner(new CertificatePinner.Builder()
.add("drakeet.me", "sha256/gGOcYKAwzEaUfun6YdxZvFSQq/x2lF/R8UizDFofveY=")
.build())
.build();
Request request = new Request.Builder()
.url("https://drakeet.me?s=type")
.post(RequestBody.create(MediaType.parse("text"), "xxx...xxx"))
.addHeader("token", "xxx")
.build();
final Handler handler = new Handler();
client.newCall(request).enqueue(new Callback() {
@Override public void onFailure(Call call, IOException e) {
e.printStackTrace();
}
@Override public void onResponse(Call call, final Response response)
throws IOException {
final String t = response.body().string();
handler.post(new Runnable() {
@Override public void run() {
textView.setText(t);
}
});
}
});
}
}
As my above codes, I preset a certificatePinner
relate to the true certificatePinner of my target server, so that if I use Packet Capture/Charles now, they will create a false certificatePinner by themselve, and OkHttp will compare the two pinning, if not equal, throw a javax.net.ssl.SSLPeerUnverifiedException: Certificate pinning failure!
And if you close the Packet Capture/Charles, the exception dismiss and send HTTPS content successfully.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With