2017-04-07 11 views
0

기본 Diffie-Hellman 프로토콜을 구현하려고하는데 DES를 사용하여 보낸 값의 암호를 해독해야하는 시점까지 코드가 성공합니다. 매칭되지 않는 키의 문제가 많은 예를 살펴 보았지만 연결의 양쪽 끝에 값을 인쇄하고 있습니다. 둘 다 똑같습니다. 또한 키가 생성되는 방식을 변경하는 것은 물론 여러 패딩 방식을 시도했습니다.DES 암호화에서 올바른 패딩을 보장하려면 어떻게해야합니까?

마지막으로 암호 IvParameterSpec에 IvParameterSpec 매개 변수를 추가했지만 오류 중 하나만 해결했습니다.

소켓을 로컬 호스트에 연결하는 단일 컴퓨터에서이 컴퓨터를 실행하고 있는데 수신 된 데이터와 정확히 일치하지 않는 전송 된 데이터가있는 문제가 있는지 확인하고 있지만 전송 중에는 아무 것도 변경되지 않았습니다. 그러나 각 바이트 배열을 클라이언트 측이 패딩 (?)으로 보이는 것보다 훨씬 긴 소켓의 양쪽에 인쇄 할 때

오류가 발생했습니다. 마지막 블록은 잘못 채워집니다 때문에 해독

내 서버 코드 (의도 한대로 작동하지 않는 측) 실패 :

public static void main(String[] args) { 
    ServerSocket welcomeSocket = null; 

    // Creates a connectable socket on port 6789 
    try { 
     welcomeSocket = new ServerSocket(6789); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
    while(true){ 
     try{ 
      double k2, B, A; 
      double n = 13; 
      double g = 61; 
      long y = 7; 
      B = (Math.pow(g, y))%n; 

      System.out.println("Accepting connections"); 
      // Accept an incoming connection on the socket server 
      Socket connectionSocket = welcomeSocket.accept(); 
      // Creates a read and write stream for that client 
      DataInputStream inFromClient = new DataInputStream(connectionSocket.getInputStream()); 
      DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream()); 

      // Sends the double to the client 
      outToClient.writeDouble(B); 
      System.out.println("Sent " + B); 
      // Reads the number sent by the Client 
      A = inFromClient.readDouble(); 
      System.out.println("Received " + A); 

      // Modifies the number 
      k2 = (Math.pow(A, y))%n; 
      System.out.println("DES key seed = " + k2); 
      byte[] deskeydata = toByteArray(k2); 

      // Turns the bytes of the modified number into a DES key spec 
      DESKeySpec deskeyspec = new DESKeySpec(deskeydata); 

      // Makes a secret key (DES) 
      SecretKeyFactory keyF = SecretKeyFactory.getInstance("DES"); 
      SecretKey keystuff = keyF.generateSecret(deskeyspec); 
      System.out.println(keystuff.toString()); 

      // Gets an incoming string from the client and turns it into binary 
      byte[] incomingBytes = new byte[128]; 
      try{ 
       inFromClient.readFully(incomingBytes); 
      } catch(EOFException eof){ 
       System.out.println("Finished reading"); 
      } 
      System.out.println(new String(incomingBytes)); 
      Cipher c = Cipher.getInstance("DES/CBC/PKCS5Padding"); 

      // Decrypts the string using the shared secret key 
      c.init(Cipher.DECRYPT_MODE, keystuff, new IvParameterSpec(new byte[8])); 
      byte[] ct2 = c.doFinal(incomingBytes); 

      // Decode it from base 64 
      //byte[] decodedBytes = Base64.getDecoder().decode(ct2); 

      // Prints the received string 
      System.out.println("Received: " + new String(ct2)); 

      inFromClient.close(); 
      outToClient.close(); 

     } catch(Exception e){ 
      e.printStackTrace(); 
     } 
    } 
} 

내 고객 코드 :

