2017-10-06 97 views
0

它给这个SSLhandshakeException。当应用程序在Android5.1上运行(android版本> = 4.4)时,它会发出异常。我在Android 4.3上测试它,它工作正常。这可能是什么原因?请帮助Android 5.1.1 SSL例程:SSL23_GET_SERVER_HELLO:sslv3警报握手故障

W/System.err(14221): javax.net.ssl.SSLHandshakeException: Handshake failed 
W/System.err(14221): at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:390) 
W/System.err(14221): at com.android.org.conscrypt.OpenSSLSocketImpl.waitForHandshake(OpenSSLSocketImpl.java:623) 
W/System.err(14221): at com.android.org.conscrypt.OpenSSLSocketImpl.getInputStream(OpenSSLSocketImpl.java:585) 
W/System.err(14221): at org.apache.http.impl.io.SocketInputBuffer.<init>(SocketInputBuffer.java:75) 
W/System.err(14221): at org.apache.http.impl.SocketHttpClientConnection.createSessionInputBuffer(SocketHttpClientConnection.java:88) 
W/System.err(14221): at org.apache.http.impl.conn.DefaultClientConnection.createSessionInputBuffer(DefaultClientConnection.java:175) 
W/System.err(14221): at org.apache.http.impl.SocketHttpClientConnection.bind(SocketHttpClientConnection.java:111) 
W/System.err(14221): at org.apache.http.impl.conn.DefaultClientConnection.openCompleted(DefaultClientConnection.java:134) 
W/System.err(14221): at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:177) 
W/System.err(14221): at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:169) 
W/System.err(14221): at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:124) 
W/System.err(14221): at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:365) 
W/System.err(14221): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:768) 
W/System.err(14221): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:700) 
W/System.err(14221): at com.up.testjavasdkdemo.ssltest.HttpHandler.makeRequestWithRetries(HttpHandler.java:75) 
W/System.err(14221): at com.up.testjavasdkdemo.ssltest.HttpHandler.doInBackground(HttpHandler.java:132) 
W/System.err(14221): at android.os.AsyncTask$2.call(AsyncTask.java:292) 
W/System.err(14221): at java.util.concurrent.FutureTask.run(FutureTask.java:237) 
W/System.err(14221): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) 
W/System.err(14221): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) 
W/System.err(14221): at java.lang.Thread.run(Thread.java:818) 
W/System.err(14221): Caused by: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0xb7c985b0: Failure in SSL library, usually a protocol error 
W/System.err(14221): error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure (external/openssl/ssl/s23_clnt.c:770 0xae157cc5:0x00000000) 
W/System.err(14221): at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method) 
W/System.err(14221): at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:318) 
W/System.err(14221): ... 20 more 
I/SSLTest (14221): onFailure:javax.net.ssl.SSLHandshakeException: Handshake failed strMsg:Handshake failed 
W/System.err(14221): javax.net.ssl.SSLHandshakeException: Handshake failed 
W/System.err(14221): at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:390) 
W/System.err(14221): at com.android.org.conscrypt.OpenSSLSocketImpl.waitForHandshake(OpenSSLSocketImpl.java:623) 
W/System.err(14221): at com.android.org.conscrypt.OpenSSLSocketImpl.getInputStream(OpenSSLSocketImpl.java:585) 
W/System.err(14221): at org.apache.http.impl.io.SocketInputBuffer.<init>(SocketInputBuffer.java:75) 
W/System.err(14221): at org.apache.http.impl.SocketHttpClientConnection.createSessionInputBuffer(SocketHttpClientConnection.java:88) 
W/System.err(14221): at org.apache.http.impl.conn.DefaultClientConnection.createSessionInputBuffer(DefaultClientConnection.java:175) 
W/System.err(14221): at org.apache.http.impl.SocketHttpClientConnection.bind(SocketHttpClientConnection.java:111) 
W/System.err(14221): at org.apache.http.impl.conn.DefaultClientConnection.openCompleted(DefaultClientConnection.java:134) 
W/System.err(14221): at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:177) 
W/System.err(14221): at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:169) 
W/System.err(14221): at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:124) 
W/System.err(14221): at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:365) 
W/System.err(14221): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:768) 
W/System.err(14221): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:700) 
W/System.err(14221): at com.up.testjavasdkdemo.ssltest.HttpHandler.makeRequestWithRetries(HttpHandler.java:75) 
W/System.err(14221): at com.up.testjavasdkdemo.ssltest.HttpHandler.doInBackground(HttpHandler.java:132) 
W/System.err(14221): at android.os.AsyncTask$2.call(AsyncTask.java:292) 
W/System.err(14221): at java.util.concurrent.FutureTask.run(FutureTask.java:237) 
W/System.err(14221): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) 
W/System.err(14221): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) 
W/System.err(14221): at java.lang.Thread.run(Thread.java:818) 
W/System.err(14221): Caused by: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0xb7c985b0: Failure in SSL library, usually a protocol error 
W/System.err(14221): error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure (external/openssl/ssl/s23_clnt.c:770 0xae157cc5:0x00000000) 
W/System.err(14221): at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method) 
W/System.err(14221): at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:318) 
W/System.err(14221): ... 20 more 
+0

