2017-06-13 71 views
0

我認爲我錯過了一些東西,我相信圖像(轉換爲字節)正在加密,但到達客戶端時並未解密。該圖像似乎通過了RSA簽名驗證,但無法查看。Android rc4加密

客戶端代碼:

public void aliceEncrypt(byte[] plaintext, byte[] sharedSecret) { 

    Cipher cipher; 
    byte[] encrypted = null; 
    try { 
     cipher = Cipher.getInstance("RC4"); 
     Key sk = new SecretKeySpec(sharedSecret, "RC4"); 
     cipher.init(Cipher.ENCRYPT_MODE, sk); 
     encrypted = cipher.doFinal(plaintext); 
     CipherOutputStream cos = new CipherOutputStream(socket.getOutputStream(), cipher); 
     ObjectOutputStream oos = new ObjectOutputStream(cos); 
     oos.writeObject(encrypted); 
     oos.flush(); 

    } catch (NoSuchAlgorithmException | NoSuchPaddingException | IOException | InvalidKeyException e) { 
     e.printStackTrace(); 
    } catch (BadPaddingException e) { 
     e.printStackTrace(); 
    } catch (IllegalBlockSizeException e) { 
     e.printStackTrace(); 
    } 
} 

服務器端代碼:

public byte[] bobDecrypt(byte[] sharedSecret) { 


    Cipher cipher = null; 
    byte[] bytes = null; 
    byte[] decrypted = null; 
    try { 
     cipher = Cipher.getInstance("RC4"); 
     Key sk = new SecretKeySpec(sharedSecret, "RC4"); 
     cipher.init(Cipher.DECRYPT_MODE, sk); 
     CipherInputStream cis = new CipherInputStream(socket.getInputStream(), cipher); 
     ObjectInputStream ois = new ObjectInputStream(cis); 
     bytes = (byte[])ois.readObject(); 
     decrypted = cipher.doFinal(bytes); 

    } catch (NoSuchAlgorithmException | NoSuchPaddingException | IOException | InvalidKeyException | ClassNotFoundException e) { 
     e.printStackTrace(); 
    } catch (BadPaddingException e) { 
     e.printStackTrace(); 
    } catch (IllegalBlockSizeException e) { 
     e.printStackTrace(); 
    } 
    return decrypted; 
} 
+1

我不認爲那些RC4存在,請糾正我,如果我錯了。 RC4是流密碼,不需要填充。 – Melo

+0

我沒有得到,你是建議我刪除cipher.doFinal()?數據仍然會被加密嗎? – Melo

+0

好吧,你清除我的困惑,它工作,謝謝隊友。我不確定我是否可以將cipher.doFinal刪除。你可以構建你的答案,我會接受它。 – Melo

回答

1

CipherInputStreamCipherOutputStream是爲了做所有的繁重,所以你只要有一個初始化Cipher實例提供給他們,然後使用寫入和讀取流方法。大多數情況下,您可以將這些數據與輸入和輸出流一起分層,但有一點微妙之處:使用分組密碼時,沒有好的方法可以通知CipherOutputStream它需要調用Cipher.doFinal()。唯一支持的方法是調用close()方法。這些close()調用將 傳播到其他包裝流,並且在這種情況下,套接字Outputstream被封裝後,它最終會關閉套接字作爲副作用。這可能是完全可以接受的行爲,但你需要意識到這一點。在這種情況下,因爲你使用的是一個面向字節的流密碼(RC4),所以沒有填充,所以Cipher.doFinal()基本上是空操作(當然,它會重設密碼狀態),所以調用flush()就好呼籲close()。下面的代碼基本上修改了您的代碼,以正確顯示如何分層和使用各種流。

public void aliceEncrypt(byte[] plaintext, byte[] sharedSecret, Socket socket) { 

    try { 
     Cipher cipher = Cipher.getInstance("RC4/ECB/NoPadding"); 
     Key sk = new SecretKeySpec(sharedSecret, "RC4"); 
     cipher.init(Cipher.ENCRYPT_MODE, sk); 
     CipherOutputStream cos = new CipherOutputStream(socket.getOutputStream(), cipher); 
     ObjectOutputStream oos = new ObjectOutputStream(cos); 
     oos.writeObject(plaintext); 
     oos.close(); 

    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 


public byte[] bobDecrypt(byte[] sharedSecret, Socket socket) { 


    try { 
     Cipher cipher = Cipher.getInstance("RC4/ECB/NoPadding"); 
     Key sk = new SecretKeySpec(sharedSecret, "RC4"); 
     cipher.init(Cipher.DECRYPT_MODE, sk); 
     CipherInputStream cis = new CipherInputStream(socket.getInputStream(), cipher); 
     ObjectInputStream ois = new ObjectInputStream(cis); 
     byte[] bytes = (byte[]) ois.readObject(); 
     return bytes; 

    } catch (Exception e) { 
     e.printStackTrace(); 
     return null; 
    } 
}