1

Я пытаюсь обработать защищенное соединение с самодельным сервером и клиентом. Сначала клиент подключается к серверу и отправляет на ObjectOutputStream объект PublicKey на сервер. Сервер отвечает зашифрованным ключом AES, а затем устанавливает зашифрованный входной и выходной поток AES.ObjectInputStream блокирует forever во время readObject()

Но клиент сохраняет блокировку при приеме ключа AES.

Thats мой код клиента:

private void createServerConnection(String serverAddress) throws IOException { 
    connection = new Socket(serverAddress, 5555); 
    InputStream is = connection.getInputStream(); 
    OutputStream os = connection.getOutputStream(); 
    ObjectOutputStream oos = new ObjectOutputStream(os); 
    ObjectInputStream ois = new ObjectInputStream(is); 
    try { 
     KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); 
     KeyPair kp = kpg.genKeyPair(); 
     oos.writeObject(kp.getPublic()); 
     Cipher ci = Cipher.getInstance("RSA"); 
     ci.init(Cipher.DECRYPT_MODE, kp.getPrivate()); 
     byte[] aesKey = (byte[]) ois.readObject(); 
     aesKey = ci.doFinal(aesKey); 
     SecretKey originalKey = new SecretKeySpec(aesKey, 0, aesKey.length, "AES"); 

     Cipher aesCipherD = Cipher.getInstance("AES"); 
     aesCipherD.init(Cipher.DECRYPT_MODE, originalKey); 

     Cipher aesCipherE = Cipher.getInstance("AES"); 
     aesCipherE.init(Cipher.ENCRYPT_MODE, originalKey); 

     this.oos = new ObjectOutputStream(new CipherOutputStream(os, aesCipherE)); 
     this.ois = new ObjectInputStream(new CipherInputStream(is, aesCipherD)); 

    } catch(NoSuchAlgorithmException nsae) { 

    } catch(ClassNotFoundException cnfe) { 

    } catch(NoSuchPaddingException nspe) { 

    } catch(InvalidKeyException ike) { 

    } catch(IllegalBlockSizeException ibse) { 

    } catch(BadPaddingException bpe) { 

    } 
} 

И вот мой сервер:

public void run() { 
    try { 
     //Verbindung Aufbauen 
     Socket s = server.accept(); 
     System.out.println("Eingehede Verbindung von " + s.getInetAddress().toString()); 
     new JSecSocket(server).start(); 
     OutputStream os = s.getOutputStream(); 
     InputStream is = s.getInputStream(); 
     ObjectOutputStream oos = new ObjectOutputStream(os); 
     ObjectInputStream ois = new ObjectInputStream(is); 
     System.out.println("Verbindung aufgebaut!"); 

     //PublicKey vom Client entgegennehmen 
     System.out.println("Öffentlicher Schlüssel wird empfangen."); 
     PublicKey clientPublicKey = (PublicKey) ois.readObject(); 

     //AES Key verschlüsseln und zum Client übertragen 
     System.out.println("AES Schlüssel wird gesendet."); 
     Cipher keyCipher = Cipher.getInstance("RSA"); 
     keyCipher.init(Cipher.ENCRYPT_MODE, clientPublicKey); 
     byte[] encryptetKey = keyCipher.doFinal(this.aesSk.getEncoded()); 
     oos.write(encryptetKey); 

     System.out.println("Verschlüsselte Verbindung wird aufgebaut!"); 
     Cipher encryptCipher = Cipher.getInstance("AES"); 
     encryptCipher.init(Cipher.ENCRYPT_MODE, aesSk); 

     Cipher decryptCipher = Cipher.getInstance("AES"); 
     decryptCipher.init(Cipher.DECRYPT_MODE, aesSk); 

     //Verschlüsselte Datenströme werden geöffnet 
     oos = new ObjectOutputStream(new CipherOutputStream(os, encryptCipher)); 
     ois = new ObjectInputStream(new CipherInputStream(is, decryptCipher)); 
     System.out.println("Verbindung bereit!"); 
     while (!this.isInterrupted()) { 
      NetworkStatus ns = (NetworkStatus) ois.readObject(); 
      JSecDatabase database = new JSecDatabase("localhost", "root", "", "database"); 
      switch (ns.getAction()) { 
       case "lookup": 
        System.out.println("Lookup von" + s.getInetAddress().toString()); 
        String target = (String) ns.getValue(); 
        try { 
         oos.writeObject(new NetworkStatus("lookupOk", database.lookup(target))); 
        } catch (Exception e) { 
         oos.writeObject(new NetworkStatus("lookupError", e)); 
        } 
        break; 
       case "create": 
        System.out.println("User wird erstellt von " + s.getInetAddress().toString()); 
        oos.writeObject(new NetworkStatus("createOk", database.create())); 
        break; 
       case "update": 
        System.out.println("User wird geupdated von" + s.getInetAddress().toString()); 
        String[] updateTarget = (String[]) ns.getValue(); 
        if (database.update(updateTarget[0], updateTarget[1], s.getInetAddress().toString())) { 
         oos.writeObject(new NetworkStatus("updateOk", s.getInetAddress().toString())); 
        } else { 
         oos.writeObject(new NetworkStatus("updateError", null)); 
        } 
        break; 
       case "delete": 

        break; 
       default: 
       case "close": 
        System.out.println("Verbindung zu " + s.getInetAddress().toString() + " wird getrennt!"); 
        oos.close(); 
        ois.close(); 
        os.close(); 
        is.close(); 
      } 
     } 

    } catch (IOException ioe) { 
     System.err.println("Es gab einen IO Error.\n" + ioe.getMessage()); 
    } catch (ClassNotFoundException cnfe) { 
     System.err.println(cnfe.getMessage()); 
    } catch (NoSuchAlgorithmException nsae) { 
     System.err.println(nsae.getMessage()); 
    } catch (NoSuchPaddingException nspe) { 
     System.err.println(nspe.getMessage()); 
    } catch (InvalidKeyException ike) { 
     System.err.println(ike.getMessage()); 
    } catch (IllegalBlockSizeException ibse) { 
     System.err.println(ibse.getMessage()); 
    } catch (BadPaddingException bpe) { 
     System.err.println(bpe.getMessage()); 
    } 
    sockets.remove(this); 
}} 

Я думаю, что его больше проблемы с objectstreams, каждый раз, когда я пытаюсь работать с objectstreams на сокете я получил аналогичные проблемы. У кого-то есть идея, что происходит?

+0

Замечание: вы знаете о недавно обнаруженной ошибке Java с десериализацией? Злые клиенты могут обмануть 'readObject', делая почти все. – immibis

+0

Метод readObject() в клиентском приложении в строке 13 блокирует. – TomHalo

+0

Что делает сервер, когда клиент ждет, чтобы прочитать объект? – immibis

ответ

0

Вы не можете использовать несколько потоков по одному и тому же сокету в целом. Существуют конкретные случаи, когда он работает, но в целом вы против неизвестной буферизации, которая быстро выведет ваших сверстников из синхронизации. Верните его с одним ObjectOutputStream и ObjectInputStream на каждом конце. Если вам нужно только зашифровать определенные части потока, посмотрите на SealedObject.

+0

Вместо этого я пытаюсь использовать SealedObject, это кажется интересным. После этого я отвечу, если он также решает мою проблему с блокировкой InputStream – TomHalo