发送经过RC4加密的数据通过UDP引起解密后明文的变化

huangapple go评论78阅读模式
英文:

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(&quot;Enter data: &quot;);
		String password = sc.nextLine();
		String credentials = password;
		String encryptedCredentials = RC4.encryptRC4(credentials, &quot;637443&quot;);
		byte encCred[] = encryptedCredentials.getBytes();
		DatagramPacket packetCred = new DatagramPacket(encCred,encCred.length,InetAddress.getByName(args[0]),1500);
		socket.send(packetCred);
		System.out.println(&quot;\nEncrypted Credentials sent&quot;);
		System.out.println(&quot;Plain: &quot; + credentials);
		System.out.println(&quot;Encrypted data: &quot; + 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(&quot;Server running. Awaiting Connection Request...\n&quot;);

		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, &quot;637443&quot;);
		System.out.println(&quot;\nReceived Authentication Data&quot;);
		System.out.println(&quot;Bob at: &quot;+new Date()+&quot; &quot;+packetCred.getAddress()+&quot;:&quot;+packetCred.getPort()+&quot;\nData: &quot;+new String(packetCred.getData(),0,packetCred.getLength()));
		System.out.println(&quot;Decrypted Credentials: &quot; + 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())都要这样做:

Stringbyte[].getBytes(StandardCharsets.UTF_8)

byte[]Stringnew 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.

huangapple
  • 本文由 发表于 2020年7月29日 07:44:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/63144338.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定