ObjectInputStream с CipherInputStream зависает, зависает - PullRequest
1 голос
/ 23 февраля 2012

Я программирую клиент-серверное Java-приложение, и у меня возникла проблема, потому что оно зависает при создании ObjectInputStream как на клиенте, так и на сервере.

Клиент:

Socket socket = new Socket("localhost", 9999);

outCiph = new CipherOutputStream(socket.getOutputStream(), AES.getEncryptCipher("key"));
out = new ObjectOutputStream(outCiph);
inCiph = new CipherInputStream(socket.getInputStream(), AES.getDecryptCipher("key"));
in = new ObjectInputStream(inCiph);

try
{
String text = "test!";

out.writeObject(text);
out.flush();

if (out != null)
out.close();

if (in != null)
in.close();
}
catch (IOException ex)
{
System.err.println(ex.toString());
}

Сервер:

ServerSocket serverSocket = new ServerSocket(9999);
Socket socket = serverSocket.accept();

outCiph = new CipherOutputStream(socket.getOutputStream(), AES.getEncryptCipher("key"));
out = new ObjectOutputStream(outCiph);
inCiph = new CipherInputStream(socket.getInputStream(), AES.getDecryptCipher("key"));
in = new ObjectInputStream(inCiph);

try
{
String rec = (String) in.readObject();
System.out.println("Received from client: " + rec);

if (out != null)
out.close();

if (in != null)
in.close();

}
catch (IOException ex)
{
System.err.println(ex.toString() + " in start()");
}
catch (ClassNotFoundException ex)
{
System.err.println(ex.toString());
}

AES:

// I'm not author of generateKey method so I've no idea if is it correct
private static byte[] generateKey(String pass) throws UnsupportedEncodingException, NoSuchAlgorithmException
{
MessageDigest sha = MessageDigest.getInstance("SHA-256");
byte[] passBytes = pass.getBytes("ASCII");
byte[] sha256Bytes = sha.digest(passBytes);


byte[] key = new byte[16];
int j = 0;
for (int i = 0; i < sha256Bytes.length; i++)
{
    if (i % 2 == 0)
    {
    key[j] = sha256Bytes[i];
    j++;
    }
}
return key;
}

public static Cipher getEncryptCipher(String pass)
{
try
{
    SecretKeySpec skeySpec = new SecretKeySpec(generateKey(pass), "AES");
    Cipher cipher = Cipher.getInstance("AES");
    cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
    return cipher;
}
catch (Exception ex) // just for clarity
{
    Logger.getLogger(AES.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}

public static Cipher getDecryptCipher(String pass)
{
try
{
    SecretKeySpec skeySpec = new SecretKeySpec(generateKey(pass), "AES");
    Cipher cipher = Cipher.getInstance("AES");
    cipher.init(Cipher.DECRYPT_MODE, skeySpec);
    return cipher;
}
catch (Exception ex) // just for clarity
{
    Logger.getLogger(AES.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}

Когда я не использую CipherInput / OutputStream, все работает нормально, поэтому проблема как-то связана с CipherInput / OutputStream.

1 Ответ

1 голос
/ 23 февраля 2012

Вам необходимо создать ObjectInputStream только после того, как вы отправите all информацию, потому что конструктор ObjectInputStream блокируется, потому что ему нужно прочитать заголовок.

Обычно всеObjectOutputStream написал бы байты, но теперь CipherOutputStream ожидает, пока у него не будет полного 16-байтового блока (в случае AES), прежде чем он отправит (последнюю часть) заголовок.Возможно, AES в режиме потокового шифра (CTR или GCM) будет более полезным, поскольку он использует шифрование по байтам и может напрямую отправлять каждый байт.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...