1

J'essaie de gérer une connexion sécurisée avec un serveur et un client. Au début, le client se connecte au serveur et envoie par ObjectOutputStream un objet PublicKey au serveur. Le serveur répond avec une clé AES cryptée, puis les deux établissent un flux d'entrée et de sortie chiffré AES.ObjectInputStream bloque pour toujours pendant readObject()

Mais le client continue à bloquer pendant la réception de la clé AES.

Thats my code client:

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) { 

    } 
} 

Et c'est mon serveur:

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); 
}} 

Je pense que plus un problème avec les objectstreams, chaque fois que j'essaie de travailler avec objectstreams sur un socket je suis arrivé problèmes similaires. Est-ce que quelqu'un a eu une idée de ce qui se passe?

+0

Remarque: connaissez-vous le bogue Java récemment découvert avec la désérialisation? Les clients malveillants pourraient être en mesure de tromper 'readObject' en faisant presque n'importe quoi. – immibis

+0

La méthode readObject() dans l'application cliente de la ligne 13 bloque. – TomHalo

+0

Que fait le serveur lorsque le client attend de lire un objet? – immibis

Répondre

0

Vous ne pouvez pas utiliser plusieurs flux sur le même socket en général. Il y a des cas spécifiques où cela fonctionne mais en général vous êtes confronté à une mise en mémoire tampon inconnue qui va désynchroniser vos pairs rapidement. Refaire avec un seul ObjectOutputStream et ObjectInputStream à chaque extrémité. Si vous avez seulement besoin de crypter certaines parties du flux, regardez SealedObject.

+0

J'essaie d'utiliser SealedObject à la place, cela semble interessant. Après cela, je vais répondre s'il résout aussi mon problème avec le InputStream bloquant – TomHalo