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?
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
La méthode readObject() dans l'application cliente de la ligne 13 bloque. – TomHalo
Que fait le serveur lorsque le client attend de lire un objet? – immibis