gpt4 book ai didi

java - 通过tcp进行aes加解密。使用填充密码解密时输入长度必须是16的倍数

转载 作者:行者123 更新时间:2023-12-01 11:38:28 24 4
gpt4 key购买 nike

运行程序时,我看到“使用填充密码解密时,输入长度必须是 16 的倍数”错误

RealEchoServer.java

import java.io.*;
import java.net.*;
import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;
public class RealEchoServer {

public static void main(String[] args) {
int i = 1;
try {
ServerSocket s = new ServerSocket(9003);

for (;;) {
Socket incoming = s.accept();
System.out.println("Spawning " + i);
new RealEchoHandler(incoming, i).start();
i++;
}
} catch (Exception e) {
System.out.println(e);
}
}
}

class RealEchoHandler extends Thread {

DataInputStream in;
DataOutputStream out;
private Socket incoming;
private int counter;

public RealEchoHandler(Socket i, int c) {
incoming = i;
counter = c;
}

public void run() {
try {

String key1 = "1234567812345678";
byte[] key2 = key1.getBytes();
SecretKeySpec secret = new SecretKeySpec(key2, "AES");
String msg = "Singapore Malaysia Japan India Indonesia HongKong Taiwan China England";
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, secret);
byte[] encrypted = cipher.doFinal(msg.getBytes());

in = new DataInputStream(incoming.getInputStream());
out = new DataOutputStream(incoming.getOutputStream());

boolean done = false;
String str = "";
out.writeUTF("Connected!\n");
out.flush();
while (!done) {
out.writeUTF(">");
out.flush();
str = in.readUTF();
System.out.println(in + ":" + str);
if (str == null) {
done = true;
} else {
System.out.println("Sending Ciphertext : " + new String(encrypted));
out.writeUTF(new String(encrypted));
out.flush();
}
}
incoming.close();
} catch (Exception e) {
System.out.println(e);
}
}
}

RealSocketTest.java

   import java.io.*;
import java.net.*;
import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import java.util.*;

class RealSocketTest {
public static void main(String[] args) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {

String str = "";
String str2 = "";
DataOutputStream out;
DataInputStream in;

try {
Socket t = new Socket("127.0.0.1", 9003);
in = new DataInputStream(t.getInputStream());
out = new DataOutputStream(t.getOutputStream());
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

boolean more = true;
System.out.println(in.readUTF());

while (more) {
str = in.readUTF();
System.out.print(str);
str2 = br.readLine();
out.writeUTF(str2);
out.flush();
str = in.readUTF();

System.out.println("Encrypted Info: " + str);

try {

String key1 = "1234567812345678";
byte[] key2 = key1.getBytes();
SecretKeySpec secret = new SecretKeySpec(key2, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, secret);
byte[] decrypted = cipher.doFinal(str.getBytes());
System.out.println("Decrypted Info: " + new String(decrypted));
} catch (BadPaddingException e) {
System.out.println("Wrong Key!");
} catch (InvalidKeyException f) {
System.out.println("Invalid Key!");
}
}
} catch (IOException e) {
System.out.println("Error");
}
}
}

我在这里读到了类似的问题 Illegal Block Size Exception Input length must be multiple of 16 when decrypting with padded cipher ,但我不明白如何改变我的问题,因为它看起来与我的非常不同。

那么应该添加/更改什么才能解密?

最佳答案

问题是密文可能包含所有可能的字节值。另一方面,许多字节值不可打印,因此不是有效的 UTF-8 编码。当您用它new String(encrypted)创建一个字符串时,它会默默地删除一些字节,并且您将无法成功解密密文。

两个可能的修复:

  • 将密文编码为 Base64 或 Hex,以便在基于文本的协议(protocol)中使用。
  • 使用DataOutputStream::write()方法使其成为二进制协议(protocol)而不对其进行编码。
<小时/>

其他安全内容:

  • 始终为预期的 Cipher 实例指定完整的字符串。不同的提供者可能有不同的默认值,并且客户端和服务器可能不使用相同的方法。示例:AES/ECB/PKCS5Padding

  • 切勿使用 ECB 模式。它在语义上并不安全。至少使用带有随机 IV 的 CBC(将 IV 放在密文前面或按顺序将其写入流)。

  • 检查您的密文是否被操纵。通过采用 GCM(AES/GCM/NoPaddingGCMParameters)等身份验证模式,可以轻松完成此操作。如果您不希望这样,那么至少尝试实现一个先加密后 MAC 方案,其中您对密文(使用不同的 key )进行 HMAC 并在解密之前对其进行检查。

关于java - 通过tcp进行aes加解密。使用填充密码解密时输入长度必须是16的倍数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29756654/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com