【问题标题】:Can't fix "Error: Input length must be a multiple of 16 when decrypting with a pad cipher"无法修复“错误:使用填充密码解密时输入长度必须是 16 的倍数”
【发布时间】:2013-08-20 04:20:05
【问题描述】:

你好!我正在开发一个聊天应用程序,它通过 AES/CBC/PKCS5 填充对其数据进行加密。它通过客户端将加密消息发送到服务器,然后将其发回并解密。不幸的是,每当我解密消息时,我都会收到如下错误:javax.crypto.IllegalBlockSizeException:使用填充密码解密时,输入长度必须是 16 的倍数。加密基于这个程序:(http://www.scottjjohnson.com/blog/AesWithCbcExample.java),它工作得很好,我看不出我的代码和那个代码之间的区别,除了我必须从字符串转换为字节数组。这是我的代码:

客户端(加密):

String message = textField.getText();
// generate a key
KeyGenerator keygen = KeyGenerator.getInstance("AES");
keygen.init(128);  // To use 256 bit keys, you need the "unlimited strength" encryption policy files from Sun.
byte[] key = keygen.generateKey().getEncoded();
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");

// build the initialization vector.  This example is all zeros, but it 
// could be any value or generated using a random number generator.
byte[] iv = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
IvParameterSpec ivspec = new IvParameterSpec(iv);

// initialize the cipher for encrypt mode
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, ivspec);

// encrypt the message
byte[] encrypted = cipher.doFinal(message.getBytes());
System.out.println("Ciphertext: " + encrypted + "\n");
System.out.println(encrypted);
out.println(encrypted);
textField.setText(""); 

服务器端:

String input = in.readLine();
writer.println("MESSAGE " + input);

客户端(解密):

//DECRYPTION
System.out.println(line);
line = line.substring(8);
System.out.println(line);

// generate a key
KeyGenerator keygen = KeyGenerator.getInstance("AES");
keygen.init(128);  // To use 256 bit keys, you need the "unlimited strength" encryption policy files from Sun.
byte[] key = keygen.generateKey().getEncoded();
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");

// build the initialization vector.  This example is all zeros, but it 
// could be any value or generated using a random number generator.
byte[] iv = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
IvParameterSpec ivspec = new IvParameterSpec(iv);

// reinitialize the cipher for decryption
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, skeySpec, ivspec);

// decrypt the message
byte[] decrypted = cipher.doFinal(line.getBytes());
System.out.println("Plaintext: " + new String(decrypted) + "\n");
messageArea.append(name + ": " + decrypted + "\n");
messageArea.setCaretPosition(messageArea.getDocument().getLength());

【问题讨论】:

  • 类似的问题还有很多,请稍微搜索一下。
  • 哈哈过去一周我一直在研究所有这些问题。我的问题不是错误本身,而是即使我的输入是 16 的倍数,我如何继续接收它。

标签: java encryption aes jce


【解决方案1】:

您的问题与密码学无关。您未能在客户端和服务器之间正确传输数据。

我相当确定out.println(encrypted) 不是您想要做的事情,尽管我并不完全清楚,因为我不知道out 的类型。你也不应该在你的解密代码中调用line.getBytes()

您应该将密文转换为无损字符串形式,例如十六进制或 base64。所以,试试:

out.println(DatatypeConverter.printHexBinary(encrypted));

byte[] decrypted = cipher.doFinal(DatatypeConverter.parseHexBinary(line));

【讨论】:

  • 嗯,它不再给出旧错误,但现在我收到了这个新错误:javax.crypto.BadPaddingException: Given final block not proper padding.
  • 知道如何解决它吗?
猜你喜欢
  • 2012-05-16
  • 1970-01-01
  • 1970-01-01
  • 2013-06-18
  • 1970-01-01
  • 2012-06-05
  • 1970-01-01
  • 1970-01-01
  • 2019-04-14
相关资源
最近更新 更多