Intereting Posts
Android с несколькими штрихами в ярлыке xml Как сделать снимок экрана и поделиться им программно Цветной логарифм в студии android от colorpid Android Get VersionName в фрагменте Как проверить имя сертификата и псевдоним в файлах хранилища ключей? Если я изменю внешнюю библиотеку: AndroidManifest, не могу разобрать файл Неверная дата Javascript в iOS / Android 2.2 Невозможно отобразить 2 экземпляра моего пользовательского SurfaceView Диалоговое окно «Диалоговое окно» Изменение сбрасывания с помощью getActivity () Есть ли способ хранения информации о кредитной / дебетовой карте для будущего использования. Использование Android SDK от Braintree Android: вкладки внизу с помощью FragmentTabHost Текстовые изменения меню Android Change Text Textatically GetExtra от Intent, запущенного из ожидающего Политика конфиденциальности Google Play Самый быстрый / простой способ найти методы в Java / Android, которые выполняют второй или более

Отсутствие взаимного авторизации на Android w / javax.net.ssl.SSLHandshakeException: сообщение об ошибке не выполнено

Я пытаюсь получить взаимный запрос на аутентификацию для работы в android. Я тестирую свой сервер, поэтому у меня есть собственный сертификат CA и клиента.

Поэтому мне придется разрешить недоверенный серверный сертификат.

Вот что я делаю:

KeyStore clientCertificate = KeyStore.getInstance("PKCS12"); InputStream client_inputStream = getResources().openRawResource(R.raw.client); clientCertificate.load(client_inputStream, "password".toCharArray()); new SSLRequest(clientCertificate).execute(); 

Затем AsyncTask выполняет запрос:

 class SSLRequest extends AsyncTask<Void, Void, Void> { private Exception exception; private KeyStore clientCertificate; public SSLRequest(KeyStore clientCertificate) { this.clientCertificate = clientCertificate; } protected Void doInBackground(Void... params) { try { KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); trustStore.load(null, null); SSLSocketFactory sf = new SSLSocketFactory(clientCertificate, null, trustStore); HttpParams httpParameters = new BasicHttpParams(); SchemeRegistry schemeRegistry = new SchemeRegistry(); schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); schemeRegistry.register(new Scheme("https", sf, 443)); ClientConnectionManager cm = new SingleClientConnManager(httpParameters, schemeRegistry); DefaultHttpClient httpClient = new DefaultHttpClient(cm, httpParameters); HttpGet request = new HttpGet("https://myserver.com/some.json"); HttpResponse response = httpClient.execute(request); response.getEntity().consumeContent(); } catch (Exception e) { this.exception = e; } return null; } protected void onPostExecute(Void params) { if (exception != null) { status.setText("Error making SSL handshake"); } else { status.setText("Successful SSL handshake"); } } } 

Я протестировал этот запрос в браузере и в iOS-клиенте, но я не могу заставить его работать в Android.

Я думаю, что это правильный способ разрешить ненадежные сертификаты сервера:

 KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); trustStore.load(null, null); SSLSocketFactory sf = new SSLSocketFactory(clientCertificate, "password", trustStore); 

Не знаю, почему я получаю:

javax.net.ssl.SSLPeerUnverifiedException

РЕДАКТИРОВАТЬ:

Я должен был добавить свой собственный SSLSocketFactory, чтобы доверять самоподписанному серверному сертификату:

 public class MySSLSocketFactory extends SSLSocketFactory { SSLContext sslContext = SSLContext.getInstance("TLS"); public MySSLSocketFactory(KeyStore keystore, String keystorePassword, KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException { super(keystore, keystorePassword, truststore); TrustManager trustManager = new X509TrustManager() { public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { } public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { } public X509Certificate[] getAcceptedIssuers() { return null; } }; sslContext.init(null, new TrustManager[] {trustManager}, null); } @Override public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException { return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose); } @Override public Socket createSocket() throws IOException { return sslContext.getSocketFactory().createSocket(); } } 

Как только я использую это, я получаю следующее:

Javax.net.ssl.SSLHandshakeException: сообщение подтверждения не выполнено

EDIT 2:

Я нахожусь на Lollipop и использую apache как мой веб-сервер. Моя конфигурация веб-сервера Apache имеет:

 # SSL Protocol support: # List the enable protocol levels with which clients will be able to # connect. Disable SSLv2 access by default: SSLProtocol all -SSLv2 -SSLv3 # SSL Cipher Suite: # List the ciphers that the client is permitted to negotiate. # See the mod_ssl documentation for a complete list. SSLHonorCipherOrder on SSLCipherSuite "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS" 

Может ли это быть моей проблемой: HttpClient не работает с Handshake Failed в Android 5.0 Lollipop

Не совсем уверен, что мне нужно изменить. Я посмотрел на все, и это, кажется, рекомендуют config (на данный момент).

ИЗМЕНИТЬ 3:

Вот полная трассировка стека:

 06-01 13:23:14.369 24486-24571/mil.nga.giat.handshake W/System.err﹕ javax.net.ssl.SSLHandshakeException: Handshake failed 06-01 13:23:14.369 24486-24571/mil.nga.giat.handshake W/System.err﹕ at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:390) 06-01 13:23:14.369 24486-24571/mil.nga.giat.handshake W/System.err﹕ at com.android.org.conscrypt.OpenSSLSocketImpl.waitForHandshake(OpenSSLSocketImpl.java:623) 06-01 13:23:14.369 24486-24571/mil.nga.giat.handshake W/System.err﹕ at com.android.org.conscrypt.OpenSSLSocketImpl.getInputStream(OpenSSLSocketImpl.java:585) 06-01 13:23:14.369 24486-24571/mil.nga.giat.handshake W/System.err﹕ at org.apache.http.impl.io.SocketInputBuffer.<init>(SocketInputBuffer.java:75) 06-01 13:23:14.369 24486-24571/mil.nga.giat.handshake W/System.err﹕ at org.apache.http.impl.SocketHttpClientConnection.createSessionInputBuffer(SocketHttpClientConnection.java:88) 06-01 13:23:14.369 24486-24571/mil.nga.giat.handshake W/System.err﹕ at org.apache.http.impl.conn.DefaultClientConnection.createSessionInputBuffer(DefaultClientConnection.java:175) 06-01 13:23:14.369 24486-24571/mil.nga.giat.handshake W/System.err﹕ at org.apache.http.impl.SocketHttpClientConnection.bind(SocketHttpClientConnection.java:111) 06-01 13:23:14.371 24486-24571/mil.nga.giat.handshake W/System.err﹕ at org.apache.http.impl.conn.DefaultClientConnection.openCompleted(DefaultClientConnection.java:134) 06-01 13:23:14.371 24486-24571/mil.nga.giat.handshake W/System.err﹕ at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:177) 06-01 13:23:14.371 24486-24571/mil.nga.giat.handshake W/System.err﹕ at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:169) 06-01 13:23:14.371 24486-24571/mil.nga.giat.handshake W/System.err﹕ at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:124) 06-01 13:23:14.372 24486-24571/mil.nga.giat.handshake W/System.err﹕ at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:365) 06-01 13:23:14.372 24486-24571/mil.nga.giat.handshake W/System.err﹕ at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:560) 06-01 13:23:14.372 24486-24571/mil.nga.giat.handshake W/System.err﹕ at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:492) 06-01 13:23:14.372 24486-24571/mil.nga.giat.handshake W/System.err﹕ at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:470) 06-01 13:23:14.372 24486-24571/mil.nga.giat.handshake W/System.err﹕ at mil.nga.giat.handshake.HandshakeActivity$SSLRequest.doInBackground(HandshakeActivity.java:115) 06-01 13:23:14.372 24486-24571/mil.nga.giat.handshake W/System.err﹕ at mil.nga.giat.handshake.HandshakeActivity$SSLRequest.doInBackground(HandshakeActivity.java:85) 06-01 13:23:14.372 24486-24571/mil.nga.giat.handshake W/System.err﹕ at android.os.AsyncTask$2.call(AsyncTask.java:292) 06-01 13:23:14.373 24486-24571/mil.nga.giat.handshake W/System.err﹕ at java.util.concurrent.FutureTask.run(FutureTask.java:237) 06-01 13:23:14.373 24486-24571/mil.nga.giat.handshake W/System.err﹕ at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231) 06-01 13:23:14.373 24486-24571/mil.nga.giat.handshake W/System.err﹕ at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) 06-01 13:23:14.373 24486-24571/mil.nga.giat.handshake W/System.err﹕ at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) 06-01 13:23:14.374 24486-24571/mil.nga.giat.handshake W/System.err﹕ at java.lang.Thread.run(Thread.java:818) 06-01 13:23:14.374 24486-24571/mil.nga.giat.handshake W/System.err﹕ Caused by: javax.net.ssl.SSLProtocolException: SSL handshake terminated: ssl=0xa21b8800: Failure in SSL library, usually a protocol error 06-01 13:23:14.374 24486-24571/mil.nga.giat.handshake W/System.err﹕ error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure (external/openssl/ssl/s3_pkt.c:1303 0xb4b57be0:0x00000003) 06-01 13:23:14.375 24486-24571/mil.nga.giat.handshake W/System.err﹕ at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method) 06-01 13:23:14.375 24486-24571/mil.nga.giat.handshake W/System.err﹕ at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:318) 