你能格式化你的问题并在这里发表你的代码吗? –

+0

@Dima Kozhevin。是的,我做了一个自定义的socketFactory类,名为SSLSocketFactoryEx.java –

+0

何浩,我已经解决了这个问题。 –

回答

-1
I made a custom socketFactory class called SSLSocketFactoryEx.java 

import com.android.org.bouncycastle.util.encoders.Base64; 
import com.pos.hsm.PKCS11Wrapper; 

import java.io.ByteArrayInputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.lang.reflect.Field; 
import java.net.InetAddress; 
import java.net.Socket; 
import java.net.UnknownHostException; 
import java.security.KeyFactory; 
import java.security.KeyManagementException; 
import java.security.KeyStore; 
import java.security.KeyStoreException; 
import java.security.NoSuchAlgorithmException; 
import java.security.NoSuchProviderException; 
import java.security.PrivateKey; 
import java.security.Principal; 
import java.security.UnrecoverableKeyException; 
import java.security.cert.CertificateException; 
import java.security.cert.CertificateFactory; 
import java.security.cert.X509Certificate; 
import java.security.spec.PKCS8EncodedKeySpec; 
import java.util.regex.Matcher; 
import java.util.regex.Pattern; 

import javax.net.ssl.KeyManager; 
import javax.net.ssl.KeyManagerFactory; 
import javax.net.ssl.SSLContext; 
import javax.net.ssl.SSLSocket; 
import javax.net.ssl.TrustManager; 
import javax.net.ssl.TrustManagerFactory; 
import javax.net.ssl.X509KeyManager; 
import javax.net.ssl.X509TrustManager; 

import org.apache.http.conn.ssl.SSLSocketFactory; 
import Decoder.BASE64Decoder; 

import android.content.Context; 
import android.content.res.AssetManager; 
//import org.apache.commons.codec.binary.Base64; 
import android.util.Log; 
public class SSLSocketFactoryEx extends SSLSocketFactory {  
    private static final String[] TLS_SUPPORT_VERSION = {"TLSv1.1", "TLSv1.2"};//Android 5.1 default enable SSLv3 

