I'm encountering an javax.net.ssl.SSLHandshakeException with the message "SSL pinning validation failed" when implementing SSL pinning in my Android application. I have already verified that I'm using the correct SHA-256 key for pinning.
Here's the relevant code snippet:
package
import android.os.Build;
import androidx.annotation.RequiresApi;
import com.android.volley.toolbox.HurlStack;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.security.KeyManagementException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Base64;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
public class CustomHurlStack extends HurlStack implements HurlStack.UrlRewriter {
private String sha256Pin;
public CustomHurlStack(String sha256Pin) {
this.sha256Pin = sha256Pin;
}
@Override
protected HttpURLConnection createConnection(java.net.URL url) throws IOException {
HttpURLConnection connection = super.createConnection(url);
if (connection instanceof HttpsURLConnection) {
HttpsURLConnection httpsURLConnection = (HttpsURLConnection) connection;
try {
// Configure SSL socket factory with SSL pinning
SSLSocketFactory sslSocketFactory = createSSLSocketFactory();
httpsURLConnection.setSSLSocketFactory(sslSocketFactory);
// Set hostname verifier to bypass hostname verification
httpsURLConnection.setHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
} catch (NoSuchAlgorithmException | KeyManagementException e) {
e.printStackTrace();
}
}
return connection;
}
private SSLSocketFactory createSSLSocketFactory() throws NoSuchAlgorithmException, KeyManagementException {
TrustManager[] trustManagers = new TrustManager[]{new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
// Perform any necessary client certificate checks
}
@RequiresApi(api = Build.VERSION_CODES.O)
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
// Perform the SSL pinning check
for (X509Certificate certificate : chain) {
String publicKeySha256 = null;
try {
publicKeySha256 = calculatePublicKeySha256(certificate.getPublicKey());
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
if (!sha256Pin.equals(publicKeySha256)) {
throw new CertificateException("SSL pinning validation failed");
}
}
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}};
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustManagers, null);
return sslContext.getSocketFactory();
}
@Override
public String rewriteUrl(String originalUrl) {
// Implement any URL rewriting logic if needed
// You can modify the original URL and return the modified URL
return originalUrl;
}
@RequiresApi(api = Build.VERSION_CODES.O)
private String calculatePublicKeySha256(PublicKey publicKey) throws NoSuchAlgorithmException {
byte[] publicKeyBytes = publicKey.getEncoded();
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] sha256Bytes = digest.digest(publicKeyBytes);
return Base64.getEncoder().encodeToString(sha256Bytes);
}
}
Here's relevant code snippet of API call:
String sha256Pin = Customize.getInstance().getSslPublicKey(); // Replace with your custom SHA256 pin
CustomHurlStack customHurlStack = new CustomHurlStack(sha256Pin);
RequestQueue sRequestQueue = Volley.newRequestQueue(mContext, customHurlStack);
I have followed the steps mentioned in the documentation and other online resources, but I'm still unable to resolve the issue. Here are the details of my setup:
- Android version: Android 10
- Library/Framework used: Volley 1.2.1
- SHA-256 key used: -----
I have also tried the following troubleshooting steps without success:
- Verifying the SHA-256 key: I have double-checked the SHA-256 key and ensured that it matches the server's public key.
- Debugging and logging: I have added debug logs to track the SSL pinning process, but the error still occurs.
- Testing in a different environment: I have tested the SSL pinning implementation with a different server, but the issue persists.
I would appreciate any insights, suggestions, or possible solutions to resolve this SSL pinning validation error. Thank you in advance for your help.