从 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 数组是动态的。
我正在尝试将 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 数组是动态的。