    SSLContext sslContext =SSLContext.getInstance("SSL"); 
    public SSLSocketFactoryEx(final Context context, KeyStore truststore)  
      throws NoSuchAlgorithmException, KeyManagementException,  
      KeyStoreException, UnrecoverableKeyException { 
     super(truststore); 

     TrustManager trustManager = new X509TrustManager() { 

      public java.security.cert.X509Certificate[] getAcceptedIssuers() { 
       logwarn("alias =========getAcceptedIssuers===== "); 
       return new X509Certificate[0];  
      }  

      @Override  
      public void checkClientTrusted(  
        java.security.cert.X509Certificate[] chain, String authType)  
        throws java.security.cert.CertificateException { 
       logwarn("=====================checkServerTrusted==================="); 
       if(chain != null)logwarn("length = " + chain.length); 
       try { 
        CertificateFactory factory = CertificateFactory.getInstance("X.509"); 
        X509Certificate cert = null; 
        X509Certificate ca; 
        ByteArrayInputStream bais; 

        if(chain != null && chain.length > 0){ 
         bais = new ByteArrayInputStream(chain[0].getEncoded()); 
         cert = (X509Certificate) factory.generateCertificate(bais); 
         bais.close(); 
        } else { 
         throw new CertificateException("There is no certificate"); 
        } 
        byte[] trust = RSASignature.readFileByBytes(context, "trust01.crt"); 
        logwarn("trust cert = " + new String(trust)); 
        bais = new ByteArrayInputStream(trust); 
        CertificateFactory myCertificateFactory; 
        ca = (X509Certificate)factory.generateCertificate(bais); 
        bais.close(); 
        cert.verify(ca.getPublicKey()); 
       }catch (Exception e){ 
        logwarn("TrustManager checkServerTrusted failed!"); 
        e.printStackTrace(); 
        throw new CertificateException(e); 
       } 
      } 

      @Override  
      public void checkServerTrusted(  
        java.security.cert.X509Certificate[] chain, String authType)  
        throws java.security.cert.CertificateException {  
       logwarn("=====================checkServerTrusted==================="); 
       if(chain != null)logwarn("length = " + chain.length); 
       try { 
        CertificateFactory factory = CertificateFactory.getInstance("X.509"); 
        X509Certificate cert = null; 
        X509Certificate ca; 
        ByteArrayInputStream bais; 
        if(chain != null && chain.length > 0){ 
         bais = new ByteArrayInputStream(chain[0].getEncoded()); 
         cert = (X509Certificate) factory.generateCertificate(bais); 
         bais.close(); 
        } else { 
         throw new CertificateException("There is no certificate"); 
        } 
        byte[] trust = RSASignature.readFileByBytes(context, "trust01.crt"); 
        logwarn("trust cert = " + new String(trust)); 
        bais = new ByteArrayInputStream(trust); 
        CertificateFactory myCertificateFactory; 
        ca = (X509Certificate)factory.generateCertificate(bais); 
        bais.close(); 
        cert.verify(ca.getPublicKey()); 
       }catch (Exception e){ 
        logwarn("TrustManager checkServerTrusted failed!"); 
        e.printStackTrace(); 
        throw new CertificateException(e); 
       } 
      }  
     }; 
     X509KeyManager keyManager = new X509KeyManager() { 
      @Override 
      public String chooseClientAlias(String[] keyType, Principal[] issuers, Socket socket) { 

       logwarn("=====================chooseClientAlias==================="); 
       if(keyType != null && keyType.length > 0){ 
        for(int i = 0; i < keyType.length; i++){ 
         logwarn("keyType["+i+"]=" + keyType[i]); 
        } 
       } 
       if(issuers != null && issuers.length > 0){ 
        for(int i = 0; i < issuers.length; i++){ 
         logwarn("issuers["+i+"]=" + issuers[i].getName()); 
        } 
       } 
       return "pk2048"; 
      } 

      @Override 
      public String chooseServerAlias(String keyType, Principal[] issuers, Socket socket) { 
       logwarn("=====================chooseServerAlias==================="); 
       logwarn("keyType================" + keyType); 
       if(issuers != null && issuers.length > 0){ 
        for(int i = 0; i < issuers.length; i++){ 
         logwarn("issuers["+i+"]=" + issuers[i].getName()); 
        } 
       } 
       return "trust01"; 
      } 

      @Override 
      public X509Certificate[] getCertificateChain(String alias) { 
       logwarn("=====================getCertificateChain==================="); 
       logwarn("alias ============== " + alias); 
       byte[] publickey = RSASignature.readFileByBytes(context, "client2048.crt"); 
       InputStream ceris = new ByteArrayInputStream(publickey); 
       CertificateFactory myCertificateFactory; 
       try { 
        myCertificateFactory = CertificateFactory.getInstance("X.509"); 
        X509Certificate cer = (X509Certificate)myCertificateFactory.generateCertificate(ceris); 
        ceris.close(); 
        return new X509Certificate[]{cer}; 
       } catch (Exception e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       } 
       return new X509Certificate[0]; 
      } 

      @Override 
      public String[] getClientAliases(String keyType, Principal[] issuers) { 
       logwarn("=====================getClientAliases==================="); 
       logwarn("keyType================" + keyType); 
       if(issuers != null && issuers.length > 0){ 
        for(int i = 0; i < issuers.length; i++){ 
         logwarn("issuers["+i+"]=" + issuers[i].getName()); 
        } 
       } 
       return new String[0]; 
      } 

      @Override 
      public String[] getServerAliases(String keyType, Principal[] issuers) { 
       logwarn("=====================getServerAliases==================="); 
       logwarn("keyType================" + keyType); 
       if(issuers != null && issuers.length > 0){ 
        for(int i = 0; i < issuers.length; i++){ 
         logwarn("issuers["+i+"]=" + issuers[i].getName()); 
        } 
       } 
       return new String[0]; 
      } 

      @Override 
      public PrivateKey getPrivateKey(String alias) { 
       logwarn("=====================getPrivateKey==================="); 
       logwarn("alias ============== " + alias); 
       byte[] keyData = RSASignature.readFileByBytes(context, alias + ".crt"); 
       String keyString = new String(keyData); 
       keyString = keyString.replaceAll("\n", ""); 
       Pattern pattern =Pattern.compile("-----BEGIN RSA PRIVATE KEY-----(.*?)-----END RSA PRIVATE KEY-----"); 
       Matcher matcher=pattern.matcher(keyString); 
       while (matcher.find()) { 
        keyData = matcher.group(1).getBytes(); 
       } 
       try { 
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(Base64.decode(keyData));//PKCS8EncodedKeySpec(Base64.decodeBase64(keyData)); 
        KeyFactory keyFactory = KeyFactory.getInstance("RSA","BC"); 
        PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec); 
        return privateK; 
       }catch (Exception e){ 
        e.printStackTrace(); 
       } 
       return null; 
      } 
     }; 
     //sslContext.init(null, new TrustManager[] { tm }, null); 
     sslContext.init(new KeyManager[]{keyManager}, new TrustManager[]{trustManager}, null); 

    }  

    @Override  
    public Socket createSocket(Socket socket, String host, int port,  
      boolean autoClose) throws IOException, UnknownHostException { 
     //injectHostname(socket, host); 
     SSLSocket S = (SSLSocket) sslContext.getSocketFactory().createSocket(socket, host, port, autoClose); 
     String[] enProtocols = S.getEnabledProtocols(); 
     for (String cipherSuite : enProtocols) { 
      logwarn("enProtocols ====c========== " + cipherSuite); 
      } 
     String[] Protocols = S.getSupportedProtocols(); 
     for (String cipherSuite : Protocols) { 
      logwarn("Protocols ====c========== " + cipherSuite); 
      } 
     S.setEnabledProtocols(TLS_SUPPORT_VERSION); 
     enProtocols = S.getEnabledProtocols(); 
     for (String cipherSuite : enProtocols) { 
      logwarn("enProtocols ====en========== " + cipherSuite); 
      } 
     Protocols = S.getSupportedProtocols(); 
     for (String cipherSuite : Protocols) { 
      logwarn("Protocols ====add========== " + cipherSuite); 
      } 
     String[] original =S.getEnabledCipherSuites(); 
     for (String cipherSuite : original) { 
      logwarn("cipherSuite ====c========== " + cipherSuite); 
      } 
     return sslContext.getSocketFactory().createSocket(socket, host, port,  
       autoClose);  
    }  
    private void injectHostname(Socket socket, String host) { 
     try { 
      Field field = InetAddress.class.getDeclaredField("hostName"); 
      field.setAccessible(true); 
      field.set(socket.getInetAddress(), host); 
     } catch (Exception ignored) { 
      ignored.printStackTrace(); 
     } 
    } 
    @Override  
    public Socket createSocket() throws IOException { 
     SSLSocket S = (SSLSocket) sslContext.getSocketFactory().createSocket(); 
     S.setEnabledProtocols(TLS_SUPPORT_VERSION); 
     String[] original =S.getEnabledCipherSuites(); 
     for (String cipherSuite : original) { 
      logwarn("cipherSuite ============== " + cipherSuite); 
      } 
     return sslContext.getSocketFactory().createSocket();  
    } 
    void logwarn(String msg) { 
     Log.d("AndroidSSLSocketFactory", msg); 
    } 
} 
+2

