我是 Java 加密技术的新手,不知道为什么在尝试解密已成功加密的文件(使用相同的密钥和 IV)时不断收到 BadPaddingException。我将 16 字节 IV 添加到密文文件的开头,然后尝试在解密过程中读取它。这和秘密密钥的初始化似乎有效,所以我不确定我哪里出了问题。
我使用
javac -g FileEncryptor.java Util.java
进行编译,使用 java FileEncryptor enc 90F6seEyxAK9cxblqsKJGQ== input.txt ciphertext.enc
和 java FileEncryptor dec 90F6seEyxAK9cxblqsKJGQ== ciphertext.enc decrypted.txt
分别进行加密和解密。
感谢帮助:)
我已经检查了 IV 和密钥是否为 16 字节,以及 IV 是否正确地前置(在加密期间)和读取(在解密期间)。在调试过程中,一旦到达包含
decryptStream.read(bytes)
的 for 循环,我总是会得到异常。
注意:并非所有代码都是我的。我用它作为学习练习。
public class FileEncryptor {
private static final Logger LOG = Logger.getLogger(FileEncryptor.class.getSimpleName());
private static final String ALGORITHM = "AES";
private static final String CIPHER = "AES/CBC/PKCS5PADDING";
public static void main(String[] args) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
InvalidAlgorithmParameterException, IOException, Exception {
SecureRandom sr = new SecureRandom();
byte[] key = new byte[16];
sr.nextBytes(key); // 128 bit key
byte[] initVector = new byte[16];
sr.nextBytes(initVector);
String mode = args[0];
String hexSkey;
IvParameterSpec iv = new IvParameterSpec(initVector);
SecretKeySpec skeySpec = new SecretKeySpec(key, ALGORITHM);
Cipher cipher = Cipher.getInstance(CIPHER);
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
final Path currentPath = Paths.get("");
if (mode.equals("enc")) {
System.out.println("initVector=" + Util.bytesToHex(initVector));
skeySpec = new SecretKeySpec(Base64.getDecoder().decode(args[1]), ALGORITHM);
final Path encryptedPath = currentPath.resolve(args[3]);// idk if this is necessary imo,
// args[1] becomes base64 encoded skey
// args[2] = input.txt
// args[3] = output encrypted file
try (InputStream fin = FileEncryptor.class.getResourceAsStream(args[2]);
OutputStream fout = Files.newOutputStream(encryptedPath);
CipherOutputStream cipherOut = new CipherOutputStream(fout, cipher) {
}) {
final byte[] bytes = new byte[1024];
fout.write(initVector);// write the IV to the first 16 bytes of the encrypted file
for (int length = fin.read(bytes); length != -1; length = fin.read(bytes)) {
cipherOut.write(bytes, 0, length);
}
cipherOut.close();
} catch (IOException e) {
LOG.log(Level.INFO, "Unable to encrypt", e);
}
return;
} else if (mode.equals("dec")) {
String encodedFile = args[2], decodedFile = args[3];
skeySpec = new SecretKeySpec(Base64.getDecoder().decode(args[1]), ALGORITHM);
final Path decryptedPath = currentPath.resolve(decodedFile);
try (InputStream encryptedData = Files.newInputStream(Path.of(encodedFile));
OutputStream decryptedOut = Files.newOutputStream(decryptedPath)) {
byte[] storedIV = new byte[16];
int first16bytes = encryptedData.read(storedIV);
if (first16bytes != storedIV.length) {
// FIXME: edit error here
}
cipher.init(Cipher.DECRYPT_MODE, skeySpec, new IvParameterSpec(storedIV));
System.out.println("key check " + storedIV.length);
final byte[] bytes = new byte[1024];
CipherInputStream decryptStream = new CipherInputStream(encryptedData, cipher);
for (int length = decryptStream.read(bytes); length != -1; length =
decryptStream.read(bytes)) {
System.out.println("reached");
decryptedOut.write(bytes, 0, length);
}
decryptStream.close();
} catch (IOException ex) {
Logger.getLogger(FileEncryptor.class.getName()).log(Level.SEVERE, "Unable to decrypt", ex);
}
LOG.info("Decryption complete, open " + decryptedPath);
return;// delete later
}
}
}
您正在生成一个随机密钥并在密码中使用它,而不是使用提供的密钥。这将产生一个错误的填充异常。