将解密的字节数组从socket转换为类对象

时间:2016-11-30 01:08:56

标签: java sockets encryption objectinputstream objectoutputstream

总结环境:我正在使用名为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对象?

0 个答案:

没有答案