Я никогда не ставил сертификат клиента в KeyManager:

  KeyManagerFactory kmf = KeyManagerFactory.getInstance("X509"); kmf.init(keystore, "password".toCharArray()); sslContext.init(kmf.getKeyManagers(), new TrustManager[]{tm}, null); 

Я пытаюсь получить взаимный запрос на аутентификацию для работы в android …

(Комментарий) Сервер CA не установлен на устройстве. Это не обязательно. Для завершения рукопожатия должен быть только сертификат клиента. Вот почему я загружаю нулевую доверенность, чтобы разрешить несертифицированный серверный сертификат.

Хорошо, поэтому самым простым решением является установка CA на устройстве. Я понимаю, что вы не хотите этого делать, и я действительно не виню вас. Это не лучшее решение, потому что оно бросает ваш CA в смесь с другими в CA Zoo.

Поскольку вы все это делаете программно, я считаю, что это ваше решение: используйте PEM Encoded CA Cert для файловой системы напрямую для запроса HTTPS? , Клиент будет проверять сертификат сервера с помощью вашего центра сертификации, а затем продолжить работу с сертификатом клиента. CA не нужно устанавливать на устройство.

Другой альтернативой является пользовательский TrustManager . Но я предпочитаю, чтобы система выполняла проверки, а не переопределяла поведение и проверки. Есть много проверок, которые вы должны выполнить, и они подвержены ошибкам. Во-первых, вы должны знать, какие RFCs пойдут, чтобы выяснить, что такое проверки.

Я буду использовать настраиваемый TrustManager для TrustManager ключа. Есть много примеров этого; См., Например, Сертификат и открытый ключ на сайте OWASP. Вы можете использовать пиннинг и отказаться от проверок, потому что вам не нужно доверять доверие. Вы либо разговариваете с ожидаемым сервером – с открытым ключом X; Или нет – и не имеет значения, что говорит третья сторона (например, CA).


Также имейте в SSLFactory что у SSLFactory Java и Android есть некоторые проблемы, например getInstance("TLS") также вернет SSLv3; И TLS 1.1 и 1.2 будут отключены. Чтобы исправить это, см. Раздел «Какие Cipher Suites для включения SSL-сокета»? ,


Связано с вашим редактированием:

 SSLCipherSuite "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS" 

Обычно это нормально работает:

 HIGH:!aNULL:!kRSA:!MD5:!RC4:!SRP:!PSK 

HIGH даст вам все, что сильно (около 112 бит безопасности и выше).

!aNULL удаляет анонимные протоколы, и !kRSA удаляет !kRSA ключей (но не подписание RSA), поэтому вы !kRSA с Integer и Elliptic Curve Diffie-Hellman. Ниже вы можете увидеть пример подписания RSA с Au=RSA .

HIGH также доставит вам слабый / раненый рывок, например MD5 и RC4 , поэтому вы явно удалите их. Вы также удаляете ненужные комплекты шифров, такие как SRP и PSK .

Вы можете проверить шифры под строкой с openssl ciphers -v 'HIGH:!aNULL:!kRSA:!MD5:!RC4:!SRP:!PSK' :

 $ openssl ciphers -v 'HIGH:!aNULL:!kRSA:!MD5:!RC4:!SRP:!PSK' ECDHE-RSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH Au=RSA Enc=AESGCM(256) Mac=AEAD ECDHE-ECDSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AESGCM(256) Mac=AEAD ECDHE-RSA-AES256-SHA384 TLSv1.2 Kx=ECDH Au=RSA Enc=AES(256) Mac=SHA384 ECDHE-ECDSA-AES256-SHA384 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AES(256) Mac=SHA384 ECDHE-RSA-AES256-SHA SSLv3 Kx=ECDH Au=RSA Enc=AES(256) Mac=SHA1 ECDHE-ECDSA-AES256-SHA SSLv3 Kx=ECDH Au=ECDSA Enc=AES(256) Mac=SHA1 ... 

