I am working on android application, which requires to communicate with server over ssl. Any good example to work with pkcs12 certificates in android using HttpsUrlConnection
After doing some modifications to the code posted by @EpicPandaForce, i was able to successfully run the code.
Changes:
1. KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("X509");
to
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
to get rid of exception: java.security.NoSuchAlgorithmException: X509 KeyManagerFactory not available
2. KeyStore keyStore = KeyStore.getInstance("PKCS12", BouncyCastleProvider.PROVIDER_NAME); //spongyCastle library
to
KeyStore keyStore = KeyStore.getInstance("PKCS12");
and added the provider to Security Class as shown below
Security.addProvider(new BouncyCastleProvider());
to get rid of Exception:java.security.NoSuchProviderException: no such provider: SC
Then Final complete code:
Security.addProvider(new BouncyCastleProvider());
SSLContext sslContext = SSLContext.getInstance("TLS");
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init((KeyStore)null); //this is where you would add the truststore
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
KeyStore keyStore = KeyStore.getInstance("PKCS12"); //spongyCastle library
keyStore.load(new FileInputStream("D:\\Documents\\VISA Direct Api\\cabcentralcert.p12"), "cabcentral".toCharArray()); //inputStream to PKCS12
keyManagerFactory.init(keyStore, "cabcentral".toCharArray());
//TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
TrustManager[] trustAllCertManagers = { new X509TrustManager() { // this is vulnerable to MITM attack
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}};
sslContext.init(keyManagerFactory.getKeyManagers(), trustAllCertManagers, new SecureRandom());
URL url = new URL(strUrl);
HttpsURLConnection httpsUrlConnection = (HttpsURLConnection) url.openConnection();
httpsUrlConnection.setSSLSocketFactory(sslContext.getSocketFactory());
System.out.println("Response Code : " + httpsUrlConnection.getResponseCode());
System.out.println("Cipher Suite : " + httpsUrlConnection.getCipherSuite());
Indeed, although it's a bit messy.
SSLContext sslContext = SSLContext.getInstance("TLS");
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init((KeyStore)null); //this is where you would add the truststore
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
KeyStore keyStore = KeyStore.getInstance("PKCS12", BouncyCastleProvider.PROVIDER_NAME); //spongyCastle library
keyStore.load(keyStoreStream, keyStorePassword); //inputStream to PKCS12
keyManagerFactory.init(keyStore, keyStorePassword);
//TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
TrustManager[] trustAllCertManagers = { new X509TrustManager() { // this is vulnerable to MITM attack
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}};
sslContext.init(keyManagerFactory.getKeyManagers(), trustAllCertManagers, new SecureRandom());
URL url = new URL(urlString);
HttpsURLConnection httpsUrlConnection = (HttpsURLConnection) url.openConnection();
httpsUrlConnection.setSSLSocketFactory(sslContext.getSocketFactory());
You need the following dependencies:
compile 'com.madgag.spongycastle:core:1.51.0.0'
compile 'com.madgag.spongycastle:prov:1.51.0.0'
compile 'com.madgag.spongycastle:pkix:1.51.0.0'
This needs a bit of fixing though as even though it initializes the key store (that stores the client certificate in PKCS12), it trusts every certificate rather than use a keystore to find out whether it is a trusted certificate or not (and this is vulnerable to Man-in-the-Middle
attacks).
EDIT: In order to make SpongyCastle work, you need to add a custom application like this:
import org.spongycastle.jce.provider.BouncyCastleProvider;
public class CustomApplication
extends Application {
static {
Security.insertProviderAt(new BouncyCastleProvider(), 1);
}
@Override
public void onCreate() {
super.onCreate();
}
}
And in AndroidManifest.xml:
<application
android:allowBackup="true"
android:name=".CustomApplication"
来源:https://stackoverflow.com/questions/30083229/any-good-example-for-working-with-unknown-ca-signed-certificatelike-pkcs12-in