Die folgenden Hauptschritte sind erforderlich, um eine gesicherte Verbindung von Zertifizierungsstellen herzustellen, die von der Android-Plattform nicht als vertrauenswürdig eingestuft werden.
Wie von vielen Benutzern gewünscht, habe ich die wichtigsten Teile meines Blog-Artikels hier gespiegelt :
- Besorgen Sie sich alle erforderlichen Zertifikate (Root- und Zwischenzertifizierungsstellen).
- Erstellen Sie einen Keystore mit Keytool und dem BouncyCastle- Anbieter und importieren Sie die Zertifikate
- Laden Sie den Keystore in Ihre Android-App und verwenden Sie ihn für die gesicherten Verbindungen (ich empfehle, den Apache HttpClient anstelle des Standards zu verwenden
java.net.ssl.HttpsURLConnection
(einfacher zu verstehen, leistungsfähiger).
Schnapp dir die Zertifikate
Sie müssen alle Zertifikate, die eine Kette bilden, vom Endpunktzertifikat bis zur Stammzertifizierungsstelle erhalten. Dies bedeutet, dass alle (falls vorhanden) Zwischenzertifizierungsstellenzertifikate sowie das Stammzertifizierungsstellenzertifikat vorhanden sind. Sie müssen das Endpunktzertifikat nicht erhalten.
Erstellen Sie den Keystore
Laden Sie den BouncyCastle-Anbieter herunter und speichern Sie ihn an einem bekannten Ort. Stellen Sie außerdem sicher, dass Sie den Befehl keytool aufrufen können (normalerweise im Ordner bin Ihrer JRE-Installation).
Importieren Sie nun die erhaltenen Zertifikate (importieren Sie das Endpunktzertifikat nicht) in einen BouncyCastle-formatierten Keystore.
Ich habe es nicht getestet, aber ich denke, die Reihenfolge des Imports der Zertifikate ist wichtig. Dies bedeutet, dass Sie zuerst das unterste Zwischenzertifizierungsstellenzertifikat und dann bis zum Stammzertifizierungsstellenzertifikat importieren.
Mit dem folgenden Befehl wird ein neuer Schlüsselspeicher (falls nicht bereits vorhanden) mit dem Kennwort mysecret erstellt und das Zwischenzertifizierungsstellenzertifikat importiert. Ich habe auch den BouncyCastle-Anbieter definiert, der sich in meinem Dateisystem und im Keystore-Format befindet. Führen Sie diesen Befehl für jedes Zertifikat in der Kette aus.
keytool -importcert -v -trustcacerts -file "path_to_cert/interm_ca.cer" -alias IntermediateCA -keystore "res/raw/mykeystore.bks" -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath "path_to_bouncycastle/bcprov-jdk16-145.jar" -storetype BKS -storepass mysecret
Überprüfen Sie, ob die Zertifikate korrekt in den Keystore importiert wurden:
keytool -list -keystore "res/raw/mykeystore.bks" -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath "path_to_bouncycastle/bcprov-jdk16-145.jar" -storetype BKS -storepass mysecret
Sollte die gesamte Kette ausgeben:
RootCA, 22.10.2010, trustedCertEntry, Thumbprint (MD5): 24:77:D9:A8:91:D1:3B:FA:88:2D:C2:FF:F8:CD:33:93
IntermediateCA, 22.10.2010, trustedCertEntry, Thumbprint (MD5): 98:0F:C3:F8:39:F7:D8:05:07:02:0D:E3:14:5B:29:43
Jetzt können Sie den Keystore als Rohstoff in Ihre Android-App unter kopieren res/raw/
Verwenden Sie den Keystore in Ihrer App
Zunächst müssen wir einen benutzerdefinierten Apache HttpClient erstellen, der unseren Keystore für HTTPS-Verbindungen verwendet:
import org.apache.http.*
public class MyHttpClient extends DefaultHttpClient {
final Context context;
public MyHttpClient(Context context) {
this.context = context;
}
@Override
protected ClientConnectionManager createClientConnectionManager() {
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
// Register for port 443 our SSLSocketFactory with our keystore
// to the ConnectionManager
registry.register(new Scheme("https", newSslSocketFactory(), 443));
return new SingleClientConnManager(getParams(), registry);
}
private SSLSocketFactory newSslSocketFactory() {
try {
// Get an instance of the Bouncy Castle KeyStore format
KeyStore trusted = KeyStore.getInstance("BKS");
// Get the raw resource, which contains the keystore with
// your trusted certificates (root and any intermediate certs)
InputStream in = context.getResources().openRawResource(R.raw.mykeystore);
try {
// Initialize the keystore with the provided trusted certificates
// Also provide the password of the keystore
trusted.load(in, "mysecret".toCharArray());
} finally {
in.close();
}
// Pass the keystore to the SSLSocketFactory. The factory is responsible
// for the verification of the server certificate.
SSLSocketFactory sf = new SSLSocketFactory(trusted);
// Hostname verification from certificate
// http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html#d4e506
sf.setHostnameVerifier(SSLSocketFactory.STRICT_HOSTNAME_VERIFIER);
return sf;
} catch (Exception e) {
throw new AssertionError(e);
}
}
}
Wir haben unseren benutzerdefinierten HttpClient erstellt und können ihn jetzt für sichere Verbindungen verwenden. Zum Beispiel, wenn wir eine REST-Ressource mit GET aufrufen:
// Instantiate the custom HttpClient
DefaultHttpClient client = new MyHttpClient(getApplicationContext());
HttpGet get = new HttpGet("https://www.mydomain.ch/rest/contacts/23");
// Execute the GET call and obtain the response
HttpResponse getResponse = client.execute(get);
HttpEntity responseEntity = getResponse.getEntity();
Das ist es ;)