如果这是你的问题的答案,而不是显示什么是解决问题的相关部分,而不是仅仅倾销一堆代码。如果这是对问题的补充信息,请将其包含在问题中。但请注意,如果您只需转储一堆代码,那么问题可能会很快被解决 - 而不是制作[__Minimal__,Complete和Verifiable示例](https://stackoverflow.com/help/mcve)。 –

0
Use this class like this while connecting : 

public void httpEX(Context context) throws Exception { 
      KeyStore trustStore = KeyStore.getInstance(KeyStore 
        .getDefaultType()); 
      trustStore.load(null, null); 

      SSLSocketFactory sf= new SSLSocketFactoryEx(context, trustStore); 

     BasicHttpParams httpParams = new BasicHttpParams(); 

     ConnManagerParams.setTimeout(httpParams, socketTimeout); 
     ConnManagerParams.setMaxConnectionsPerRoute(httpParams, new ConnPerRouteBean(maxConnections)); 
     ConnManagerParams.setMaxTotalConnections(httpParams, 10); 

     HttpConnectionParams.setSoTimeout(httpParams, socketTimeout); 
     HttpConnectionParams.setConnectionTimeout(httpParams, socketTimeout); 
     HttpConnectionParams.setTcpNoDelay(httpParams, true); 
     HttpConnectionParams.setSocketBufferSize(httpParams, DEFAULT_SOCKET_BUFFER_SIZE); 

     HttpProtocolParams.setVersion(httpParams, HttpVersion.HTTP_1_1); 

     SchemeRegistry schemeRegistry = new SchemeRegistry(); 
     schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); 
     schemeRegistry.register(new Scheme("https", sf, 443)); 
     ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager(httpParams, schemeRegistry); 
     httpContext = new SyncBasicHttpContext(new BasicHttpContext()); 



     httpClient = new DefaultHttpClient(cm, httpParams); 

     httpClient.addRequestInterceptor(new HttpRequestInterceptor() { 
      public void process(HttpRequest request, HttpContext context) { 
       if (!request.containsHeader(HEADER_ACCEPT_ENCODING)) { 
        request.addHeader(HEADER_ACCEPT_ENCODING, ENCODING_GZIP); 
       } 
       for (String header : clientHeaderMap.keySet()) { 
        request.addHeader(header, clientHeaderMap.get(header)); 
       } 
      } 
     }); 

     httpClient.addResponseInterceptor(new HttpResponseInterceptor() { 
      public void process(HttpResponse response, HttpContext context) { 
       final HttpEntity entity = response.getEntity(); 
       if (entity == null) { 
        return; 
       } 
       final Header encoding = entity.getContentEncoding(); 
       if (encoding != null) { 
        for (HeaderElement element : encoding.getElements()) { 
         if (element.getName().equalsIgnoreCase(ENCODING_GZIP)) { 
          response.setEntity(new InflatingEntity(response.getEntity())); 
          break; 
         } 
        } 
       } 
      } 
     }); 

     clientHeaderMap = new HashMap<String, String>(); 
    } 
