gpt4 book ai didi

使用 BouncyCaSTLe SSL 使用 keyFile 进行 Java AES 加密

转载 作者:行者123 更新时间:2023-12-05 04:27:19 26 4
gpt4 key购买 nike

我正在尝试将 SSL 中的以下命令转换为 Java

openssl enc -in <inputfilename> -out <file_to_encrypt> -e -aes256 -k s_key

s_key 是提供的文件,其中包含将用于加密和解密的 key

需要完成的步骤:1 - 读取 key 文件2 - 用它来AES加密来加密文件inputfilename3 - 使用 key 对其进行解密。

我是加密新手,下面是我到目前为止编写的用于加密的代码,但我遇到了问题。

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 语句:

  • 必须生成随机的 8 字节盐
  • 必须使用 EVP_BytesToKey() 导出 32 字节的 key 和 16 字节的 IV和盐
  • 结果必须以OpenSSL格式给出:
    <ASCII Encoding of Salted__>|<salt>|<ciphertext>

对于 EVP_BytesToKey()你可以申请OpenSSLPBEParametersGenerator您已经建议的类(class)。

EVP_BytesToKey()使用摘要。在早期版本的 OpenSSL 中,默认情况下应用 MD5,从 v1.1.0 SHA256 开始。可以使用 -md5 选项设置摘要。代码和 OpenSSL 语句必须都使用相同的摘要才能兼容。 OpenSSLPBEParametersGenerator允许在构造函数中指定摘要,默认为 MD5。

以下代码基于您的代码,即使用 OpenSSLPBEParametersGenerator对于 EVP_BytesToKey()但另外考虑以上几点。不是加密整个数据,而是应用流,数据逐 block 加密,这样即使是大文件也可以处理:

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 对,因此没有重用,这也消除了评论中提到的漏洞。

关于使用 BouncyCaSTLe SSL 使用 keyFile 进行 Java AES 加密,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72856975/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com