当我在没有close方法的情况下运行此代码时,服务器无法接收消息!
客户端:
Socket con = new Socket(InetAddress.getByName("localhost"), 12345);
InputStream is = con.getInputStream();
OutputStream os = con.getOutputStream();
byte[] key = new byte[]{5};
DataOutputStream dos = EncryptIO.getEncryptedOutputStream(key, os);
DataInputStream dis = EncryptIO.getEncryptedInputStream(key, is);
dos.writeUTF("Player 2");
dos.close(); //with this the server receives the message
String opUsername = dis.readUTF();
服务器:
ServerSocket serverSocket = new ServerSocket(12345);
Socket con = serverSocket.accept();
InputStream is = con.getInputStream();
OutputStream os = con.getOutputStream();
byte[] key = new byte[]{5};
DataOutputStream dos = EncryptIO.getEncryptedOutputStream(key, os);
DataInputStream dis = EncryptIO.getEncryptedInputStream(key, is);
String opUsername = dis.readUTF();
System.out.println(opUsername);
dos.writeUTF("Player 1"); //this line isn't reached because DataInputStream waits for the data
在DataOutput / InputStream下面是Cipherstreams底层没有它们可以工作!
EncryptIO代码:
public static DataInputStream getEncryptedInputStream(byte[] key, InputStream is) throws InvalidKeyException, InvalidAlgorithmParameterException, NoSuchPaddingException {
try {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, EncryptIO.getAESKey(key), EncryptIO.getIV(key));
CipherInputStream cis = new CipherInputStream(is, cipher);
return new DataInputStream(cis);
} catch (NoSuchAlgorithmException ex) {
Logger.getLogger(EncryptIO.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
public static DataOutputStream getEncryptedOutputStream(byte[] key, OutputStream os) throws InvalidKeyException, NoSuchPaddingException, InvalidAlgorithmParameterException {
try {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, EncryptIO.getAESKey(key), EncryptIO.getIV(key));
CipherOutputStream cos = new CipherOutputStream(os, cipher);
return new DataOutputStream(cos);
} catch (NoSuchAlgorithmException ex) {
Logger.getLogger(EncryptIO.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
如何让DataOutputStream通过加密发送数据而不关闭?
提前致谢
答案 0 :(得分:2)
这
Cipher.getInstance("AES/CBC/PKCS5Padding")
您正在使用带有PKCS5Padding的CBC模式的AES密码。根据{{3}}(重新格式化,包含原始链接):
<强> AES 强>
NIST在Java Cryptography Architecture Standard Algorithm Name Documentation for JDK 8中指定的高级加密标准。 也被称为Joan Daemen和Vincent的Rijndael算法 Rijmen,AES是128位分组密码,支持128,192和128的密钥 256位。
要仅使用一个有效密钥大小的AES密码,请使用该格式 AES_,其中可以是128,192或256。
和
<强> CBC 强>
密码块链接模式,如FIPS 197中所定义。
和
<强> PKCS5Padding 强>
FIPS PUB 81中描述的填充方案。
因此,一个块密码,可能是128位(16字节),带填充。
请注意密码算法模式:
CFB,CFBx
密码反馈模式,如RSA Laboratories, "PKCS #5: Password-Based Encryption Standard," version 1.5, November 1993中所定义。
使用CFB和OFB等模式,分组密码可以加密数据 单位小于密码的实际块大小。请求时 在这种模式下,您可以选择指定要的位数 通过将此数字附加到模式名称来一次处理,如图所示 在“DES / CFB8 / NoPadding”和“DES / OFB32 / PKCS5Padding”中 转换。如果未指定此类号码,则特定于提供者 使用默认值。 (例如,SunJCE提供程序使用默认值 DES的64位。)因此,块密码可以转换为面向字节的 通过使用8位模式(如CFB8或OFB8 )来流密码。
因此"AES/CFB8/NoPadding"
或类似内容应该作为非阻塞流密码。但是,您可能仍需要flush()
。并且可能会对性能产生影响。