0

哈,哈,ho.I有固定的这个question.Android 5.1默认禁用SSL_RSA_WITH_RC4_128_MD5密码套件。 我需要昌SSLSocketFactoryEx.java类中,实现该方法:`@Override
公共插座的createSocket(Socket套接字,字符串主机,INT端口,
布尔自动关闭)抛出IOException异常,UnknownHostException异常{ SSLSocket的S =(SSLSocket的)的SSLContext。 getSocketFactory()。createSocket(socket,host,port,autoClose);

String[] availableCiphers =S.getEnabledCipherSuites(); 
    for (String cipherSuite : availableCiphers) { 
     logwarn("cipherSuite ====c========== " + cipherSuite); 
     } 
    List<String> aa = new ArrayList<String>(); 

    for(int i = 0; i < availableCiphers.length; i++) 
    { 
     aa.add(availableCiphers[i]); 
    } 
    aa.add("SSL_RSA_WITH_RC4_128_MD5"); 
    aa.add("TLS_EMPTY_RENEGOTIATION_INFO_SCSV"); 
    String[] m_ciphers = aa.toArray(new String[0]); 
    logwarn("new ====preferredCiphers========== " + m_ciphers.length); 
    S.setEnabledCipherSuites(m_ciphers); 
    return S; 
    }`