Кстати, вот ваша строка. В общем, я думаю, это выглядит хорошо. RC4 предоставит вам устаревшие криптографические предупреждения из некоторых браузеров. Просто отбросьте это, так как прописные оракулы в блочных шифрах фиксируются (снова …).

 $ openssl ciphers -v 'EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:EECDH+ECDSA+SHA384:EECDH+ECDSA+SHA256:EECDH+aRSA+SHA384: \ EECDH+aRSA+SHA256:EECDH+aRSA+RC4:EECDH:EDH+aRSA:RC4:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS' ECDHE-ECDSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AESGCM(256) Mac=AEAD ECDHE-ECDSA-AES128-GCM-SHA256 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AESGCM(128) Mac=AEAD ECDHE-RSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH Au=RSA Enc=AESGCM(256) Mac=AEAD ECDHE-RSA-AES128-GCM-SHA256 TLSv1.2 Kx=ECDH Au=RSA Enc=AESGCM(128) Mac=AEAD ECDHE-ECDSA-AES256-SHA384 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AES(256) Mac=SHA384 ECDHE-ECDSA-AES128-SHA256 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AES(128) Mac=SHA256 ECDHE-RSA-AES256-SHA384 TLSv1.2 Kx=ECDH Au=RSA Enc=AES(256) Mac=SHA384 ECDHE-RSA-AES128-SHA256 TLSv1.2 Kx=ECDH Au=RSA Enc=AES(128) Mac=SHA256 ECDHE-RSA-RC4-SHA SSLv3 Kx=ECDH Au=RSA Enc=RC4(128) Mac=SHA1 ECDHE-RSA-AES256-SHA SSLv3 Kx=ECDH Au=RSA Enc=AES(256) Mac=SHA1 ECDHE-ECDSA-AES256-SHA SSLv3 Kx=ECDH Au=ECDSA Enc=AES(256) Mac=SHA1 ECDHE-RSA-AES128-SHA SSLv3 Kx=ECDH Au=RSA Enc=AES(128) Mac=SHA1 ECDHE-ECDSA-AES128-SHA SSLv3 Kx=ECDH Au=ECDSA Enc=AES(128) Mac=SHA1 ECDHE-ECDSA-RC4-SHA SSLv3 Kx=ECDH Au=ECDSA Enc=RC4(128) Mac=SHA1 DHE-RSA-AES256-GCM-SHA384 TLSv1.2 Kx=DH Au=RSA Enc=AESGCM(256) Mac=AEAD DHE-RSA-AES256-SHA256 TLSv1.2 Kx=DH Au=RSA Enc=AES(256) Mac=SHA256 DHE-RSA-AES256-SHA SSLv3 Kx=DH Au=RSA Enc=AES(256) Mac=SHA1 DHE-RSA-CAMELLIA256-SHA SSLv3 Kx=DH Au=RSA Enc=Camellia(256) Mac=SHA1 DHE-RSA-AES128-GCM-SHA256 TLSv1.2 Kx=DH Au=RSA Enc=AESGCM(128) Mac=AEAD DHE-RSA-AES128-SHA256 TLSv1.2 Kx=DH Au=RSA Enc=AES(128) Mac=SHA256 DHE-RSA-AES128-SHA SSLv3 Kx=DH Au=RSA Enc=AES(128) Mac=SHA1 DHE-RSA-SEED-SHA SSLv3 Kx=DH Au=RSA Enc=SEED(128) Mac=SHA1 DHE-RSA-CAMELLIA128-SHA SSLv3 Kx=DH Au=RSA Enc=Camellia(128) Mac=SHA1 ECDH-RSA-RC4-SHA SSLv3 Kx=ECDH/RSA Au=ECDH Enc=RC4(128) Mac=SHA1 ECDH-ECDSA-RC4-SHA SSLv3 Kx=ECDH/ECDSA Au=ECDH Enc=RC4(128) Mac=SHA1 RC4-SHA SSLv3 Kx=RSA Au=RSA Enc=RC4(128) Mac=SHA1