2014-10-09 9 views
2

비 차단 socketChannel 및 SSLEngine을 사용하고 있습니다. 그래서 성공적인 핸드 셰이크 후 소켓 (184 바이트/384 바이트를 처음 읽는 중)을 읽은 다음이 버퍼를 unwrap 메서드에 전달합니다. 언랩 방법은 다음과 같은 예외 던져 :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에 unwrap 할 바이트가 충분하지 않으면 bufferUnderflow 상태가 반환 될 것이라고 생각했습니다.

unwrap 메서드를 호출하기 위해 실제로 모든 바이트가 필요합니까? 그렇다면 어떻게 비 블로킹 소켓의 모든 바이트를 읽을 수 있습니까?


편집 : 코드 :

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; 

    } 

는 내가 아닌 차단 채널을 사용하여 384분의 184 바이트를 읽습니다.

read = _socketChannel.read (buffer);

다음에 buffer 패스가 해독 될 :

예외가 engine.unwrap에서 발생되는
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; 
    } 

engineRes = engine.unwrap (inNetData, outAppData);

+0

몇 가지 코드를 게시하십시오. – EJP

+0

완료.제발 도움이 – user3791570

답변

0

여기에 몇 가지 문제가 있습니다.

  1. 당신은 당신이해야 flip(), write(), compact(),BUFFER_OVERFLOW을 얻고 wrap()를 반복합니다. 위와 같이 인쇄하지 않고 포기하십시오.

  2. BUFFER_UNDERFLOW이 표시되면()을 읽고 unwrap()을 반복해야합니다. 이것은 당신의 구체적인 문제입니다.

  3. 어떤 종류의 Exception이 발생하는 경우 예외를 인쇄하고 발생하지 않은 것처럼 계속 진행하는 것만으로는 충분하지 않습니다.

  4. FINISHEDgetHandshakeStatus()에 의해 반환되지 않습니다. wrap()unwrap()에 의해 반환되는 SSLEngineResult의 핸드 셰이크 상태로만 설정됩니다.

  5. decrypt() 메서드 내에서 encrypt()을 호출하고 있습니다. 이것은 말이되지 않습니다.

  6. 귀하의 전반적인 기술은 작동하지 않습니다. 핸드 셰이크는 읽기 또는 쓰기의 중간에 언제든지 발생할 수 있으며이를 해결할 수 있도록 코드를 작성해야합니다. 코드를 성공적으로 수행했으면 doHandshake() 메서드를 호출 할 필요가 없습니다. 코드에서 코드를 처리 할 수 ​​있습니다.

SSLEngine에이 상태 머신이다. 당신이해야 할 일을 정확하게해야합니다.

+0

예기치 않은 chrap 블록은 unwrap()에 의해 예외가 던져지고 있음을 보여줍니다. 내 질문은 왜 내가 unwrap() 384 중 384 바이트 그것을 전달하는 대신 bufferunderflow 포인팅 대신 exeception 던졌습니다 ??? 384 바이트 중 384 바이트를 통과하면 왜 잘 작동합니까? 내 경우에 – user3791570

+0

: unwrap 메서드는 예외를 throw하고 바이트 수가 충분하지 않으면 BUFFER_UNDERFLOW를 반환하지 않습니다. – user3791570

관련 문제