英文:
Sending RC4 encrypted data over UDP causes changes in decrypted plaintext
问题
我正在尝试使用Java发送一些数据通过UDP连接。
在客户端,我使用RC4算法对数据进行加密,返回一个字符串。然后,我将此字符串转换为字节数组并将其发送为数据包。
然而,在服务器端,解密后的明文与原始数据类似,但存在一些差异。
RC4加密程序在我独立运行它时运行良好,并且客户端和服务器都使用相同的源代码,所以我真的不明白为什么会发生这种情况。
以下是客户端的代码:
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);
//加密并发送数据
System.out.print("Enter data: ");
String password = sc.nextLine();
String credentials = password;
String encryptedCredentials = RC4.encryptRC4(credentials, "637443");
byte encCred[] = encryptedCredentials.getBytes();
DatagramPacket packetCred = new DatagramPacket(encCred,encCred.length,InetAddress.getByName(args[0]),1500);
socket.send(packetCred);
System.out.println("\nEncrypted Credentials sent");
System.out.println("Plain: " + credentials);
System.out.println("Encrypted data: " + encryptedCredentials);
}
}
以下是服务器端的代码:
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");
Scanner sc = new Scanner (System.in);
DatagramSocket socket = new DatagramSocket(1500);
//接收凭据
DatagramPacket packetCred = new DatagramPacket(new byte[512],512);
socket.receive(packetCred);
String stringCred = new String(packetCred.getData(),0,packetCred.getLength());
String decryptedCred = RC4.decryptRC4(stringCred, "637443");
System.out.println("\nReceived Authentication Data");
System.out.println("Bob at: "+new Date()+" "+packetCred.getAddress()+":"+packetCred.getPort()+"\nData: "+new String(packetCred.getData(),0,packetCred.getLength()));
System.out.println("Decrypted Credentials: " + decryptedCred);
}
}
以下是客户端终端输出:
> Enter data: Hello there. How's it going? I'm doing fine; thanks.
>
> Setting up RC4...
>
> Starting RC4 encryption...
>
> Encryption Complete:
>
> Encrypted Credentials sent
>
> Plain: Hello there. How's it going? I'm doing fine; thanks.
>
> Encrypted data: ?d¥érSÿ?dNé?=P°?Whéá=Nù?H!)îërC??f@?ï<B¬?i?í!
以下是服务器端终端输出:
> Server running. Awaiting Connection Request...
>
> Setting up RC4...
>
> Starting RC4 decryption...
>
> Decryption Complete:
>
> Received Authentication Data
>
> Bob at: Wed Jul 29 05:01:51 IST 2020 /127.0.0.1:54835
>
> Data: ?d¥érSÿ?dNé?=P°?Whéá=Nù?H!)îërC??f@?ï<B¬?i?í!
>
> Decrypted Credentials: Hello thÆre. How'sÆ it goinÆ? I'm doÆng fine;
> thanks.
英文:
I'm trying to send some data across a UDP connection using Java.
At the Client, I encrypt the data with an RC4 algorithm which returns a string. This string, I convert to a byte array and send it as a Datagram Packet.
However, at the Server, the decrypted plaintext gives a result similar to the original but with some differences.
The RC4 encryption program works fine when I run it independently and both Client and Server use the same source code so I really don't understand why this is happening.
Here's the code for the Client side:
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);
//Encrypting and sending data
System.out.print("Enter data: ");
String password = sc.nextLine();
String credentials = password;
String encryptedCredentials = RC4.encryptRC4(credentials, "637443");
byte encCred[] = encryptedCredentials.getBytes();
DatagramPacket packetCred = new DatagramPacket(encCred,encCred.length,InetAddress.getByName(args[0]),1500);
socket.send(packetCred);
System.out.println("\nEncrypted Credentials sent");
System.out.println("Plain: " + credentials);
System.out.println("Encrypted data: " + encryptedCredentials);
}
}
And here's the Server:
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");
Scanner sc = new Scanner (System.in);
DatagramSocket socket = new DatagramSocket(1500);
//Recieving Credentials
DatagramPacket packetCred = new DatagramPacket(new byte[512],512);
socket.receive(packetCred);
String stringCred = new String(packetCred.getData(),0,packetCred.getLength());
String decryptedCred = RC4.decryptRC4(stringCred, "637443");
System.out.println("\nReceived Authentication Data");
System.out.println("Bob at: "+new Date()+" "+packetCred.getAddress()+":"+packetCred.getPort()+"\nData: "+new String(packetCred.getData(),0,packetCred.getLength()));
System.out.println("Decrypted Credentials: " + decryptedCred);
}
Here's the Client terminal output:
> Enter data: Hello there. How's it going? I'm doing fine; thanks.
>
> Setting up RC4...
>
> Starting RC4 encryption...
>
> Encryption Complete:
>
> Encrypted Credentials sent
>
> Plain: Hello there. How's it going? I'm doing fine; thanks.
>
> Encrypted data: ?d¥érSÿ?dNé?=P°?Whéá=Nù?H!)îërC??f@?ï<B¬?i?í!
And here's the Server terminal output:
> Server running. Awaiting Connection Request...
>
> Setting up RC4...
>
> Starting RC4 decryption...
>
> Decryption Complete:
>
> Received Authentication Data
>
> Bob at: Wed Jul 29 05:01:51 IST 2020 /127.0.0.1:54835
>
> Data: ?d¥érSÿ?dNé?=P°?Whéá=Nù?H!)îërC??f@?ï<B¬?i?í!
>
> Decrypted Credentials: Hello thÆre. How'Æ it goinÆ? I'm doÆng fine;
> thanks.
答案1
得分: 0
我认为这是与字符串编码有关的问题。除非你确信两端使用相同的平台编码,否则永远不要使用String.getBytes()
而不指定编码。
在需要转换byte[]/String
的任何地方(RC4.decryptRC4()/RC4.encryptRC4()
,new String()
,String.getBytes()
)都要这样做:
从String
到byte[]
:.getBytes(StandardCharsets.UTF_8)
从byte[]
到String
:new String(byte[], int, int, StandardCharsets.UTF_8)
重要的是它在两端是一样的,无论是UTF-8还是ISO-8859-1。
哦,正如@MarquisofLorne所说,除非仅用于教育目的,否则请不要使用RC4。
英文:
I think it's a problem with string encoding. Never use String.getBytes()
without specifying an encoding unless you're absolutely sure that both ends use the same platform encoding.
Everywhere (RC4.decryptRC4()/RC4.encryptRC4()
, new String()
, String.getBytes()
) where you need to convert byte[]/String
do this:
From String
to byte[]
: .getBytes(StandardCharsets.UTF_8)
From byte[]
to String
: new String(byte[], int, int, StandardCharsets.UTF_8)
It doesn't really matter if it's UTF-8 or ISO-8859-1, as long as it is the same in both ends.
Oh, as @MarquisofLorne said, please don't use RC4 unless its for educational purposes only.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论