通过 UDP 发送 RC4 加密数据导致解密明文发生变化

Sending RC4 encrypted data over UDP causes changes in decrypted plaintext

我正在尝试使用 Java 通过 UDP 连接发送一些数据。

在客户端,我使用 returns 字符串的 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);
        
        //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);
    
    }
}

这是服务器:

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);
}

这是客户端输出:

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'Æ it goinÆ? I'm doÆng fine; thanks.

我认为这是字符串编码的问题。除非您绝对确定两端使用相同的平台编码,否则切勿在未指定编码的情况下使用 String.getBytes()

任何需要转换的地方(RC4.decryptRC4()/RC4.encryptRC4()new String()String.getBytes()byte[]/String 执行此操作:

Stringbyte[].getBytes(StandardCharsets.UTF_8)

byte[]Stringnew String(byte[], int, int, StandardCharsets.UTF_8)

不管是UTF-8还是ISO-8859-1,只要两端相同.

哦,正如@MarquisofLorne 所说,请不要使用 RC4,除非它仅用于教育目的。