问题
I know this subject is discussed in many places, but after I went through almost all of them, I have decided to create my first StackOverflow question...
The problem is the following:
I want to connect to a secured webservice (https) that use a certificate to restrict the access, and a username/password to authenticate the user. So i have a client cert (p12 file) and a server cert (pem or der file). I try to use the HttpURLConnection class, because from what I've heard, Apache library will no more be supported on Android.
So this is my implementations (serverCert and clientCert are the full path to my files):
// Load CAs from our reference to the file
CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream caInput = new BufferedInputStream(new FileInputStream(serverCert));
X509Certificate serverCertificate;
try {
serverCertificate = (X509Certificate)cf.generateCertificate(caInput);
System.out.println("ca=" + serverCertificate.getSubjectDN());
} finally {
caInput.close();
}
Log.d(TAG, "Server Cert: " + serverCertificate);
// Create a KeyStore containing our trusted CAs
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(null);
trustStore.setCertificateEntry("my ca", serverCertificate);
//Load the Client certificate in the keystore
KeyStore keyStore = KeyStore.getInstance("PKCS12");
FileInputStream fis = new FileInputStream(clientCert);
keyStore.load(fis,CLIENT_PASSWORD);
// Create a TrustManager that trusts the CAs in our KeyStore
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(trustStore);
//Build the SSL Context
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(keyStore, pref.getString(Constants.clientCertificatePassword, "").toCharArray
());
//Create the SSL context
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
...
//And later, we use that sslContext to initiatize the socketFactory
urlConnection = (HttpsURLConnection) requestedUrl.openConnection();
urlConnection.setSSLSocketFactory(CertificateManager.getInstance().getSslContext().getSocketFactory());
...
So i can create my SSLContext, and display my two certificates content. But when i try to execute my HTTPS connection, I get the following exception:
09-23 13:43:30.283: W/System.err(19422): javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
Does one of you ever met the following error? What was your solution?
These are the website i went through (without success):
http://blog.chariotsolutions.com/2013/01/https-with-client-certificates-on.html
http://nelenkov.blogspot.ch/2011/12/using-custom-certificate-trust-store-on.html
回答1:
In your code your are creating and initializing a SSLContext
but not using it. Maybe you should replace :
urlConnection.setSSLSocketFactory(CertificateManager.getInstance().getSslContext().getSocketFactory());
by
urlConnection.setSSLSocketFactory(sslContext.getSocketFactory());
I also suggest you if possible to pass the option -Djavax.net.debug=all
to the JVM. It will print detailed information about the SSL connection and handshake on the standard output.
来源:https://stackoverflow.com/questions/18959663/android-self-signed-certificate-trust-anchor-for-certification-path-not-found