英文:
Java - Input byte has incorrect ending byte at 300
问题
我已经编写了一个基于JAVA的实用程序,用于将数据加密(AES)存储在Excel中,并将其上传到FTP服务器,同时也编写了相反的机制来下载并将其解密回纯文本。
目前,加密方面的功能正常运行,但是在解密时出现以下异常:
解密时出错:java.lang.IllegalArgumentException: 输入字节数组在第300字节处具有不正确的结束字节
我尝试过更改编码方案,但没有起作用。
我的代码
public void downloadFileFromFTP () {
// ...(前面的代码部分已省略)
byte[] buffer = new byte[1024];
BufferedInputStream bis = new BufferedInputStream(channelSftp.get("test.csv"));
File newFile = new File("D:\\FMS_Encryption\\dec2.csv");
OutputStream os = new FileOutputStream(newFile);
BufferedOutputStream bos = new BufferedOutputStream(os);
int readCount;
while ((readCount = bis.read(buffer)) > 0) {
String encryptedRow = new String(buffer, StandardCharsets.UTF_8);
String decryptedRow = decrypt(encryptedRow.trim(), "FMS");
bos.write(decryptedRow.getBytes(), 0, readCount);
}
bis.close();
bos.close();
}
加密/解密代码
public static String encrypt(String strToEncrypt, String secret) {
// ...(加密部分的代码已省略)
}
public static String decrypt(String strToDecrypt, String secret) {
// ...(解密部分的代码已省略)
}
在下载功能中,当我将行String decryptedRow = decrypt( encryptedRow, "FMS" );
更改为String decryptedRow = decrypt( encryptedRow.trim(), "FMS" );
时,会抛出以下错误:
java.lang.ArrayIndexOutOfBoundsException
at java.lang.System.arraycopy(Native Method)
at java.io.BufferedOutputStream.write(Unknown Source)
at IbftFileEncryption.downloadFileFromFTP(IbftFileEncryption.java:426)
at IbftFileEncryption.main(IbftFileEncryption.java:521)
英文:
I have written a JAVA based utility to store my data in excel encrypted (AES) and upload it to FTP Server and reverse mechanism for the same to download it and decrypt back to plain text.
Now, the encryption side is working perfectly, but when I decrypt the same. It throws the below exception:
Error while decrypting: java.lang.IllegalArgumentException: Input byte array has incorrect ending byte at 300
I have tried to change the encoding scheme but nothing worked.
My Code
public void downloadFileFromFTP () {
int SFTPPORT = 22;
String SFTPHOST = "";
String SFTPUSER = "";
String SFTPPASS = "";
String SFTPWORKINGDIR = "";
Session session = null;
Channel channel = null;
ChannelSftp channelSftp = null;
try {
JSch jsch = new JSch();
session = jsch.getSession(SFTPUSER, SFTPHOST, SFTPPORT);
session.setPassword(SFTPPASS);
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.connect();
channel = session.openChannel("sftp");
channel.connect();
channelSftp = (ChannelSftp) channel;
channelSftp.cd(SFTPWORKINGDIR);
byte[] buffer = new byte[1024];
BufferedInputStream bis = new BufferedInputStream(channelSftp.get("test.csv"));
File newFile = new File("D:\\FMS_Encryption\\dec2.csv");
OutputStream os = new FileOutputStream(newFile);
BufferedOutputStream bos = new BufferedOutputStream(os);
int readCount;
while ((readCount = bis.read(buffer)) > 0) {
String encryptedRow = new String(buffer, StandardCharsets.UTF_8);
String decryptedRow = decrypt( encryptedRow.trim(), "FMS" );
bos.write(decryptedRow.getBytes(), 0, readCount);
}
bis.close();
bos.close();
}
catch (Exception ex) {
ex.printStackTrace();
}
}
ENCRYPTION/DECRYPTION CODE
public static String encrypt(String strToEncrypt, String secret)
{
try
{
setKey(secret);
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
return Base64.getEncoder().encodeToString(cipher.doFinal(strToEncrypt.getBytes("UTF-8")));
}
catch (Exception e)
{
System.out.println("Error while encrypting: " + e.toString());
}
return null;
}
public static String decrypt(String strToDecrypt, String secret)
{
try
{
setKey(secret);
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secretKey);
return new String(cipher.doFinal(Base64.getDecoder().decode(strToDecrypt)));
}
catch (Exception e)
{
System.out.println("Error while decrypting: " + e.toString());
}
return null;
}
Now in download function, when I change the line String decryptedRow = decrypt( encryptedRow, "FMS" );
to String decryptedRow = decrypt( encryptedRow.trim(), "FMS" );
it throws:
java.lang.ArrayIndexOutOfBoundsException
at java.lang.System.arraycopy(Native Method)
at java.io.BufferedOutputStream.write(Unknown Source)
at IbftFileEncryption.downloadFileFromFTP(IbftFileEncryption.java:426)
at IbftFileEncryption.main(IbftFileEncryption.java:521)
答案1
得分: 0
你正在尝试以小块处理加密数据,但是你的加密/解密方法期望一个完整的加密块。
你正在使用PKCS5Padding
填充与AES密码器一起使用,因此在加密期间的最终doFinal(...)
调用时,会将加密数据填充以与AES的块大小对齐。在解密期间的最终doFinal(...)
调用时,会删除此填充。如果尝试解密不存在此填充的数据,解密将失败。
在你的代码中,你过多地调用了doFinal(...)
...
同样地,你也在不知道是否有完整块的情况下对块进行了base64解码。
如果在解密之前将整个文件下载到一个字符串中,可能会起作用。
英文:
You are trying to process your encrypted data in small chunks, but your encryption/decryption methods are expecting one complete encrypted block.
You are using PKCS5Padding
padding with your AES cipher, so your encrypted data is padded to align with the block size of AES when the final call to doFinal(...)
occurs during encrypt. This padding is then removed when the final call to doFinal(...)
is called during decrypt. If you try to decrypt data where this padding don't exist, the decrypt will fail.
In your code you and up calling doFinal(...)
too many times ..
In the same way you are also using base64 decoding on chunks without knowing if you have a complete block.
If you download the full file into a String before decrypting it might work.
专注分享java语言的经验与见解,让所有开发者获益!
评论