Reputation: 13
I got a security alert from google play when I upload an APK to play store below. Your App is using the unsafe implementation of the HostnameVerifier Interface. My code is here.
public class NukeSSLCerts {
protected static final String TAG = "NukeSSLCerts";
public static void nuke() {
try {
TrustManager[] trustManagerArr = new TrustManager[]{new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] x509CertificateArr, String str) {
}
public void checkServerTrusted(X509Certificate[] x509CertificateArr, String str) {
}
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}};
SSLContext instance = SSLContext.getInstance("SSL");
instance.init(null, trustManagerArr, new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(instance.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
public boolean verify(String str, SSLSession sSLSession) {
return true;
}
});
} catch (Exception unused) {
}
}
}
Upvotes: 0
Views: 461
Reputation: 1004
Accepting all SSL certificates is usually not the ideal scenario. Slightly better is to only accept your specific SSL certificate using this code snippet.
final class CustomTrust {
private static InputStream trustedCertificatesInputStream() {
String certificate_one = "ADD_YOUR_CERTIFICATE";
String certificate_two = "ADD_YOUR_CERTIFICATE";
return new Buffer()
.writeUtf8(certificate_one)
.writeUtf8(certificate_two)
.inputStream();
}
public static X509TrustManager getTrustManagerForCertificates()
throws GeneralSecurityException {
InputStream in= trustedCertificatesInputStream();
CertificateFactory certificateFactory =
CertificateFactory.getInstance("X.509");
Collection<? extends Certificate> certificates =
certificateFactory.generateCertificates(in);
if (certificates.isEmpty()) {
throw new IllegalArgumentException("expected non-empty set of trusted
certificates");
}
// Put the certificates a key store.
char[] password = "password".toCharArray(); // Any password will work.
KeyStore keyStore = newEmptyKeyStore(password);
int index = 0;
for (Certificate certificate : certificates) {
String certificateAlias = Integer.toString(index++);
keyStore.setCertificateEntry(certificateAlias, certificate);
}
// Use it to build an X509 trust manager.
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(
KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, password);
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
if (trustManagers.length != 1 || !(trustManagers[0] instanceof
X509TrustManager)) {
throw new IllegalStateException("Unexpected default trust managers:"
+ Arrays.toString(trustManagers));
}
return (X509TrustManager) trustManagers[0];
}
private static KeyStore newEmptyKeyStore(char[] password) throws
GeneralSecurityException {
try {
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
InputStream in = null; // By convention, 'null' creates an empty key
store.
keyStore.load(in, password);
return keyStore;
} catch (IOException e) {
throw new AssertionError(e);
}
}}
Use this CustomTrust in your OKHttp Client as.
public class MyOkHttpClient {
public static OkHttpClient get(Context context) {
try {
// Install the all-trusting trust manager
X509TrustManager trustManager =
CustomTrust.getTrustManagerForCertificates();
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[]{trustManager}, null);
SSLSocketFactory sslSocketFactory =
sslContext.getSocketFactory();
OkHttpClient.Builder okHttpBuilder = new
OkHttpClient.Builder()
.sslSocketFactory(sslSocketFactory, trustManager)
.hostnameVerifier((hostname, session) -> true)
.connectTimeout(30, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
return okHttpBuilder.build();
} catch (Exception e) {
throw new RuntimeException(e);
}
} }
Upvotes: 3