2011-01-19 26 views
7

Bir sunucuya bağlanmak için SSLSocket kullanan bir Android uygulaması geliştiriyorum. Ben de benzer bir yaptıkSSLSocket kullanarak TLS bağlantısı Android işletim sisteminde yavaş çalışıyor

SSLSession session = socket.getSession(); 

:

// Connect 
if (socket == null || socket.isClosed() || !socket.isConnected()) { 
    if (socket != null && !socket.isClosed()) 
     socket.close(); 
    Log.i(getClass().toString(), "Connecting..."); 
    if (sslContext == null) { 
     sslContext = SSLContext.getInstance("TLS"); 
     sslContext.init(null, trustAllCerts, new SecureRandom()); 
    } 
    SSLSocketFactory socketFactory = sslContext.getSocketFactory(); 
    socket = (SSLSocket)socketFactory.createSocket(host, port); 
    socket.setSoTimeout(20000); 
    socket.setUseClientMode(true); 
    connected = true; 
    Log.i(getClass().toString(), "Connected."); 
} 

// Secure 
if (connected) { 
    Log.i(getClass().toString(), "Securing..."); 
    SSLSession session = socket.getSession(); 
    secured = session.isValid(); 
    if (secured) { 
     Log.i(getClass().toString(), "Secured."); 
    } 
    else 
     Log.i(getClass().toString(), "Securing failed."); 
} 

sorun yaklaşık 5 saniye veya altında doğrultusunda TLS el sıkışma yapmak için daha fazla olay almasıdır: Bu kullanıyorum kodudur iPhone uygulaması, el sıkışma sadece 1 saniye sürüyor, bu yüzden sorunun bağlandığım sunucuda olmadığını düşünüyorum, belki yukarıdaki kodda. Bağlantı yeterince hızlı, sadece TLS el sıkışma yavaş.

herkes bunun Android'de normal olup olmadığını biliyor mu, yoksa değilse, nasıl daha hızlı yapmak için?

Teşekkür ederiz.

21.01.11 tarihinde DÜZENLENECEK: Ben örnek paypal.com:443 için, başka bir sunucuya bağlandığınızda el sıkışma hızlı olduğunu, öğrendim

.

Ama daha önce başka bir sunucuya bağlanıyordum - bana yazılan bir .NET hizmeti. Daha önce de söylediğim gibi, bu sunucuda problem olduğunu düşünmedim çünkü iPhone Uygulamam ile bağlantı kurarsam el sıkışma hızlıdır. Artık iPhone'da neden hızlı olduğunu ve Android'de yavaş olduğunu bilmiyorum. Bağlantı kurulduktan sonra, .NET sunucusunuzda tek şey:

Console.WriteLine("New client connected."); 
this.sslStream = new SslStream(tcpClient.GetStream(), true); 
this.sslStream.ReadTimeout = 15000; 
this.sslStream.WriteTimeout = 15000; 

Console.WriteLine("Beginning TLS handshake..."); 
this.sslStream.AuthenticateAsServer(connection.ServerCertificate, false, SslProtocols.Tls, false); 
Console.WriteLine("TLS handshake completed."); 

cevap

0

Ben buna benzer bir şey yapmış ve güvenli olmayan bağlantı daha yavaştır. Benim davam https vs http oldu ve biraz farklı SSL/TLS faktörü anlaşma yavaşlık katacak.

Ben aynı sunucuda, android içinde bir ve iPhone biri, ikisini de kullanarak https aynı protokol comunicate iki özdeş uygulamalar var. Bunları her ikisinde de test ettiğimde, aynı tepki süresini daha çok veya daha az görecektim. Https'de iOS, durumumda biraz daha hızlıydı, ancak korkunç değildi.

+0

Evet TLS'nin genellikle saf bir bağlantıdan daha yavaş olduğunu biliyorum, ancak yeterince hızlı. Ancak TLS el sıkışma çok yavaş, 10 saniye sürüyor, daha önce de söylediğim gibi değil. – Arthur

2
Sen bağlantı başına yeni SecureRandom kullanarak yerine tek bir statik önceden başlangıç ​​ SecureRandom kullandığınız

. Her zaman yeni bir SecureRandom() yaratırsanız, tohumlama için entropiyi toplamanız gerekir (yavaş bir süreç). İlk kullanılıncaya kadar

SecureRandom gecikme getSession()

+0

Cevabınız için teşekkür ederiz. Jumbogram, Söylediklerinizi denedim, şimdi tek bir SecureRandom örneğini kullanarak kurucuda başlatıldı. Ama ne sıklıkta bağlandığımı ve bağlantısını keserim, her zaman socket.getSession(); – Arthur

+0

Eğer ben olsaydım, bir paket yakalamaya çalışırım ve yavaşlamanın nerede olduğuna bakarım. Her paket arasında 1 saniye mi var? Paket (n) ve (n + 1) arasında uzun bir gecikme var mı, ancak diğer her şey hızlı mı? Böyle şeyler. – Jumbogram

+0

