SSL / TLS-Protokolle und Cipher Suites mit dem AndroidHttpClient

8

EDIT: Entschuldigung, wenn mein ursprünglicher Beitrag schlecht formuliert war. Es führte zu einiger Verwirrung, die durch Kommentare zum ursprünglichen Beitrag dargestellt wird. Also lass es mich nochmal versuchen:

Ich habe mit einer Frage angefangen. Ich wollte ein Problem auf Android lösen, wusste aber nicht wie. Ich habe viel Zeit damit verbracht, im Internet nach Lösungen zu suchen, fand aber nirgendwo eine einzige Diskussion. Nichtsdestotrotz führte mich eine Reihe von Diskussionen, einschließlich StackOverflow-Threads, zu einer Technik, die vielversprechend aussah. Ich habe das Problem gelöst. Aber die Lösung war ein wenig beteiligt. Also habe ich mich entschieden, die Frage hier zu stellen und a) es muss eine bessere Lösung geben, und hoffentlich wird jemand die Antwort hier wissen und posten; oder b) vielleicht ist das eine gute Lösung, und da ich nirgends sonst im Internet eine Diskussion über die Angelegenheit fand, wäre meine Lösung des Problems vielleicht nützlich für andere, die versuchen, dasselbe zu tun. So oder so, das Ergebnis wäre ein neuer Beitrag zu StackOverflow: eine Frage, die anderswo nicht beantwortet wird, mit der richtigen Antwort auf die eine oder andere Weise. Tatsächlich hat mich StackOverflow sogar dazu eingeladen, meine eigene Frage zu beantworten, indem ich mein Wissen teilte, als ich es ursprünglich gepostet habe. Das war in der Tat Teil meiner Motivation. Auch die Fakten dieser Angelegenheit sind nirgends gesammelt, die ich gefunden habe.

Also:

Q. Wie kann ich bei Verwendung des AndroidHttpClient für die Ausführung von REST-Anforderungen über HTTPS angeben, welche SSL-Protokolle und -Chipherien verwendet werden sollen?

Das ist wichtig. Der Punkt ist gut, dass es viel gibt, was auf dem Server getan werden kann, aber es gibt Grenzen. Derselbe Server muss Browser, einschließlich der alten, sowie anderer Clients bedienen. Das bedeutet, dass der Server eine breite Palette von Protokollen und Verschlüsselungen unterstützen muss. Selbst wenn Sie innerhalb von Android viele verschiedene Versionen unterstützen müssen, müssen Sie eine Reihe verschiedener Protokolle und Verschlüsselungen unterstützen.

Wichtiger ist, dass OpenSSL standardmäßig die Verschlüsselungseinstellung des Clients, nicht , während des SSL-Handshakes berücksichtigt. Sehen Sie sich zum Beispiel posten an, das besagt, dass Sie dieses Verhalten im Client überschreiben können, indem Sie SSL_OP_CIPHER_SERVER_PREFERENCE festlegen. Es ist nicht ganz klar, ob diese Option auch auf einem SSLSocket in Java gesetzt werden kann. Auch wenn dies möglich ist, können Sie die Verschlüsselungsliste selbst festlegen oder Ihrem Client mitteilen, dass er die Serverliste berücksichtigen soll. Andernfalls erhalten Sie die Android-Standardeinstellung, unabhängig davon, für welche Version Sie die Version verwenden (nicht die Version, für die Sie eine Verknüpfung herstellen).

Wenn Sie die Standardwerte verwenden, wird die vom Client an den Server von einem Jellybean 4.2 + -Client gesendete Präferenzliste hier , beginnend bei Zeile 504. Die Standardliste von Protokollen beginnt bei Zeile 620. Obwohl Jellybean 4.2 + enthält Unterstützung für OpenSSL 1.0.1, insbesondere TLSv1.1 und TLSv1.2, diese Protokolle sind standardmäßig nicht aktiviert. Wenn Sie etwas nicht tun, was ich getan habe, können Sie die TLSv1.2-Unterstützung nicht nutzen, obwohl die Unterstützung für TLSv1.2 in den neuesten Versionen von Android angekündigt wird. Und die Details variieren ziemlich, wenn Sie frühere Android-Versionen verwenden. Zumindest möchten Sie vielleicht die Standardeinstellungen aller unterstützten Versionen genau betrachten und sehen, was Ihr Client tatsächlich macht. Sie könnten überrascht sein.

