从 DatagramPacket 转换为字节数组时添加的填充

Padding added while converting from DatagramPacket to bye array

我正在尝试将 RSA public 密钥从 UDP 服务器传递到 Java 上的客户端。

为此,我在服务器端生成了一个 public 密钥,将其转换为字节数组并将其作为 DatagramPacket 传递给客户端。

不幸的是,在客户端,虽然接收到的数据包与发送的数据包具有相同的大小,但在我将数据包数据保存到字节数组中后,由于在接收到的数据后添加了一些填充,大小急剧增加。

如何去掉这个填充?

这是服务器的代码:

import java.net.*; import javax.crypto.Cipher; import java.io.*; import java.security.*; import java.security.spec.*; import java.util.*; import java.util.Base64.*;
 
class EchoServer 
{
    public static void main( String args[] ) throws Exception 
    {
        System.out.println("Server running. Awaiting Connection Request...\n");
        
        DatagramSocket socket = new DatagramSocket(1500);
        
        //Receive Username
        DatagramPacket packetU = new DatagramPacket(new byte[512],512);
        socket.receive( packetU );
        
        //Generate Key Pair
        System.out.println("Generating Key Pair");
        KeyPair pair = RSA.generateKeyPair();
        byte[] encodedPrivateKey = pair.getPrivate().getEncoded();
        byte[] encodedPublicKey = pair.getPublic().getEncoded();
        
        System.out.println("\nPublic Key: " + Base64.getEncoder().encodeToString(encodedPublicKey));
        
        //Sending Public Key
        System.out.println("Sending Public Key");
        DatagramPacket packetPK = new DatagramPacket(encodedPublicKey,encodedPublicKey.length,packetU.getAddress(),packetU.getPort());
            socket.send( packetPK );
            System.out.println("Packet length: " + packetPK.getLength());
}
}

对于客户:

import java.net.*; import javax.crypto.Cipher; import java.io.*; import java.security.*; import java.security.spec.*; import java.util.*; import java.util.Base64.*;
 
 
class EchoClient 
{
    public static void main( String args[] ) throws Exception 
    {
        Scanner sc = new Scanner (System.in);
        
        DatagramSocket socket = new DatagramSocket();
        socket.setSoTimeout(120000);
        
        //Initiate Authentication
        System.out.print("Enter username: ");
        String username = sc.nextLine();            
        byte[] uname = username.getBytes();
        DatagramPacket packetU = new DatagramPacket(uname,uname.length,InetAddress.getByName(args[0]),1500);
        socket.send( packetU );
        
        //Recieving Public Key
        System.out.println("Public Key Recieved");
        DatagramPacket packetPK = new DatagramPacket(new byte[512],512);
        socket.receive( packetPK );
        byte[] publicKey = packetPK.getData();
        System.out.println("Packet length: " + packetPK.getLength());
        System.out.println("Byte[] length: " + publicKey.length);
        System.out.println( "Alice at: "+new Date()+" "+packetPK.getAddress()+":"+packetPK.getPort()+"\nPublic Key: "+Base64.getEncoder().encodeToString(publicKey));
    
    }
}

这是我在服务器端收到的输出:

服务器运行。等待连接请求...

正在生成密钥对

Public Key: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhYGTu7revdBCqdSm7ksM9qyagDirjsXtq52hPDdARoVbBNbZmZh4OoyNNorLqQqQzfF1oy9YtiDF4CLEip1t1T3oL2oRu1AQyIFlbbUyBoDh1jmvse0yAE2wcBumjZ1v8AvqV8tqzbn42uIaeBNjy3z5jLLx7NH80djSCHzkw1yCC+zs1uMJ8ZfuqPdDGqtOTskvw8qZ0LbhKcUFI1yLwkjlu1sVrZu1P86GTazEswV+B9f8255jyzS6AYR4+xosbvJpuyyQVahZ+LNRIAFFXnMe4BNX1WsT5hSlWOgtNy7NtKJSfXMts4RWJccZNznX8dRxZYPmZBEi7yI1WDHXkQIDAQAB 发送 Public 密钥 数据包长度:294

客户端输出:

输入用户名:你好

Public 密钥已收到

数据包长度:294

字节[]长度:512

爱丽丝时间:7 月 27 日星期一 22:59:29 IST 2020 /127.0.0.1:1500

Public Key: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhYGTu7revdBCqdSm7ksM9qyagDirjsXtq52hPDdARoVbBNbZmZh4OoyNNorLqQqQzfF1oy9YtiDF4CLEip1t1T3oL2oRu1AQyIFlbbUyBoDh1jmvse0yAE2wcBumjZ1v8AvqV8tqzbn42uIaeBNjy3z5jLLx7NH80djSCHzkw1yCC+zs1uMJ8ZfuqPdDGqtOTskvw8qZ0LbhKcUFI1yLwkjlu1sVrZu1P86GTazEswV+B9f8255jyzS6AYR4+xosbvJpuyyQVahZ+LNRIAFFXnMe4BNX1WsT5hSlWOgtNy7NtKJSfXMts4RWJccZNznX8dRxZYPmZBEi7yI1WDHXkQIDAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=

在客户端,您将获得分配的完整缓冲区,而不仅仅是发送的数据:

byte[] publicKey = packetPK.getData();

您还需要获取已发送数据的长度,并且只打印数据缓冲区的那部分:

int len = packetPK.getLength();

https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/net/DatagramPacket.html#getData()

当您将字节数组转换为字符串时,您会看到您得到了正确的响应。尝试:

        String x = new String(publicKey);
        System.out.println(x);

所以你看,是 byteArray 的空元素导致了这个问题。 要么将 publicKey 转换为 String 然后使用它,要么截断字节数组以删除空白数组元素。两者都有效

我已经弄明白了。多亏了这里的答案,我做了更多的研究,发现我没有直接将数据包复制到字节数组,而是执行了以下操作:

byte[] publicKey = new byte[packetPK.getLength()];
    
System.arraycopy(packetPK.getData(), packetPK.getOffset(), publicKey, 0, packetPK.getLength());

我想到使用 ArrayList,因为字节数组被初始化为可变大小,但据我所知,上述方法也没有错,因为 Java 数组是动态的。