Android - SSL/TLS и ECC (криптография с эллиптической кривой)
Я разрабатываю приложение для Android, которое взаимодействует с веб-сервером. Мы используем HTTPS для этой связи, и у нас также есть сертификат клиента внутри приложения Android для аутентификации.
Мы создали сертификаты SSL, используя ECC (ANSI x9.62), чтобы иметь очень маленькие сертификаты, чтобы мы могли снизить стоимость передачи во время рукопожатия.
Исходный код для сообщения более или менее похож на это:
InputStream keystoreIs = getResources().openRawResource(R.raw.client_bks);
KeyStore keystore = KeyStore.getInstance("BKS");
keystore.load(keystoreIs, KEYSTORE_PASSWORD);
SSLSocketFactory socketFactory = new SSLSocketFactory(keystore, KEYSTORE_PASSWORD, keystore);
Scheme serverScheme = new Scheme("https", socketFactory, SERVER_PORT);
HttpClient httpclient = new DefaultHttpClient();
httpclient.getConnectionManager().getSchemeRegistry().register(iServerScheme);
HttpPost httppost = new HttpPost(SERVER_URL);
HttpResponse response = httpclient.execute(httppost);
Проблема в том, что когда мы пытаемся подключиться, у нас появляются такие ошибки, как:
E/NativeCrypto(4744): Unknown error 5 during connect
W/System.err(4744): java.io.IOException: SSL handshake failure: I/O error during system call, Connection reset by peer
W/System.err(4744): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.nativeconnect(Native Method)
W/System.err(4744): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:316)
W/System.err(4744): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl$SSLInputStream.<init>(OpenSSLSocketImpl.java:520)
W/System.err(4744): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.getInputStream(OpenSSLSocketImpl.java:461)
W/System.err(4744): at org.apache.http.impl.io.SocketInputBuffer.<init>(SocketInputBuffer.java:93)
W/System.err(4744): at org.apache.http.impl.SocketHttpClientConnection.createSessionInputBuffer(SocketHttpClientConnection.java:83)
W/System.err(4744): at org.apache.http.impl.conn.DefaultClientConnection.createSessionInputBuffer(DefaultClientConnection.java:170)
W/System.err(4744): at org.apache.http.impl.SocketHttpClientConnection.bind(SocketHttpClientConnection.java:106)
W/System.err(4744): at org.apache.http.impl.conn.DefaultClientConnection.openCompleted(DefaultClientConnection.java:129)
(...)
Я попытался найти пример с ECC и SSL, но ничего не нашел. Я нашел несколько статей о шифровании и генерации пар ключей (например, http://nelenkov.blogspot.com/2011/12/using-ecdh-on-android.html), но ничего не связано с этим видом ошибок SSL.
Мы будем благодарны за любые отзывы. Заранее спасибо!!
1 ответ
По умолчанию Android 7.0 SSLSocketFactory
не поддерживает все эллиптические кривые, известные OpenSSL/BoringSSL. Рукопожатие только списки secp256r1
в supported_curves
в клиенте привет.
SSLEngine
документация даже не упоминает поддерживаемые кривые.
Если сервер не может согласиться использовать эту кривую, он закроет соединение, и на стороне клиента произойдет сбой рукопожатия с показанной ошибкой ввода-вывода.
Chrome на Android однако поддерживает 3 общих кривых, secp256r1
, secp384r1
, а также x25519
,
РЕДАКТИРОВАТЬ
Я должен добавить, что расширение поддержки алгоритма хеширования подписи включает в себя ECDSA с SHA1 по SHA512, поэтому можно использовать сертификат ECDSA на стороне сервера.