Javax.net.ssl.SSLException: SSL handshake canceled on older Android devices

I have an Android app that works great for most devices. Recently, some hackers tried to do a DDOS attack on our servers, which forced us to add some security and some firewalls.

not all devices work and give me the following exception.

javax.net.ssl.SSLException: SSL handshake aborted: ssl=0x63eb8240: I/O error during system call, Connection reset by peer 

Can someone please tell me what the problem is and how can I solve it?

EDIT

this is the code of my execution method

 public static BaseResponse execute(Context context, BaseRequest request) { mStartTime = System.nanoTime(); BaseResponse response = new BaseResponse(); DataOutputStream outputStream; try { URL url = new URL(request.getURL()); HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection(); urlConnection.setConnectTimeout(TIMEOUT_DURATION); urlConnection.setReadTimeout(TIMEOUT_DURATION); urlConnection.setRequestMethod(request.getRequestType().getValue()); urlConnection.addRequestProperty("Accept", "application/json"); urlConnection.addRequestProperty("Content-Type","application/json"); urlConnection.setRequestProperty("Accept-Charset", CHARACTER_SET); urlConnection.addRequestProperty("Device-Id", PhoneUtils.getDeviceId(context)); urlConnection.addRequestProperty("Version-Number", PhoneUtils.getAppVersion(context)); TLSSocketFactory socketFactory = new TLSSocketFactory(); urlConnection.setSSLSocketFactory(socketFactory); switch (request.getRequestType()) { case POST: case PUT: urlConnection.setDoOutput(true); if (request.getStringEntity() != null) { outputStream = new DataOutputStream(urlConnection.getOutputStream()); BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream, CHARACTER_SET)); writer.write(request.getStringParam()); writer.close(); outputStream.flush(); outputStream.close(); } break; case GET: urlConnection.setDoOutput(false); break; } urlConnection.connect(); try { if (urlConnection.getResponseCode() == STATUS_OK) { InputStream inputStream = new BufferedInputStream(urlConnection.getInputStream()); BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); StringBuilder result = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { result.append(line); } inputStream.close(); response.setResponse(convertStringToJSONObject(result.toString())); } else { response.setResponse(null); } } catch (Exception ex) { response.setAppError(AppError.DATA_ERROR); } } catch (MalformedURLException e) { e.printStackTrace(); response.setAppError(AppError.PARSING_ERROR); } catch (IOException e) { e.printStackTrace(); response.setAppError(AppError.DATA_ERROR); } catch (Exception e) { e.printStackTrace(); response.setAppError(AppError.DATA_ERROR); } return response; } 
+6
source share
2 answers

Use this in your code before making any network call.

 /** * Initialize SSL * @param mContext */ public static void initializeSSLContext(Context mContext){ try { SSLContext.getInstance("TLSv1.2"); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } try { ProviderInstaller.installIfNeeded(mContext.getApplicationContext()); } catch (GooglePlayServicesRepairableException e) { e.printStackTrace(); } catch (GooglePlayServicesNotAvailableException e) { e.printStackTrace(); } } 

I had the same problem and this piece of code solved my problem. FYI: I used a modified library to create network calls.

+17
source

Different levels of the Android API have different support for SSL / TLS protocol versions, see the documentation for Android for details - https://developer.android.com/reference/javax/net/ssl/SSLSocket.html

To enable TLS 1.1 and 1.2, you need to create your own SSLSocketFactory - https://blog.dev-area.net/2015/08/13/android-4-1-enable-tls-1-1-and-tls-1 -2 /

 public class TLSSocketFactory extends SSLSocketFactory { private SSLSocketFactory internalSSLSocketFactory; public TLSSocketFactory() throws KeyManagementException, NoSuchAlgorithmException { SSLContext context = SSLContext.getInstance("TLS"); context.init(null, null, null); internalSSLSocketFactory = context.getSocketFactory(); } @Override public String[] getDefaultCipherSuites() { return internalSSLSocketFactory.getDefaultCipherSuites(); } @Override public String[] getSupportedCipherSuites() { return internalSSLSocketFactory.getSupportedCipherSuites(); } @Override public Socket createSocket() throws IOException { return enableTLSOnSocket(internalSSLSocketFactory.createSocket()); } @Override public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException { return enableTLSOnSocket(internalSSLSocketFactory.createSocket(s, host, port, autoClose)); } @Override public Socket createSocket(String host, int port) throws IOException, UnknownHostException { return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port)); } @Override public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException { return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port, localHost, localPort)); } @Override public Socket createSocket(InetAddress host, int port) throws IOException { return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port)); } @Override public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException { return enableTLSOnSocket(internalSSLSocketFactory.createSocket(address, port, localAddress, localPort)); } private Socket enableTLSOnSocket(Socket socket) { if(socket != null && (socket instanceof SSLSocket)) { ((SSLSocket)socket).setEnabledProtocols(new String[] {"TLSv1.1", "TLSv1.2"}); } return socket; } } 

And then use it in your mix

 HttpsURLConnection conn = (HttpsURLConnection) url.openConnection(); TLSSocketFactory socketFactory = new TLSSocketFactory(); conn.setSSLSocketFactory(socketFactory); conn.connect(); 
+2
source

Source: https://habr.com/ru/post/1015295/


All Articles