我认为我遗漏了一些东西,我相信图像(转换为字节)正在加密但在到达客户端时不会被解密。该图像似乎通过了RSA签名验证,但无论如何都无法查看。
客户端代码:
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;
}
答案 0 :(得分:2)
CipherInputStream
和CipherOutputStream
旨在完成所有繁重工作,因此您只需为其提供初始化的Cipher
实例,然后使用写入和读取流方法。在大多数情况下,您可以将它们与输出和输出流分层,但有一个微妙之处:当使用分组密码时,没有好的方法来通知它需要调用Cipher.doFinal()
的CipherOutputStream。唯一支持的方法是调用close()
方法。这些close()
次调用会传播
对于其他包装的流,在这种情况下,套接字Outputstream被包装,它最终会关闭套接字作为副作用。这可能是完全可以接受的行为,但您需要了解它。在这种情况下,因为你使用的是面向字节的流密码(RC4),所以没有填充,所以Cipher.doFinal()
基本上是无操作的(好吧,它确实重置了密码状态),所以调用{ {1}}与调用flush()
一样好。下面的代码基本上是您的代码修改,以正确显示如何分层和使用各种流。
close()