gpt4 book ai didi

java - 解密时出现错误填充异常,但仍然有效

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

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;


public class Encryptor{

private static final int bufferSize= 128;

/**
* @param args
*/
public static void main(String[] args) {

BufferedInputStream in = null;
BufferedOutputStream out = null;
SecretKeyFactory kf = null;
KeySpec ks = null;
byte[] salt = new byte[20];
SecretKey key = null;
Cipher cipher = null;
SecretKeySpec keyspec = null;
int bytesRead = 0;
if (args.length != 4) {
printUsageMessage();
System.exit(1);
}
try {
in = new BufferedInputStream(new FileInputStream(args[1]));
} catch (FileNotFoundException e) {
printErrorMessage("Unable to open input file: " + args[1], null);
System.exit(1);
}
try {
out = new BufferedOutputStream(new FileOutputStream(args[2]));
} catch (FileNotFoundException e) {
printErrorMessage("Unable to open output file: " + args[2], e);
System.exit(1);
}
try {
kf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
} catch (NoSuchAlgorithmException e2) {
e2.printStackTrace();
}
String password = args[3];

ks = new PBEKeySpec(password.toCharArray(), salt, 128, 128);
try {
key = kf.generateSecret(ks);
} catch (InvalidKeySpecException e1) {
e1.printStackTrace();
}
byte[] aeskey = key.getEncoded();
try {

cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
} catch (NoSuchAlgorithmException e) {
printErrorMessage("No Such Algorithm Exception when creating main cipher", e);
System.exit(2);
} catch (NoSuchPaddingException e) {
printErrorMessage("No Such Padding Exception when creating main cipher", e);
System.exit(2);
}
int cipherMode = -1;
char mode = Character.toLowerCase(args[0].charAt(0));
switch (mode) {
case 'e':
cipherMode = Cipher.ENCRYPT_MODE;
break;
case 'd':
cipherMode = Cipher.DECRYPT_MODE;
break;
default:
printUsageMessage();
System.exit(1);
}
keyspec = new SecretKeySpec(aeskey, "AES");
try {
cipher.init(cipherMode, keyspec);
} catch (InvalidKeyException e) {
printErrorMessage("Invalid Key Spec", e);
System.exit(2);
}
byte[] inputBuffer = new byte[bufferSize];
byte[] outputBuffer = null;
try {
bytesRead = in.read(inputBuffer);
} catch (IOException e) {
printErrorMessage("Error reading input file " + args[1], e);
System.exit(1);
}
while (bytesRead > 0) {
outputBuffer = cipher.update(inputBuffer);
try {
out.write(outputBuffer);
} catch (IOException e) {
printErrorMessage("Error writing to output file " + args[2], e);
System.exit(1);
}
try {
bytesRead = in.read(inputBuffer);
} catch (IOException e) {
printErrorMessage("Error reading input file " + args[1], e);
System.exit(1);
}
}
try {
outputBuffer = cipher.doFinal(inputBuffer);
} catch (IllegalBlockSizeException | BadPaddingException e1) {
e1.printStackTrace();
}
try {
out.write(outputBuffer);
} catch (IOException e) {
printErrorMessage("Error on final write to output file " + args[2], e);
System.exit(1);
}
try {
in.close();
out.close();
} catch (IOException e) {
printErrorMessage("Error closing file", e);
}
}


private static void printErrorMessage(String errMsg, Exception e) {
System.err.println(errMsg);
if (e != null)
System.err.println(e.getMessage());
}


private static void printUsageMessage() {
System.out.println(progName + " $Revision: 1.1 $: Usage: " + progName + " E/D infile outfile passphrase");
}

}

我正在尝试编写一个使用密码加密和解密文本文档的程序。它不会在加密时抛出任何错误,但在解密时会抛出错误的填充异常,但它仍然输出正确的文本,但最后有额外的内容。我搜索了其他答案但找不到解决方案。该程序的运行方式是编译成可运行的 jar 并像 java -jar filename e/d(加密/解密)inputFile.txt outputFile.txt 密码一样运行它。

提前致谢

编辑:

Exception:
javax.crypto.BadPaddingException: Given final block not properly padded. Such issues can arise if a bad key is used during decryption.
at java.base/com.sun.crypto.provider.CipherCore.unpad(Unknown Source)
at java.base/com.sun.crypto.provider.CipherCore.fillOutputBuffer(Unknown Source)
at java.base/com.sun.crypto.provider.CipherCore.doFinal(Unknown Source)
at java.base/com.sun.crypto.provider.AESCipher.engineDoFinal(Unknown Source)
at java.base/javax.crypto.Cipher.doFinal(Unknown Source)
at FileEncryptorSkeleton.main(FileEncryptorSkeleton.java:183)

这是我添加outputBuffer = cipher.doFinal(inputBuffer);的地方

示例输入:

aaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazz
aaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazz
aaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazz
aaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazz
aaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazz
aaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazz
aaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazz
aaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazz
aaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazz
aaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazz

示例输出:

aaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazz
aaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazz
aaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazz
aaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazz
aaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazz
aaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazz
aaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazz
aaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazz
aaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazz
aaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazz
aaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazz
aaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazz
aaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazz
aaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzz

output picture as invalid characters didnt show up in cod block

最佳答案

您多次调用bytesRead = in.read(inputBuffer)然后cipher.update(inputBuffer) 。当到达输入文件末尾时,仅显示 inputBuffer 的一部分设置为新数据,其余部分是先前读取的剩余内容,但您会使用所有这些数据。然后你调用cipher.doFinal(inputBuffer)它使用上次读取后缓冲区中剩余内容的另一个副本。

在加密时,这会导致对最后几行(最多 128 字节)中的某些数据的重复进行加密。解密时,这会导致调用 doFinal数据实际上不是密文的最后部分,因此出现“错误填充”异常。

而是这样做(为了清楚起见,进行模数错误处理):

bytesRead = in.read(inputBuffer);
while( bytesRead > 0 ){
outputBuffer = cipher.update(inputBuffer, 0, readBytes); // only use the part read
out.write(outputBuffer);
bytesRead = in.read(inputBuffer);
}
outputBuffer = cipher.doFinal(); // no data at all here, .update already processed it
out.write(outputBuffer);

PS:应用于一般数据(如“文本文档”)的 ECB 几乎总是不安全的;谷歌欧洲央行企鹅。并且只有 128 次迭代的 PBKDF2 不是很好,并且具有恒定的盐则非常糟糕。但这些都是安全问题,而且是题外话。

关于java - 解密时出现错误填充异常,但仍然有效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60426169/

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