【发布时间】:2020-02-28 09:22:40
【问题描述】:
我正在创建一个带有加密的回显服务器/客户端。基本上我希望程序做的是:
- 用户在客户端输入字符串
- 客户端加密字符串
- 客户端将加密后的字符串发送给服务器
- 服务器收到字符串
- 服务器将字符串发送回客户端
- 客户端收到字符串
- 客户端解密字符串
- 客户端显示解密后的字符串
我的问题是,当客户端尝试解密从服务器接收到的字符串时,它失败并抛出这个错误:
Exception in thread "main" javax.crypto.IllegalBlockSizeException: Input length
must be multiple of 8 when decrypting with padded cipher
at java.base/com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:936)
at java.base/com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:847)
at java.base/com.sun.crypto.provider.DESCipher.engineDoFinal(DESCipher.java:314)
at java.base/javax.crypto.Cipher.doFinal(Cipher.java:2202)
at EnClient.decrypt(EnClient.java:100)
at EnClient.main(EnClient.java:85)
我尝试在将字符串发送到服务器之前对其进行解密,然后它工作正常,所以这肯定与字符串通过套接字到服务器并返回有关。而且我还注意到,当加密字符串的填充存在某种问题时,我经常会发生错误。除了我能够收集到的信息之外,我不知道该怎么做或如何解决这个问题。所以我需要你的帮助。首先请告诉我我的假设是否正确以及您对如何解决此问题的建议。
客户端代码:
c1 = Cipher.getInstance("DES");
String userInput;
while ((userInput = stdIn.readLine()) != null) {
byte[] eui = encrypt(userInput);
System.out.println(eui);
System.out.println(decrypt(eui));
out.println(eui.toString());
byte[] ein = in.readLine().getBytes();
String din = decrypt(ein);
System.out.println(din);
}
...
private static String decrypt(byte[] encryptionBytes) throws Exception{
c1.init(Cipher.DECRYPT_MODE, k);
byte[] recoveredBytes = c1.doFinal(encryptionBytes);
String recovered = new String(recoveredBytes);
return recovered;
}
private static byte[] encrypt(String input) throws Exception {
c1.init(Cipher.ENCRYPT_MODE, k);
byte[] ib = input.getBytes();
return c1.doFinal(ib);
}
服务器代码:
String inputLine;
while ((inputLine = in.readLine()) != null) {
out.println(inputLine);
}
我认为我可以通过将接收到的字符串与原始加密字符串进行比较来解决此问题,如果它们匹配,则只需解密原始字符串,但这似乎是一个程序,它只是通过额外的步骤来加密和解密字符串和我不想要那个。我希望客户端解密直接从服务器接收到的字符串。
无论如何,任何帮助都表示感谢并提前致谢。
编辑:
我替换了这个:
...
byte[] eui = encrypt(userInput);
System.out.println(eui);
System.out.println(decrypt(eui));
out.println(eui.toString());
byte[] ein = in.readLine().getBytes();
String din = decrypt(ein);
System.out.println(din);
...
用这个:
...
byte[] eui = encrypt(userInput);
String b64eui = Base64.getEncoder().encodeToString(eui);
out.println(b64eui);
byte[] ein = Base64.getDecoder().decode(in.readLine().getBytes());
String din = decrypt(ein);
System.out.println("echo: " + din);
...
【问题讨论】:
-
eui.toString()不会像您认为的那样做。它没有做任何有用的事情。此外,您正在混合面向字节和面向字符的 IO。对于初学者来说,这可能非常复杂。我认为最简单的解决方案是继续使用面向字符的 IO,但在通过套接字发送之前使用 Base64 类将您的byte[]编码为字符串。请记住在解密之前将字符串解码回byte[]。
标签: java string sockets encryption