2012-02-22 4 views
1

클라이언트 - 서버 기반 Java 응용 프로그램을 프로그래밍하고 있는데 클라이언트와 서버 모두에서 ObjectInputStream을 구성 할 때 중단되므로 문제가 발생합니다.CipherInputStream이 고정 된 상태의 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

DES.getEncryptCipher는 어떤 종류의 암호를 반환합니까? 반환 된 암호의 알고리즘과 상태를 인쇄 할 수 있습니까? 패딩을 수행하는 Cipher가 필요할 수도 있습니다. 그렇지 않으면 정확히 N * [블록 크기] 바이트가 계산을 마칠 때까지 기다릴 수 있습니다. * DES가 안전하지 않음을 유의하십시오. AES * –

+0

DES는 단지 예일 뿐이므로 다른 클래스를 테스트하고 있습니다. 기본 암호화 클래스는 DES가 아닌 위의 암호화 클래스입니다. – user1227115

+0

좋습니다.하지만 "AES/CBC/PKCS5Padding"을 암호로 사용하는 것은 적어도 "AES/ECB/PKCS5Padding"으로 기본 설정되어 있습니다. ECB는 안전하지 않습니다. 헤더 및 객체와 같은 무작위 화되지 않은 바이트의 경우 –

답변

1

모두으로 정보를 보낸 후에 만 ​​ObjectInputStream을 만들어야합니다. 헤더를 읽어야하기 때문에 ObjectInputStream 생성자가 차단되기 때문에 정보가 끝났습니다.

보통, 모든 바이트는 ObjectOutputStream에 의해 쓰여지지만 CipherOutputStream은 (헤더의 마지막 부분을 보내기 전에) AES의 경우 전체 16 바이트 블록이있을 때까지 대기합니다. . 어쩌면 스트림 암호 모드 (CTR 또는 GCM)의 AES가 바이트 당 암호화를 사용하고 각 바이트를 직접 보낼 수 있기 때문에 더 유용 할 것입니다.

+0

생성자를 생성 한 직후에 바이트의 바이트 배열을 작성한 다음 ObjectOutputStream을 플러시하는 등 수행 할 수있는 해킹이 있습니다. 물론 다른 쪽에서도 16 바이트의 스퓨리어스를 읽어야합니다. –

+0

당신이 질문에 따라, user1227115, 또는 어쩌면 동의 버튼을 누르면 좋을 것입니다. –