【发布时间】:2020-12-22 07:11:53
【问题描述】:
我正在尝试制定使用“PBEWithHmacSHA256AndAES_256”标准加密和解密文件的正确流程。
根据我从 Oracle 看到的 example code 的理解。
我已经收集到需要盐,以及迭代计数和哈希标准。
所以我有我的主要方法,传入加密方法:
- 用户定义的密码
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");
}
那我也有我的main方法,传入解密方法:
-
一个用户定义的密码
String inputKEY作为一个字符串(也使用此方法进行其他解密运行) -
inputIV的字符串已作为 null 传入,因为不用于 PBE。 -
密文文件
inputFile作为字符串 -
要创建的以字符串形式显示纯文本文件
outputFile的名称private static void decrypt(String inputKEY, String inputIV, String inputFile, String outputFile) { 密码密码 = 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 的理解有问题,因此我实施它的方式可能是错误的。谁能指出似乎有什么问题?
【问题讨论】:
-
您是否收到错误或解密文件与原始文件不相等?顺便说一句:今天的迭代值应该 > 10.000。
-
它捕获了解密方法底部的try-catch方法,但仍然完成。是的,解密文件不等于原始文件。我认为解密文件的文件大小也可能比纯文本小。
-
将完整的错误堆栈跟踪添加到您的问题中可能是个好主意。
标签: java encryption salt jce