我試圖使用Java中的密碼將一個文件的內容加密到另一個文件中。該文件正在讀取到一個字節數組,加密到另一個字節數組,然後寫入新文件。不幸的是,當我嘗試反轉加密時,輸出文件被解密爲垃圾。在Java文件中使用基於密碼的加密
我強烈懷疑這個問題與每次使用相同密碼短語時生成相同的密鑰有關。我編寫了一個測試方法,可以在生成密鑰時將密鑰轉儲到文件中。密鑰直接記錄並以編碼形式記錄。前者每次都是一樣的,但後者由於某種原因總是不同的。
誠實地說,我不太瞭解加密方法,特別是在Java中。我只需要這些數據是適度安全的,並且加密不需要承受任何有大量時間和技能的人的攻擊。在此先感謝任何有此建議的人。
編輯:Esailija非常友善地指出我總是使用ENCRYPT_MODE設置密碼。我糾正使用布爾參數的問題,但現在我得到以下異常:
javax.crypto.IllegalBlockSizeException:帶襯墊的密碼
這聽起來好像解密時輸入長度必須是多8該密碼未被正確使用。我的印象是「PBEWithMD5AndDES」會將它散列成一個16字節的代碼,這當然是8的倍數。我想知道爲什麼密鑰會生成並在加密模式下使用得很好,但是當它嘗試時在完全相同的條件下解密。
import java.various.stuff;
/**Utility class to encrypt and decrypt files**/
public class FileEncryptor {
//Arbitrarily selected 8-byte salt sequence:
private static final byte[] salt = {
(byte) 0x43, (byte) 0x76, (byte) 0x95, (byte) 0xc7,
(byte) 0x5b, (byte) 0xd7, (byte) 0x45, (byte) 0x17
};
private static Cipher makeCipher(String pass, Boolean decryptMode) throws GeneralSecurityException{
//Use a KeyFactory to derive the corresponding key from the passphrase:
PBEKeySpec keySpec = new PBEKeySpec(pass.toCharArray());
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
SecretKey key = keyFactory.generateSecret(keySpec);
//Create parameters from the salt and an arbitrary number of iterations:
PBEParameterSpec pbeParamSpec = new PBEParameterSpec(salt, 42);
/*Dump the key to a file for testing: */
FileEncryptor.keyToFile(key);
//Set up the cipher:
Cipher cipher = Cipher.getInstance("PBEWithMD5AndDES");
//Set the cipher mode to decryption or encryption:
if(decryptMode){
cipher.init(Cipher.ENCRYPT_MODE, key, pbeParamSpec);
} else {
cipher.init(Cipher.DECRYPT_MODE, key, pbeParamSpec);
}
return cipher;
}
/**Encrypts one file to a second file using a key derived from a passphrase:**/
public static void encryptFile(String fileName, String pass)
throws IOException, GeneralSecurityException{
byte[] decData;
byte[] encData;
File inFile = new File(fileName);
//Generate the cipher using pass:
Cipher cipher = FileEncryptor.makeCipher(pass, false);
//Read in the file:
FileInputStream inStream = new FileInputStream(inFile);
decData = new byte[(int)inFile.length()];
inStream.read(decData);
inStream.close();
//Encrypt the file data:
encData = cipher.doFinal(decData);
//Write the encrypted data to a new file:
FileOutputStream outStream = new FileOutputStream(new File(fileName + ".encrypted"));
outStream.write(encData);
outStream.close();
}
/**Decrypts one file to a second file using a key derived from a passphrase:**/
public static void decryptFile(String fileName, String pass)
throws GeneralSecurityException, IOException{
byte[] encData;
byte[] decData;
File inFile = new File(fileName);
//Generate the cipher using pass:
Cipher cipher = FileEncryptor.makeCipher(pass, true);
//Read in the file:
FileInputStream inStream = new FileInputStream(inFile);
encData = new byte[(int)inFile.length()];
inStream.read(encData);
inStream.close();
//Decrypt the file data:
decData = cipher.doFinal(encData);
//Write the decrypted data to a new file:
FileOutputStream target = new FileOutputStream(new File(fileName + ".decrypted.txt"));
target.write(decData);
target.close();
}
/**Record the key to a text file for testing:**/
private static void keyToFile(SecretKey key){
try {
File keyFile = new File("C:\\keyfile.txt");
FileWriter keyStream = new FileWriter(keyFile);
String encodedKey = "\n" + "Encoded version of key: " + key.getEncoded().toString();
keyStream.write(key.toString());
keyStream.write(encodedKey);
keyStream.close();
} catch (IOException e) {
System.err.println("Failure writing key to file");
e.printStackTrace();
}
}
}
我以某種方式設法忽略了這一點。感謝您指出。我最初在encryptFile/decryptFile方法內部創建了密鑰和密碼,然後將它們合併到makeCipher中。我在原始問題的代碼中解決了問題,但是我仍然遇到了編輯中提到的問題。 – user1870901
@ user1870901請參閱編輯我的答案 – Esailija
我非常肯定,這讓我更好地理解加密過程應該如何在Java中工作。我的印象是填充與密鑰本身而不是數據有關。就像你說的,我不認爲向數據添加/刪除額外的字節將不得不手動完成。我認爲這個問題涉及到加密過程中比實際更復雜的部分。我對整件事情感到沮喪,我非常感謝幫助。 – user1870901