Я пытаюсь обработать защищенное соединение с самодельным сервером и клиентом. Сначала клиент подключается к серверу и отправляет на 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 на сокете я получил аналогичные проблемы. У кого-то есть идея, что происходит?
Замечание: вы знаете о недавно обнаруженной ошибке Java с десериализацией? Злые клиенты могут обмануть 'readObject', делая почти все. – immibis
Метод readObject() в клиентском приложении в строке 13 блокирует. – TomHalo
Что делает сервер, когда клиент ждет, чтобы прочитать объект? – immibis