2014-06-24 2 views
6

SSLCertificateSocketFactory.setHostname을 사용하여 SNI 지원을 추가하려고합니다. wireshark를 사용하여 클라이언트와 SNI 지원 서버 간의 통신을 봅니다. CLIENT HELLO는 서버 (올바른 호스트 이름이 설정된 경우), 서버 서버 Hello로 응답하고 클라이언트에게 인증서를 보냅니다. 클라이언트가 인증서를 보내지 않고 openssl 명령을 통해 통신/핸드 쉐이크가 중지 된 후 openssl s_client - 클라이언트 - 서버 이름 호스트 이름 - 인증서 인증서가 모두 원활하게 처리되면서 핸드 셰이크가 성공적으로 수행됩니다 ..SSLCertificateSocketFactory를 사용하는 Android HTTPS SNI 지원

소켓을 사용하고 socket.startHandshake 예외가 발생합니다 : IOException : javax.net.ssl.SSLHandshakeException : java.security.cert.CertPathValidatorException : T 인증서 경로에 대한 녹 앵커를 찾을 수 없습니다.

  final SSLCertificateSocketFactory sslSocketFactory = (SSLCertificateSocketFactory) SSLCertificateSocketFactory.getDefault(0); 

      socket = (SSLSocket) sslSocketFactory.createSocket(InetAddress.getByName("theserver"), 443); 


      socket.setEnabledProtocols(socket.getSupportedProtocols()); 

      String[] cipherArray = socket.getEnabledCipherSuites(); 
      for(int i = 0; i<cipherArray.length; i++) { 
       Log.e("","Available Cipher:"+cipherArray[i]); 
      } 
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { 
       sslSocketFactory.setHostname(socket, "thehostname"); 
      } else { 
       try { 
        java.lang.reflect.Method setHostnameMethod = socket.getClass().getMethod("setHostname", String.class); 
        setHostnameMethod.invoke(socket, "thehostname"); 
       } catch (Exception e) { 
        Log.w("", "SNI not useable", e); 
       } 
      } 
      socket.setSoTimeout(20000); 
      socket.setUseClientMode(true); 
      Log.i(getClass().toString(), "Connected."); 
      socket.startHandshake(); 
      SSLSession session = socket.getSession(); 
      boolean secured = session.isValid(); 

안드로이드 개발자에이 IOException이 SSLHandshakeException이의 솔루션은 https://developer.android.com/training/articles/security-ssl.html#CommonProblems입니다 :

"다음 만들고의 TrustManager를 초기화하는 데 사용되는 키 스토어를 생성하는 데 사용 InputStream로부터 특정 CA를 가져 가라. TrustManager는 시스템이 서버의 인증서를 검증하는 데 사용하는 것으로, 하나 이상의 CA가있는 KeyStore에서 인증서를 만들면 해당 TrustManager가 신뢰할 수있는 유일한 CA가됩니다. SSLSocketFactory를 제공하는 새로운 SSLContext HttpsURLConnection에서 기본 SSLSocketFactory를 재정의하는 데 사용할 수 있습니다. 연결이 인증서 확인을 위해 CA를 사용합니다 이쪽으로. "

는 지금의 SSLContext 내가 나를 못하게하면 나는 질문이 분명하다 희망 ... 무엇을 할 (sethostname시 법에 대한) 을 SSLCertificateSocketFactory를 사용하려면,의 SSLSocketFactory를 반환 알고 있거나

+2

보면 그 방법을보고 싶다면

HttpsURLConnection connection = NetCipher.getHttpsURLConnection(sourceUrl); 

. 나는 여기서 일어날 일을 따라갈 것입니다. 다음은 내가 사용하고있는 일부 코드 조각의 pastebin입니다. http://pastebin.com/K18PwtLa – Derek

답변

2

당신은 SNI 지원을 포함하여 안드로이드의 HttpsURLConnection를 사용할 때 현대 TLS의 설정을 얻을 수있는 NetCipher 라이브러리를 사용할 수 있습니다에 더 명확하게 주시기 바랍니다. NetCipher이뿐만 아니라, 최고의 지원 TLS 버전을 사용하는 HttpsURLConnection 인스턴스를 구성합니다 해당 TLS 버전에 가장 적합한 암호 모음입니다. 먼저 build.gradle에 추가하십시오. :

compile 'info.guardianproject.netcipher:netcipher:2.0.0-alpha1' 

netcipher.jar을 다운로드하여 앱에 직접 포함시킬 수 있습니다. 그런 다음 호출하는 대신 :

HttpURLConnection connection = (HttpURLConnection) sourceUrl.openConnection(); 

콜이 : 당신은 코드에서 수행, 내가 유사한 문제에 직면하고있다 TlsOnlySocketFactory

+0

훌륭한 해결책이며, 저를 구해 줬습니다. +1 – christian