2014-10-09 1 views
2

Я использую неблокирующий socketChannel и SSLEngine ssl server. Поэтому после успешного рукопожатия я прочитал сокет (184 байта/384 байта читаются в первый раз), а затем я передаю этот буфер для разворачивания метода. Метод разворачивать бросить следующее исключение:SSLEngine: Недопустимые данные заполнения TLS при распаковке после успешного установления связи

javax.net.ssl.SSLHandshakeException: Invalid TLS padding data 
    at sun.security.ssl.Alerts.getSSLException(Unknown Source) 
    at sun.security.ssl.SSLEngineImpl.fatal(Unknown Source) 
    at sun.security.ssl.SSLEngineImpl.readRecord(Unknown Source) 
    at sun.security.ssl.SSLEngineImpl.readNetRecord(Unknown Source) 
    at sun.security.ssl.SSLEngineImpl.unwrap(Unknown Source) 
    at javax.net.ssl.SSLEngine.unwrap(Unknown Source) 

Но в случае, если я читаю все байты (384/384) в первый раз, то я не получаю это исключение.

Я думал, что если sslengine не имеет достаточного байта для разворачивания, он вернет статус bufferUnderflow.

Действительно ли мне нужны все байты для вызова метода разворота? Если да, то как я могу быть уверен, что я прочитал все байты для неблокирующего сокета?


EDIT: код:

public boolean doHandShake(SocketChannel socket) throws Exception{ 

     if(!socket.isConnected()){ 
      return false; 
     } 

     outAppData.clear(); 
     inAppData.clear(); 
     inNetData.clear(); 
     outNetData.clear(); 

     if(engine==null || socket==null) 
     return false; 


      engine.beginHandshake(); 
      SSLEngineResult.HandshakeStatus hs = engine.getHandshakeStatus(); 

      while (hs != SSLEngineResult.HandshakeStatus.FINISHED && 
        hs != SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) { 

       switch (hs) { 

       case NEED_UNWRAP: 
        int read=1; 
        while (read > 0) { 
          read=socket.read(inNetData); 
          if(read==-1){ 
           throw new IOException ("channel closed"); 
          } 
         } 

        inNetData.flip(); 
        engineRes=engine.unwrap(inNetData, outAppData); 
        inNetData.compact(); 

        switch(engineRes.getStatus()){ 
          case BUFFER_OVERFLOW: 
           System.out.println("overFlow"); 
           break; 
          case CLOSED: 
           return false; 
          case OK: 
           //outAppData.clear(); 
          // inNetData.clear(); 
           break; 
          default: 
           break; 
        } 

       break; 

       case NEED_WRAP : 
       outNetData.clear(); 
        engineRes=engine.wrap(inAppData, outNetData); 
        outNetData.flip(); 
        switch (engineRes.getStatus()){ 
          case BUFFER_OVERFLOW: 
           System.out.println("overFlow"); 
           break; 
          case BUFFER_UNDERFLOW: 
           System.out.println("underFlowa"); 
           break; 
          case CLOSED: 
           return false; 
          case OK: 
           //outNetData.flip(); 
           while(outNetData.hasRemaining()){ 
            if(socket.write(outNetData)<0){ 
             throw new Exception("Channel Has been Closed"); 
            } 
           } 

           break; 
          default: 
           break; 


        } 

       break; 

       case NEED_TASK : 
        Runnable r=engine.getDelegatedTask(); 
        r.run(); 
        break; 

       case FINISHED: 
        System.out.println("finished"); 
        break; 

       case NOT_HANDSHAKING: 
        break; 

        default: 
         throw new IllegalArgumentException("Inexpected/Unhadled SSLEngineResult :"+hs); 

       } 

       hs = engine.getHandshakeStatus(); 

      } 
      return true; 

    } 

потом я прочитал 184/384 байт с использованием не канала блокировки.

читать = _socketChannel.read (buffer);

, а затем передать на buffer, чтобы быть расшифрованы:

public ByteBuffer decrypt(ByteBuffer inNetData) throws SSLException{ 

     if(!isValidSession()){ 
      return null; 
     } 
      outAppData.clear(); 

      try{ 
       engineRes=engine.unwrap(inNetData, outAppData); 
      }catch(Exception e){ 
       e.printStackTrace(); 
      } 
       inNetData.compact(); 

       switch(engineRes.getStatus()){ 
        case BUFFER_OVERFLOW: 
         outAppData=ByteBuffer.allocate(outNetData.capacity()*2); 
         inNetData.position(0); 
         return encrypt(inNetData); 
        case BUFFER_UNDERFLOW: 
         return null; 
        case CLOSED: 
         return null; 
        case OK: 
         outAppData.flip(); 
         System.out.println(new String(outAppData.array(),0,400)); 

         return outAppData; 
        default: 
         break; 
       } 


     return null; 
    } 

исключение бросают в engine.unwrap engineRes = engine.unwrap (inNetData, outAppData);

+0

Опубликовать код. – EJP

+0

сделано.Пожалуйста, помогите – user3791570

ответ

0

Несколько вопросов здесь.

  1. Если вы BUFFER_OVERFLOW вы должны flip(), write(), compact(), и повторить wrap(). Не просто распечатать и отказаться, как указано выше.

  2. Если вы получаете BUFFER_UNDERFLOW, вы должны прочитать() и повторить разворот(). Это ваша конкретная проблема.

  3. Если вы получаете Exception любого вида, этого недостаточно, чтобы просто распечатать исключение и продолжить, как будто этого не произошло.

  4. FINISHED не возвращается getHandshakeStatus(). Он только когда-либо устанавливается в статусе рукопожатия в SSLEngineResult, который возвращается wrap() и unwrap().

  5. Вы звоните encrypt() с точностью до decrypt(). Это не имеет смысла.

  6. Ваша общая техника не будет работать. Рукопожатие может произойти в любое время, в середине чтения или записи, и вы должны написать свой код, чтобы справиться с этим. Когда вам это удастся, вам не нужно будет вызывать свой собственный метод doHandshake(), так как ваш код все равно справится с ним.

SSLEngine - государственный автомат. Вы должны делать именно то, что он вам говорит.

+0

yep Я знаю, что блок chatch try был просто для того, чтобы показать, что исключение вызывается функцией unrap(). Мой вопрос был, почему, когда я перехожу к распаку() 184 байта из 384, он бросает exeception вместо того, чтобы указывать на bufferunderflow ??? и почему, когда я пропускаю 384 байт из 384, он работает хорошо? – user3791570

+0

в моем случае: метод разворота выдает исключение и не возвращает BUFFER_UNDERFLOW, когда количество байтов недостаточно – user3791570

Смежные вопросы