1

クライアント/サーバー ベースの 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 に関連しています。

4

1 に答える 1

1

ObjectInputStreamのコンストラクターは、ヘッダーを読み取る必要があるためにブロックされるため、すべての情報を送信した後にのみ ObjectInputStream を作成する必要があります。

通常、すべてのバイトは ObjectOutputStream によって書き込まれますが、CipherOutputStream は、ヘッダー (の最後の部分) を送信する前に、完全な 16 バイト ブロック (AES の場合) になるまで待機しています。おそらく、ストリーム暗号モード (CTR または GCM) の AES は、バイトごとの暗号化を使用し、各バイトを直接送信できるため、ここではより便利です。

于 2012-02-23T00:38:09.070 に答える