[英]Java AES Decryption with keyFile using BouncyCastle SSL
[英]Java AES encryption with keyFile using BouncyCastle SSL
我正在嘗試將 SSL 中的以下命令轉換為 Java
openssl enc -in <inputfilename> -out <file_to_encrypt> -e -aes256 -k s_key
s_key 是提供的文件,其中包含將用於加密和解密的密鑰
要完成的步驟: 1 - 讀取密鑰文件 2 - 使用它進行 AES 加密以加密文件 inputfilename 3 - 使用密鑰解密相同。
我是加密新手,下面是我迄今為止編寫的加密代碼,但我遇到了問題。
Path path = Paths.get("/home/debashishd/Downloads/s_key");
String content = new String(Files.readAllBytes(Paths.get("/home/debashishd/Downloads/s_key")));
String Test_message = "Hello this is Roxane";
byte[] keyValue = Files.readAllBytes(path);
ByteArrayInputStream byteIS = new ByteArrayInputStream(keyValue);
OpenSSLPBEParametersGenerator gen = new OpenSSLPBEParametersGenerator();
OpenSSLPBEParametersGenerator gen1 = gen;
byte[] saltBytes = Hex.decode(salt.getBytes());
gen1.init(keyValue);
CipherParameters cp = gen1.generateDerivedParameters(256);
byte[] keyBytes = ((KeyParameter)cp);
SecretKeySpec secretKey = new SecretKeySpec(keyBytes,"AES");
System.out.println(secretKey);
Cipher cipher;
Cipher decryptCipher;
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secretKey,new IvParameterSpec(new byte[16]));
String encrypt_value = getEncoder().encodeToString(cipher.doFinal(Test_message.getBytes(StandardCharsets.UTF_8)));
System.out.println("Encrypted value: " + encrypt_value);
decryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
decryptCipher.init(Cipher.DECRYPT_MODE, secretKey,new IvParameterSpec(new byte[16]));
String Decrypt_result = new String(decryptCipher.doFinal(getDecoder().decode(encrypt_value)));
System.out.println("Decrypted value: " + Decrypt_result);
是否需要進行任何更改才能實現上述加密和解密
預期輸出:
Encrypted value: jvggHDPa58+/zQ+HyGUEk/ypndXbatE+b+hBBqiinABOIwxJ7FXqnDb5j813fPwwm/D6d2Y2uh+k4qD77QMqOg==
Decrypted value: Hello this is Roxane
為了與 OpenSSL 語句兼容:
EVP_BytesToKey()
和 salt 導出 32 字節密鑰和 16 字節 IV<ASCII Encoding of Salted__>|<salt>|<ciphertext>
對於EVP_BytesToKey()
您可以應用您已經建議的OpenSSLPBEParametersGenerator
類。
EVP_BytesToKey()
使用摘要。 從 v1.1.0 SHA256 開始,在早期版本的 OpenSSL 中默認應用 MD5。 可以使用-md5選項設置摘要。 代碼和 OpenSSL 語句必須都使用相同的摘要才能兼容。 OpenSSLPBEParametersGenerator
允許在構造函數中指定摘要,默認為 MD5。
以下代碼基於您的代碼,即對EVP_BytesToKey()
使用OpenSSLPBEParametersGenerator
但還考慮了以上幾點。 不是加密整個數據,而是應用流並且數據被逐塊加密,因此即使是大文件也可以處理:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import org.bouncycastle.crypto.digests.MD5Digest;
import org.bouncycastle.crypto.engines.AESEngine;
import org.bouncycastle.crypto.generators.OpenSSLPBEParametersGenerator;
import org.bouncycastle.crypto.io.CipherOutputStream;
import org.bouncycastle.crypto.modes.CBCBlockCipher;
import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.bouncycastle.crypto.params.ParametersWithIV;
...
String inputPath = "...";
String outputPath = "...";
String passwordStr = "...";
// Generate random 8 bytes salt
SecureRandom random = new SecureRandom();
byte salt[] = new byte[8];
random.nextBytes(salt);
// Derive 32 bytes key (AES_256) and 16 bytes IV
byte[] password = passwordStr.getBytes(StandardCharsets.UTF_8);
OpenSSLPBEParametersGenerator pbeGenerator = new OpenSSLPBEParametersGenerator(new MD5Digest()); // SHA256 as of v1.1.0 (if in OpenSSL the default digest is applied)
pbeGenerator.init(password, salt);
ParametersWithIV parameters = (ParametersWithIV) pbeGenerator.generateDerivedParameters(256, 128); // keySize, ivSize in bits
// Encrypt with AES-256, CBC using streams
try (FileOutputStream fos = new FileOutputStream(outputPath)) {
// Apply OpenSSL format
fos.write("Salted__".getBytes(StandardCharsets.UTF_8));
fos.write(salt);
// Encrypt chunkwise (for large data)
PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(new AESEngine()));
cipher.init(true, parameters);
try (FileInputStream fis = new FileInputStream(inputPath);
CipherOutputStream cos = new CipherOutputStream(fos, cipher)) {
int bytesRead = -1;
byte[] buffer = new byte[64 * 1024 * 1024]; // chunksize, e.g. 64 MiB
while ((bytesRead = fis.read(buffer)) != -1) {
cos.write(buffer, 0, bytesRead);
}
}
}
使用此代碼加密的文件可以使用 OpenSSL 解密,如下所示:
openssl enc -d -aes256 -k <passpharse> -in <enc file> -out <dec file>
因此,該代碼是您問題開頭發布的 OpenSSL 語句的編程模擬(因此仍然必須考慮關於摘要的歧義,即對於 v1.1.0 的 OpenSSL 版本,必須使用 SHA256 而不是 MD5 )。
注意因為隨機鹽,每次加密都會生成不同的key/IV對,所以沒有復用,這也去掉了評論中提到的漏洞。
我能夠用下面的代碼實現我的結果。 確實可以用更好的方式編寫代碼並刪除不必要的初始化。 我將在我的實際實施中做同樣的事情
public class test2 {
public static void main(String[] args) throws IOException, NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException {
Path path = Paths.get("/home/debashishd/Downloads/key");
String Test_message = FileUtils.readFileToString(new File("/home/debashishd/Downloads/sample.txt"), StandardCharsets.UTF_8);
/**
* Read the keyfile provided to encrypt
*/
byte[] keyValue = Files.readAllBytes(path);
OpenSSLPBEParametersGenerator gen = new OpenSSLPBEParametersGenerator();
OpenSSLPBEParametersGenerator gen1 = gen;
final String salt = "";
byte[] saltBytes = Hex.decode(salt.getBytes());
gen1.init(keyValue,saltBytes);
CipherParameters cp = gen1.generateDerivedParameters(256);
byte[] keyBytes = ((KeyParameter)cp).getKey();
SecretKeySpec secretKey = new SecretKeySpec(keyBytes,"AES");
/**
* Initialize the Encrypt Ciphers and encrypt the data from input file
*/
Cipher encryptcipher;
Cipher decryptCipher;
encryptcipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
encryptcipher.init(Cipher.ENCRYPT_MODE, secretKey,new IvParameterSpec(new byte[16]));
String encrypt_value = getEncoder().encodeToString(encryptcipher.doFinal(Test_message.getBytes(StandardCharsets.UTF_8)));
System.out.println("Encrypted value: " + encrypt_value);
/**
* Initialize the Decrypt Ciphers and decrypt the encrypted data
*/
decryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
decryptCipher.init(Cipher.DECRYPT_MODE, secretKey,new IvParameterSpec(new byte[16]));
String Decrypt_result = new String(decryptCipher.doFinal(getDecoder().decode(encrypt_value)));
System.out.println("Decrypted value: " + Decrypt_result);
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.