2012-03-30 8 views
6

Muszę pracować z gniazdem TCP przez TLS dla aplikacji, nad którą pracuję. Przeszedłem przez dziesiątki przykładów i podczas gdy nie mam problemu z przechodzeniem przez uścisk dłoni, nie mogę wydawać się odczytywać strumienia wejściowego w jakikolwiek sposób (próbowałem dużo, włączając readline(), czytanie do tablicy znaków, itp.). za każdym razem, gdy próbuję, aplikacja zamarza w tym miejscu. Jeśli debuguję, nigdy nie przechodzi do następnej linii kodu.Przykład SSLEngine Android

Podjęłam próbę przejścia do używania SSLEngine, ponieważ jest to odpowiedź Java 1.5 dla java.nio na SSL. Jednak znalazłem jeden przykład przykład (tutaj: http://docs.oracle.com/javase/7/docs/technotes/guides/security/jsse/samples/sslengine/SSLEngineSimpleDemo.java), który jest dla mnie nieco mylący i nie udało mi się go wdrożyć. Kiedy próbuję, wywołanie unwrap() daje pusty bufor, gdzie wiem (z wykorzystaniem OpenSSL w linii poleceń), że dana usługa przesyła dane z powrotem do potoku.

Propozycje są mile widziane, już wypaliłem za dużo czasu. Oto odpowiedni kod:

SSLEngine engine = sslContext.createSSLEngine(uri.getHost(), uri.getPort()); 
      engine.setUseClientMode(true); 
      engine.beginHandshake(); 
      SSLSession session = engine.getSession(); 
      int bufferMax = session.getPacketBufferSize(); 
      int appBufferMax = session.getApplicationBufferSize() + 50; 
      ByteBuffer cTo = ByteBuffer.allocateDirect(bufferMax); 
      ByteBuffer sTo = ByteBuffer.allocateDirect(bufferMax); 

      ByteBuffer out = ByteBuffer.wrap(sessionId.getBytes()); 
      ByteBuffer in = ByteBuffer.allocate(appBufferMax); 


      debug("sending secret"); 
      SSLEngineResult rslt = engine.wrap(out, cTo); 
      debug("first result: " + rslt.toString()); 
      sTo.flip(); 
      rslt = engine.unwrap(sTo, in); 
      debug("next result" + rslt.toString()); 
+0

W ramach aktualizacji próbowałem również zapętlić wywołanie podczas gdy (rslt.getStatus()! = SSLEngineResult.Status.OK), i nigdy nie było zapełniane, a status nigdy nie był poprawny. – Paul

+0

Czy próbowałeś uruchomić ten kod w zwykłej aplikacji Java? To przynajmniej pomoże ustalić, czy jest to problem specyficzny dla Androida, czy nie. – elevine

+0

Tak, nie sądzę, że jest to specyficzne dla Androida, po prostu robię to w projekcie Android. – Paul

Odpowiedz

1

Ta implementacja brakuje kilka kluczowych elementów. Mianowicie handshake może odbijać się pomiędzy kilkoma stanami NEED_WRAP, NEED_UNWRAP, NEED_TASK, aby negocjować połączenie. Oznacza to, że nie można po prostu połączyć się z jednym, a potem z drugim. Będziesz musiał zapętlić stan, aż uzgadni się uścisk dłoni.

while (handshaking) { 
     switch (state) { 
      case NEED_WRAP: 
       doWrap(); 
       break; 
      case NEED_UNWRAP: 
       doUnwrap(); 
       break; 
      case NEED_TASK: 
       doTask(); 
       break; 
     } 
    } 

A full working example of Java SSL and NIO

Teraz powiedział, że powinieneś być świadomy SSLEngine na Android is broken. Google zaleca używanie wątków i blokowanie gniazd zgodnie z tym wątkiem.

0

unwrap() może przynieść pusty bufor, jeśli co odwinął był komunikat SSL handshake lub alert, zamiast danych aplikacji. Nie ma tu wystarczającej ilości informacji, by powiedzieć więcej. Jaki był później status silnika?

0

beginHandshake nie wykonuje uzgadniania, służy tylko do poinformowania SSLEngine, że chcesz wykonać uzgadnianie dla następnych połączeń do zawijania/rozwijania. Przydaje się, gdy chcesz wykonać kolejny uścisk dłoni. W pierwszym przypadku nie jest to konieczne, ponieważ pierwsze wezwanie do zawinięcia zainicjuje uzgadnianie.

Poza tym należy sprawdzić wynik owijania i rozwinąć metody, aby sprawdzić, czy wszystkie dane zostały poprawnie zakodowane. Może się zdarzyć, że będziesz musiał wywołać kilka metod, aby przetworzyć wszystkie dane.

Poniższy link może pomóc: http://onjava.com/onjava/2004/11/03/ssl-nio.html

albo to pytanie: SSL Handshaking Using Self-Signed Certs and SSLEngine (JSSE)

Powiązane problemy