public static void main(String[] args) { 

    // Creates a socket to the local host on port 6789 
    Socket clientSocket = null; 
    try { 
     clientSocket = new Socket("localhost", 6789); 
    } catch (IOException e1) { 
     e1.printStackTrace(); 
    } 
    try{ 
     double k1, B, A; 
     double n = 13; 
     double g = 61; 
     long x = 3; 

     // Sends an unencrypted number to the server 
     A = (Math.pow(g, x))%n; 
     DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream()); 
     DataInputStream inFromServer = new DataInputStream(clientSocket.getInputStream()); 

     // Transforms A into a byte array and sends it over 
     outToServer.writeDouble(A); 
     outToServer.flush(); 
     System.out.println("Sending " + A); 

     // Reads the incoming data from the server 
     B = inFromServer.readDouble(); 
     System.out.println("Recieved " + B); 

     // Modifies the data to create the number for des key 
     k1 = (Math.pow(B, x))%n; 
     System.out.println("DES key seed = " + k1); 
     byte[] deskeydata = toByteArray(k1); 

     // Turns the bytes of the modified number into a DES key spec 
     DESKeySpec deskeyspec = new DESKeySpec(deskeydata); 

     // Makes a secret key (DES) 
     SecretKeyFactory keyF = SecretKeyFactory.getInstance("DES"); 
     SecretKey keystuff = keyF.generateSecret(deskeyspec); 
     System.out.println(keystuff.toString()); 

     // Takes in input from the user and turns it into binary 
     BufferedReader inFromUser = new BufferedReader(new InputStreamReader(System.in)); 
     System.out.println("Enter a message:"); 

     String sentence = inFromUser.readLine(); 
     byte[] str2 = sentence.getBytes(); 
     byte[] encodedMessage = Base64.getEncoder().encode(str2); 

     Cipher c = Cipher.getInstance("DES/CBC/PKCS5Padding"); 

     // Encrypts the user's input with the secret key 
     c.init(Cipher.ENCRYPT_MODE, keystuff, new IvParameterSpec(new byte[8])); 
     byte[] ct2 = c.doFinal(encodedMessage); 
     System.out.println("Initted the cipher and moving forward with " + new String(ct2)); 

     // Writes the encrypted message to the user 
     outToServer.write(ct2); 
     outToServer.flush(); 


     inFromServer.close(); 
     outToServer.close(); 
    } catch(Exception e){ 
     e.printStackTrace(); 
    } 

} 

나는이 오류를 혼자서 꽤 오랫동안 작업 해 왔기 때문에이 작업을하는 데 도움이 될 수있는 모든 것을 대단히 환영 할 것입니다.

+0

"의도 한대로 작동하지 않는 것"보다 구체적 일 수 있습니까? 실제 오류/예기치 않은 결과는 무엇입니까? – slipperyseal

+0

설명을 조정했습니다. 최종 블록이 올바르게 채워지지 않는다는 badpaddingexception입니다. – KM529

+1

클라이언트 측에서 알 수없고 다양한 길이의 바이트 배열을 작성하고 있습니다. 서버 측에서는 항상 128 바이트를 읽습니다. 이러한 불일치가 버그의 원인 일 수 있습니다. 클라이언트에서 base64 인코딩과 같은 다른 버그가 있지만 서버 측에서 디코딩되지는 않습니다. –

답변

0

나는 이것을 해결할 방법을 찾아 낼 수 있었다. (나는 매우 비효율적이라고 생각하지만). 이 문제는 서버 측의 readFully 메소드로 인해 발생했습니다. 나는 128 바이트 배열에 대한 해답을 읽고 해독 함수는 아무것도 아닌 바이트 배열의 빈 슬롯을 보았다.

이 문제를 해결하기 위해 필자는 입력 섹션을 다음과 같이 바꿨다. 다음은 각 개별 바이트를 읽고 들어오는 메시지의 정확한 길이를 가진 바이트 배열을 생성한다.

  ArrayList<Byte> totalBytes = new ArrayList<Byte>(); 
      while(true){ 
       try{ 
        byte in = inFromClient.readByte(); 
        totalBytes.add(in); 
       } catch(EOFException eof){ 
        System.out.println("Finished reading"); 
        break; 
       } 
      } 
      int incomingSize = totalBytes.size(); 
      byte[] receivedBytes = new byte[incomingSize]; 
      for(int i = 0; i < incomingSize; i++){ 
       receivedBytes[i] = totalBytes.get(i); 
      }