- Il certificato del server (pub_server.crt) è self signed (firmato) da una CA personale (personal_ca.crt)
- Il client si autentica utilizzando il proprio certificato p12 (client.p12) e in più con il proprio user e password.
Vi spiego i passi che ho fatto:
- Siccome Android utilizza il provider JCE di Bouncy Castle ho scaricato il jar bcprov-jdk16-146.jar e l'ho salvato sotto la directory lib del progetto ($workspace/mioProgetto/libs/).
- Importo personal_ca.crt e pub_server.crt in un unico file chiamato server_cert di tipo BKS nel miProgetto come risorsa raw ($workspace/mioProgetto/res/raw/) :
Basta fare un refresh sulla directory res/raw per vedere il certificato importato.#importo il CA personale keytool -import -alias personalCa -file [percorso]\personal_ca.crt -keypass provapass -keystore
$workspace\mioProgetto\res\raw\server_cert -storetype BKS -storepass
provapass
-providerClass org.bouncycastle2.jce.provider.BouncyCastleProvider -providerpath$workspace\mioProgetto\libs\bcprov-jdk16-146.jar #importo il certificato server keytool -importcert -v -trustcacerts -file [percorso]\pub_server.crt -alias serverCert -keystore $workspace\mioProgetto\res\raw\server_cert -providerClass org.bouncycastle2.jce.provider.BouncyCastleProvider -providerpath $workspace\mioProgetto\libs\bcprov-jdk16-146.jar -storetype BKS -storepass provapass
- Salvo anche il certificato client client.p12 sotto $workspace/mioProgetto/res/raw/
- Ora utilizzo questi certificati per fare l'autenticazione.
try { SSLContext sslContext = SSLContext.getInstance("TLS"); // truststore KeyStore trustStore = KeyStore.getInstance("BKS"); TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); InputStream trustStoreStream = this.getResources().openRawResource(R.raw.server_cert); // passo la password utilizzata quando ho importato il certificato trustStore.load(trustStoreStream, "provapass".toCharArray()); trustManagerFactory.init(trustStore); // keystore KeyStore keyStore = KeyStore.getInstance("pkcs12"); KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); InputStream keyStoreStream = this.getResources().openRawResource(R.raw.client); // passo la password del certificato client keyStore.load(keyStoreStream, "clientpass".toCharArray()); keyManagerFactory.init(keyStore, "clientpass".toCharArray()); sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null); URL url = new URL("https://webserviceUrl"); // utilizzo HttpsURLConnection per fare connessioni https HttpsURLConnection conn = (HttpsURLConnection) url.openConnection(); // username e password String usernamePass = "userName:password"; String basicAuth = new String(Base64.encode(usernamePass.getBytes())); // basic authentication conn.setRequestProperty("Authorization", "Basic " + basicAuth); conn.setRequestProperty("User-Agent", "Android Application"); // non la faccio la verifica del hostname conn.setHostnameVerifier(new SkipVerifier()); conn.setSSLSocketFactory(sslContext.getSocketFactory()); System.out.println("Response code is " + conn.getResponseCode()); } catch (Exception e) { largeTxt.setText(e.getMessage()); e.printStackTrace(); }
-
Creo la classe SkipVerifier che implementa HostnameVerifier, che non fa altro che ritorna true per ogni hostname.
public class SkipVerifier implements HostnameVerifier { @Override public final boolean verify(final String hostname, final SSLSession sslSession) { return true; } }