您的代码使用随机盐来获取密码,但盐永远不会存储,因此当以后解密(在第二次运行中)时,您不再有盐。
第二 - 用于 AES 加密的初始化向量存在类似问题。您没有在加密方面定义一个,所以 Java 是(内部)
生成一个并进行加密。现在您必须从密码中获取此 iv 并将其保存以供以后解密。由于您不提供您运行的 iv
进入异常“缺少参数类型:IV 预期”。
由于我懒得检查您在代码下方找到的代码(由 @Topaco 提供,所有功劳归他所有!链接:https://stackoverflow.com/a/63719246/8166854)
完整的文件加密/解密,甚至适用于较大的文件,因为它使用缓冲的 CipherInput-/OutputStreams。
安全警告:代码没有异常处理,仅用于教育目的!。
代码:
import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.security.SecureRandom;
public class MainFileEncryption {
public static void main(String[] args) throws Exception {
System.out.println("File encryption with PBEWithHmacSHA256AndAES_256");
String uncryptedFilename = "plaintext.txt";
String encryptedFilename = "plaintext.enc";
String decryptedFilename = "decrypted.txt";
String password = "mySecretPassword";
byte[] iv = new byte[16];
SecureRandom secureRandom = new SecureRandom();
secureRandom.nextBytes(iv);
encrypt(password, iv, uncryptedFilename, encryptedFilename);
decrypt(password, encryptedFilename, decryptedFilename);
}
// by Topaco https://stackoverflow.com/a/63719246/8166854
private static void encrypt(String key, byte[] initVector, String inputFile, String outputFile) throws Exception {
// Key
PBEKeySpec pbeKeySpec = new PBEKeySpec(key.toCharArray());
SecretKeyFactory keyFac = SecretKeyFactory.getInstance("PBEWithHmacSHA256AndAES_256");
SecretKey pbeKey = keyFac.generateSecret(pbeKeySpec);
// IV
IvParameterSpec iv = new IvParameterSpec(initVector);
// Salt
SecureRandom rand = new SecureRandom();
byte[] salt = new byte[16];
rand.nextBytes(salt);
// ParameterSpec
int count = 10000;
PBEParameterSpec pbeParamSpec = new PBEParameterSpec(salt, count, iv);
// Cipher
Cipher cipher = Cipher.getInstance("PBEWithHmacSHA256AndAES_256");
cipher.init(Cipher.ENCRYPT_MODE, pbeKey, pbeParamSpec);
try (FileInputStream fin = new FileInputStream(inputFile);
FileOutputStream fout = new FileOutputStream(outputFile);
CipherOutputStream cipherOut = new CipherOutputStream(fout, cipher)) {
// Write IV, Salt
fout.write(initVector);
fout.write(salt);
// Encrypt
final byte[] bytes = new byte[1024];
for (int length = fin.read(bytes); length != -1; length = fin.read(bytes)) {
cipherOut.write(bytes, 0, length);
}
}
}
private static void decrypt(String key, String inputFile, String outputFile) throws Exception {
try (FileInputStream encryptedData = new FileInputStream(inputFile);
FileOutputStream decryptedOut = new FileOutputStream(outputFile)) {
// Key
PBEKeySpec pbeKeySpec = new PBEKeySpec(key.toCharArray());
SecretKeyFactory keyFac = SecretKeyFactory.getInstance("PBEWithHmacSHA256AndAES_256");
SecretKey pbeKey = keyFac.generateSecret(pbeKeySpec);
// Read IV
byte[] initVect = new byte[16];
encryptedData.read(initVect);
IvParameterSpec iv = new IvParameterSpec(initVect);
// Read salt
byte[] salt = new byte[16];
encryptedData.read(salt);
// ParameterSpec
int count = 10000;
PBEParameterSpec pbeParamSpec = new PBEParameterSpec(salt, count, iv);
// Cipher
Cipher cipher = Cipher.getInstance("PBEWithHmacSHA256AndAES_256");
cipher.init(Cipher.DECRYPT_MODE, pbeKey, pbeParamSpec);
try (CipherInputStream decryptStream = new CipherInputStream(encryptedData, cipher)) {
// Decrypt
final byte[] bytes = new byte[1024];
for (int length = decryptStream.read(bytes); length != -1; length = decryptStream.read(bytes)) {
decryptedOut.write(bytes, 0, length);
}
}
}
}
}