Я пытаюсь разработать правильный процесс шифрования и дешифрования файла с использованием стандарта PBEWithHmacSHA256AndAES_256.
Насколько я понимаю, глядя на этот пример кода от Oracle.
Я понял, что нужна соль, а также количество итераций и стандарт хеширования.
Итак, у меня есть основной метод, переходящий в метод шифрования:
- определяемый пользователем пароль
new String(key).toCharArray()
в виде массива байтов (с использованием этого метода для других запусков шифрования) - безопасный случайный IV
initVector
в виде байтового массива - простой текстовый файл
inputFile
в виде строки - имя создаваемого файла зашифрованного текста
outputFile
в виде строки
Я следовал примеру кода, чтобы закодировать то, что я считаю правильным для метода шифрования. И я сохраняю соль и IV, которые будут использоваться для дешифрования, добавляя их к зашифрованному тексту.
private static void encrypt(byte[] key, byte[] initVector, String inputFile, String outputFile) //exceptions for throws... {
//Initalisation for encryption
Cipher cipher;
byte[] salt = new byte[16];
SecureRandom rand = new SecureRandom();
// Salt randomly generated with base64
rand.nextBytes(salt);
System.out.println("my salt should be" + Base64.getEncoder().encodeToString(salt));
salt = Base64.getEncoder().encode(salt);
// Iteration count
int count = 1000;
IvParameterSpec iv = new IvParameterSpec(initVector);
// Create PBE parameter set
PBEParameterSpec pbeParamSpec = new PBEParameterSpec(Base64.getDecoder().decode(salt), count, iv);
// Convert pass into SecretKey object
PBEKeySpec pbeKeySpec = new PBEKeySpec(new String(key).toCharArray());
SecretKeyFactory keyFac = SecretKeyFactory.getInstance("PBEWithHmacSHA256AndAES_256");
SecretKey pbeKey;
try {
pbeKey = keyFac.generateSecret(pbeKeySpec);
} catch (InvalidKeySpecException e) {
System.out.println("Sorry, the password specified cannot be used as a secret key");
System.out.println("Please check that your password uses valid characters");
return;
}
// Create PBE Cipher
cipher = Cipher.getInstance("PBEWithHmacSHA256AndAES_256");
// Initialize PBE Cipher with key and parameters
cipher.init(Cipher.ENCRYPT_MODE, pbeKey, pbeParamSpec);
}
//File error checking and file handling (i.e. generating file paths)...
System.out.println("Secret key is " + Base64.getEncoder().encodeToString(key));
System.out.println("IV is " + Base64.getEncoder().encodeToString(initVector));
//Special file reading and writing with 'Cipher Stream'
try (InputStream fin = FileEncryptor.class.getResourceAsStream(loadFile.getName());
OutputStream fout = Files.newOutputStream(saveFile);
CipherOutputStream cipherOut = new CipherOutputStream(fout, cipher) {
}) {
final byte[] bytes = new byte[1024];
for(int length=fin.read(bytes); length!=-1; length = fin.read(bytes)){
fout.write(initVector);
fout.write(salt);
cipherOut.write(bytes, 0, length);
}
} catch (IOException e) {
System.out.println("Something went wrong with reading and writing these files!");
System.out.println("Please check you have the latest version of this program");
System.out.println("Contact your IT admin to make sure you have sufficient privileges");
}
System.out.println("SUCCESS! Encryption finished, saved at specified location");
}
Затем у меня также есть мой основной метод, переходящий в метод дешифрования:
определяемый пользователем пароль
String inputKEY
в виде строки (также используется этот метод для других запусков дешифрования)Строка для
inputIV
была передана как null, поскольку не используется для PBE.файл зашифрованного текста
inputFile
в виде строкиимя создаваемого файла открытого текста
outputFile
в виде строкичастный статический void дешифровать (String inputKEY, String inputIV, String inputFile, String outputFile) {Cipher cipher = null;
//File error checking and file handling (i.e. generating file paths)... InputStream encryptedData = Files.newInputStream(loadFilePath); PBEKeySpec pbeKeySpec = new PBEKeySpec(inputKEY.toCharArray()); SecretKeyFactory keyFac = SecretKeyFactory.getInstance("PBEWithHmacSHA256AndAES_256"); SecretKey pbeKey = null; try { pbeKey = keyFac.generateSecret(pbeKeySpec); } catch (InvalidKeySpecException e) { // TODO Auto-generated catch block e.printStackTrace(); } byte[] initVect = new byte[16]; encryptedData.read(initVect); IvParameterSpec iv = new IvParameterSpec(Base64.getDecoder().decode(initVect); byte[] salt = new byte[16]; encryptedData.read(salt); PBEParameterSpec pbeParamSpec = new PBEParameterSpec(Base64.getDecoder().decode(salt), 1000, iv); cipher = Cipher.getInstance("PBEWithHmacSHA256AndAES_256"); System.out.println("my salt should be" + Base64.getEncoder().encodeToString(Base64.getDecoder().decode(salt))); cipher.init(Cipher.DECRYPT_MODE, pbeKey, pbeParamSpec); try (CipherInputStream decryptStream = new CipherInputStream(encryptedData, cipher); OutputStream decryptedOut = Files.newOutputStream(saveFile)){ final byte[] bytes = new byte[1024]; for(int length=decryptStream.read(bytes); length!=-1; length = decryptStream.read(bytes)){ decryptedOut.write(bytes, 0, length); } } catch (IOException e) { //This is caught when decryption is run System.out.println("Something went wrong with reading and writing these files!"); System.out.println("Please check you have the latest version of this program"); System.out.println("Contact your IT admin to make sure you have sufficient privileges"); } System.out.println("SUCESS! Decryption finished, saved at specified location");
}
Я считаю, что что-то не так с моим пониманием PBE, и поэтому способ, которым я это реализовал, вероятно, неправильный. Может ли кто-нибудь указать на то, что кажется неправильным?