İyi fikir, deneyeceğim. Başka bir sunucuya bağlandığımda el sıkışmasının hızlı olduğunu öğrendim, örneğin paypal.com:443. Mesajımı şimdi düzenledim, sanırım .NET sunucusundaki bir şeyi değiştirmek zorundayım ama ne olduğunu bilmiyorum, belki de sorun sunucunun sertifikasında, hiçbir fikrin yok .. – Arthur

-1

sorun cihaz sunucu sertifikaları doğrular şekilde büyük olasılıkla çağrısına kadar oluşmaz bu yüzden, değil kendini tohum yok. Doğrulama, CRL'ler ve OCSP yanıtları için üçüncü taraflarla iletişim kurmayı içerebilir. Bu olursa, zaman alır. iPhone muhtemelen bunu (en azından varsayılan olarak) bir güvenlik deliği olan BTW yapmaz.

6

Android SDK'nın önceki sürümlerinde bir hata oluştu. Görünüşe göre, gereksiz bir DNS geriye doğru arama yapıyor. Bunun olmasını engellemeniz gerekiyor. İşte benim için çalışan bir geçici çözüm. 15 saniye sürdü, şimdi 0-1 saniye sürüyor. Umarım yardımcı olur.

İşte Google'a issue bağlantısı şudur.

boolean connected = false; 
if (socket == null || socket.isClosed() || !socket.isConnected()) { 
    if (socket != null && !socket.isClosed()) { 
     socket.close(); 
    } 

    Log.i(getClass().toString(), "Connecting..."); 
    messages.getText().append("Connecting..."); 
    final KeyStore keyStore = KeyStore.getInstance("BKS"); 
    keyStore.load(getResources().openRawResource(R.raw.serverkey), null); 

    final KeyManagerFactory keyManager = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); 
    keyManager.init(keyStore, null); 
    //keyManager.init(null, null); 

    final TrustManagerFactory trustFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); 
    trustFactory.init(keyStore); 

    sslContext = SSLContext.getInstance("TLS"); 
    sslContext.init(keyManager.getKeyManagers(), trustFactory.getTrustManagers(), rnd); 
    final SSLSocketFactory delegate = sslContext.getSocketFactory(); 
    SocketFactory factory = new SSLSocketFactory() { 
     @Override 
     public Socket createSocket(String host, int port) 
         throws IOException, UnknownHostException { 

      InetAddress addr = InetAddress.getByName(host); 
      injectHostname(addr, host); 
      return delegate.createSocket(addr, port); 
     } 
     @Override 
     public Socket createSocket(InetAddress host, int port) 
         throws IOException { 

      return delegate.createSocket(host, port); 
     } 
     @Override 
     public Socket createSocket(String host, int port, InetAddress localHost, int localPort) 
         throws IOException, UnknownHostException { 

      return delegate.createSocket(host, port, localHost, localPort); 
     } 
     @Override 
     public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) 
         throws IOException { 

      return delegate.createSocket(address, port, localAddress, localPort); 
     } 
     private void injectHostname(InetAddress address, String host) { 
      try { 
       Field field = InetAddress.class.getDeclaredField("hostName"); 
       field.setAccessible(true); 
       field.set(address, host); 
      } catch (Exception ignored) { 
      } 
     } 
     @Override 
     public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException { 

      injectHostname(s.getInetAddress(), host); 
      return delegate.createSocket(s, host, port, autoClose); 
     } 
     @Override 
     public String[] getDefaultCipherSuites() { 
      return delegate.getDefaultCipherSuites(); 
     } 
     @Override 
     public String[] getSupportedCipherSuites() { 
      return delegate.getSupportedCipherSuites(); 
     } 
    }; 
    socket = (SSLSocket)factory.createSocket("192.168.197.133", 9999); 
    socket.setSoTimeout(20000); 
    socket.setUseClientMode(true); 
    connected = true; 
    Log.i(getClass().toString(), "Connected."); 
    messages.getText().append("Connected."); 
} 

// Secure 
if (connected) { 
    Log.i(getClass().toString(), "Securing..."); 
    messages.getText().append("Securing..."); 
    SSLSession session = socket.getSession(); 
    boolean secured = session.isValid(); 
    if (secured) { 
     Log.i(getClass().toString(), "Secured."); 
     messages.getText().append("Secured."); 
    } 
} 
+1

Bunu yapmak için bir yol bulmak için her yere bakıyorum (sadece bir java projesinde ters DNS aramalarını devre dışı bırakmak için gerekli olan android ile ilgili değil). En son JDK için onu değiştirmek zorunda kaldım - 'HostAdı' bir' InetAddressHolder' sarmalayıcı sınıfının bir seviyesinin daha derinlerine koydular (aynı zamanda erişilemeyen, daha fazla yansıma yapmak için daha fazla yansıma gerekiyordu). Hala - teşekkür ederim. –

+1

Teşekkür ederim Yuyo. Sorun beni uzun zamandır rahatsız ediyor. – SalutonMondo

+0

Android 6'da arka uç isteğimi çok daha hızlı yaptım, Android SDK'da maalesef hala var gibi görünüyor. –

İlgili konular