Es gibt viel mehr, was Sie über die Unterstützung für verschiedene Protokolle und Verschlüsselungen sagen können. Der Punkt ist, dass es manchmal notwendig sein kann, diese Einstellungen in einem Client zu ändern.

A. Verwenden Sie eine benutzerdefinierte SSLSocketFactory

Das hat gut für mich funktioniert, und am Ende war es nicht sehr viel Code. Aber es war ein wenig dornig für eine Reihe von Gründen:

  • Es gibt zwei verschiedene SSLSocketFactory-Klassen. Der Kunde benötigt ein org.apache.http.conn.ssl.SSLSocketFactory, aber OpenSSL gibt a zurück javax.net.ssl.SSLSocketFactory. Das ist definitiv verwirrend. ich benutzte Delegation, um den einen den anderen ohne viel Problem zu nennen.
  • Achten Sie auf den Unterschied zwischen dem OpenSSLContextImpl und dem SSLContextImpl. Der eine wickelt den anderen einfach ein, aber das ist er nicht austauschbar. Als ich das benutzt habe SSLContextImpl.engineGetSocketFactory-Methode - ich vergesse was genau ist passiert, aber etwas ist gescheitert. Verwenden Sie unbedingt ein OpenSSLContextImpl, um Ihre Socket-Factory zu erhalten, kein SSLContextImpl. Sie können möglicherweise auch verwenden javax.net.ssl.SSLSocketFactory.getDefault (), aber ich bin mir nicht sicher.
  • Sie können AndroidHttpClient nicht leicht von der Unterklasse ableiten, da sein Konstruktor ist Privatgelände. Dies ist bedauerlich, da es einige andere schöne bietet Goodies, wie stellen Sie sicher, dass Sie es ordnungsgemäß herunterfahren statt undichte Ressourcen. Der DefaultHttpClient funktioniert gut. Ich lieh die newInstance-Methode von AndroidHttpClient (um Zeile 105).

Die wichtigsten Punkte:

%Vor%

Dann:

%Vor%

Unter Android 3.0 (Honeycomb / SDK 11) sind die unterstützten Verschlüsselungsoptionen begrenzter und es gibt weniger Motivation, die Standardeinstellungen zu überschreiben. Auf FROYO / SDK 8, meine SecureSocketFactory explodiert aus irgendeinem Grund, und die Jury ist auf 10 hinaus. Aber es scheint für 11 aufwärts funktionieren gut.

Die vollständige Lösung befindet sich in einem öffentlichen GitHub Repo .

Eine andere Lösung könnte darin bestehen, eine HttpsUrlConnection zu verwenden, die die Verwendung einer benutzerdefinierten Socket-Factory vereinfacht, aber ich nehme an, dass Sie wahrscheinlich noch mehr von der Bequemlichkeit des High-Level-HTTP-Clients verlieren werden. Ich habe keine Erfahrung mit HttpsUrlConnection.

    
Jimmy Dee 30.08.2013, 02:03
quelle

1 Antwort

1
  

Wie kann ich bei der Verwendung von AndroidHttpClient für REST-Anforderungen über HTTPS angeben, welche SSL-Protokolle und -Chips verwendet werden sollen?

Ich glaube nicht, dass du es mit AndroidHttpClient schaffen kannst. Alles, was ich getan habe, um den Kanal zu härten (wie Chiffre-Listen, Zertifikats-Pinning und Public-Key-Pinning), erforderte irgendwo eine benutzerdefinierte Klasse, egal ob es SSLSocketFactory oder X509TrustManager war. Das ist Java und das ist Android. Siehe Wie überschreiben die Cipherlist, die von Android an den Server gesendet wird, wenn HttpsURLConnection verwendet wird? .

    
jww 02.12.2013, 01:07
quelle

Tags und Links