总结环境:我正在使用名为Packet
的类构建网络库,为简单起见,我将其称为po
。当我收到带有Java Socket的数据包时,它会将收到的数据转换为po
。
接收方式:
public Packet ReceiveUnencryptedPacket() throws ReadPacketException {
Packet p = new Packet(Packet.PACKET_TYPE.NULL, ""); // Packet is my 'po'
if (!connectionActive)
return p;
try {
// in is ObjectInputStream
p = (Packet) in.readObject(); // <-- receiving and casting to 'po'
} catch (IOException e) {
throw new ReadPacketException(
"Error reading the received data. Possible causes: Wrong Object Type; Incomplete Send;");
} catch (ClassNotFoundException e) {
throw new ReadPacketException(
"Unable to find class Packet when reading in the data from the socket stream! Fatal Error.");
}
return p;
}
写作方法:
public boolean SendUnencryptedPacket(Packet p) throws SendPacketException {
if (!connectionActive)
return false;
try {
out.writeObject(p); // out is ObjectOutputStream
out.flush();
return true;
} catch (IOException e) {
throw new SendPacketException("Error sending packet to socket. PacketType: " + p.packetType.toString()
+ ". PacketMessage: " + p.packetString);
}
}
这已经有效,没有任何问题。
现在为有趣的部分。我正在尝试实现我为教育目的而构建的RSA 512位加密库(不是为了学校,只是为了学习)。没有网络,加密就可以生成密钥,接受密钥,加密和解密对象。
当我对网络库实施加密时,接收从任何一方发送的po
都有问题。例如,我有握手。当服务器发送它的公钥时,客户端可以读取它,因为它是未加密的。但是当客户端尝试发送它的公钥时,服务器无法将其转换为po
对象来读取它。 po
类有一个构造函数,它将byte[]
作为参数并将其转换为po
对象,然后将所有值复制到自身中。
这是该实例的po
构造函数:
public Packet(byte[] packetBytes) throws IOException, ClassNotFoundException {
Packet p;
ByteArrayInputStream bis = new ByteArrayInputStream(packetBytes);
ObjectInput in = new ObjectInputStream(bis);
p = (Packet) in.readObject();
// data assignment omitted for space-saving. Not the issue
}
当从保存的文件中读取保存的对象时,此构造函数运行正常,我认为这也不是问题。
然而,需要注意的是。 ObjectInput in = new ObjectInputStream(bis)
是抛出异常的地方。
要创建新的po
对象,我有这个方法。它从套接字接收BigInteger
数组,并对其进行处理。
public Packet ReceivePacket() throws ReadPacketException {
Packet p = new Packet(Packet.PACKET_TYPE.NULL, "");
if (!connectionActive)
return p;
try {
BigInteger[] encryptedBytes = (BigInteger[]) in.readObject();
byte[] packetBytes = new byte[encryptedBytes.length];
for (int i = 0; i < encryptedBytes.length; i++) {
packetBytes[i] = kript.decrypt(encryptedBytes[i]);
}
p = new Packet(packetBytes); // PROBLEM CHILD, PACKET ISN'T ABLE TO
// BE CREATED//
return p;
} catch (IOException e) {
e.printStackTrace(); // <-- happens any time an encrypted packet is received. Traces back to the declaration in the `po` constructor I mentioned directly above
throw new ReadPacketException(
"Error reading the received data. Possible causes: Wrong Object Type; Incomplete Send;");
} catch (ClassNotFoundException e) {
throw new ReadPacketException(
"Unable to find class Packet when reading in the data from the socket stream! Fatal Error.");
}
}
引发的异常是:
java.io.StreamCorruptedException: invalid stream header: DD1E0005
at java.io.ObjectInputStream.readStreamHeader(Unknown Source)
at java.io.ObjectInputStream.<init>(Unknown Source)
at Netta.Connection.Packet.<init>(Packet.java:80)
at Netta.Connection.Connection.ReceivePacket(Connection.java:189)
at Netta.Connection.Server.ConnectedClient.HandShake(ConnectedClient.java:106)
at Netta.Connection.Server.ConnectedClient.<init>(ConnectedClient.java:40)
at Heart.ClientConnection.<init>(ClientConnection.java:21)
at Heart.Server.ThreadAction(Server.java:27)
at Netta.Connection.Server.MultiClientServer.run(MultiClientServer.java:89)
at java.lang.Thread.run(Unknown Source)
提到的流标头每次抛出都会发生变化。
因此,我首先想到的是套接字收到的数据包也已损坏或加密。但是,我不认为可能是这种情况,看看套接字如何处理自己的通信,加密解密的数据是我可以使用的。
可以肯定的是,这是加密的发送方法:
public boolean SendPacket(Packet p) throws SendPacketException { // Packet p is my `po` object
if (!connectionActive)
return false;
try {
byte[] packetBytes = p.ToBytes();
BigInteger[] encryptedBytes = new BigInteger[packetBytes.length];
for (int i = 0; i < packetBytes.length; i++) {
encryptedBytes[i] = kript.encrypt(packetBytes[i]);
}
out.writeObject(encryptedBytes);
out.flush();
return true;
} catch (IOException e) {
throw new SendPacketException("Error sending packet to socket. PacketType: " + p.packetType.toString()
+ ". PacketMessage: " + p.packetString);
}
}
为什么当我发送未加密的数据包时,一切正常,但是一旦加密就无法创建要读取的po
对象?