I'm trying to pin my server's self-signed certificate. My OkHttpClient takes two parameters, the first one is the ssl Socket Factory :
final TrustManager[] trustAllCerts = new TrustManager[] {
new X509TrustManager() {
@SuppressLint("TrustAllX509TrustManager")
@Override
public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {}
@SuppressLint("TrustAllX509TrustManager")
@Override
public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {}
@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}
};
// Install the all-trusting trust manager
SSLContext sslContext;
try {
sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
} catch (NoSuchAlgorithmException | KeyManagementException e) {
e.printStackTrace();
FirebaseCrash.report(e);
return null;
}
// Create an ssl socket factory with our all-trusting manager
final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
Second is a certificate pinner :
new CertificatePinner.Builder()
.add("bogus.com", "sha1/BOGUS")
.build()
Note: if I don't add a certificatePinner, then everything works fine. The problem is that when the request gets executed, CertificatePinner.check() gets called:
if (pins.isEmpty()) return;
Obviously, if I do set a (non-empty) certificatePinner, the method won't stop there and will continue. It then goes on to check that "at least one of the certificates pinned for my hostname is a trusted certificate".
The problem is that I passed an empty array in getAcceptedIssuers for my TrustManager - meaning the self-signed cert will trigger an exception since it hasn't been explicitly trusted in "getAcceptedIssues". Seems like it's impossible to pin a certificate that isn't trusted explicitly in "getAcceptedIssuers".
Is there any way to get around that? Is it by design?
This is how I build my OkHttpClient :
OkHttpClient client = new OkHttpClient.Builder()
.sslSocketFactory(sslSocketFactory, (X509TrustManager) trustAllCerts[0])
.certificatePinner(certPinner)
.readTimeout(10, TimeUnit.SECONDS)
.connectTimeout(10, TimeUnit.SECONDS)
.build();
private static OkHttpClient getUnsafeOkHttpClient() {
try {
// Create a trust manager that does not validate certificate chains
final TrustManager[] trustAllCerts = new TrustManager[] {
new X509TrustManager() {
@Override
public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new java.security.cert.X509Certificate[]{};
}
}
};
// Install the all-trusting trust manager
final SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
// Create an ssl socket factory with our all-trusting manager
final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.sslSocketFactory(sslSocketFactory, (X509TrustManager)trustAllCerts[0]);
builder.hostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
OkHttpClient okHttpClient = builder
.connectTimeout(15, TimeUnit.SECONDS)
.writeTimeout(15, TimeUnit.SECONDS)
.readTimeout(15, TimeUnit.SECONDS)
.build();
return okHttpClient;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
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