gpt4 book ai didi

java - AES 使用相同的 IV 进行加密和解密

转载 作者:行者123 更新时间:2023-12-01 20:19:59 28 4
gpt4 key购买 nike

我的代码存在一些问题,我没有使用相同的 IV 进行加密和解密。我知道为了正确地做到这一点,我必须在数据之前将 IV 写入我的输出文件,但是我正在努力实现这一点。谁能帮我解决这个问题吗?

再次编辑代码以显示完整范围

public class TestFileEncryption {
private static void mainCrypto(int cipherMode, File inputFile, File outputFile) throws Exception{
//Let the user enter the key they wish to use
Key secretKey = new SecretKeySpec(UITest.getStoreKey().getBytes(), UITest.getSendAlg()); //Generates a key based on the default keysize for the specified algorithm

//Generate an Initialization Vector (IV)
final int ALG_KEYLENGTH = UITest.getStoreKey().length(); //Change this as desired for the security level you want
byte[] iv = new byte[ALG_KEYLENGTH]; //Save the IV bytes or send it in plaintext with the encrypted data so you can decrypt the data later
SecureRandom prng = new SecureRandom(); //Use SecureRandom to generate random bits. The size of the IV matches the blocksize of the cipher
prng.nextBytes(iv); //Construct the appropriate IvParameterSpec object for the data to pass to Cipher's init() method

//Create a Cipher by specifying the following parameters: Alg name, Mode (CBC), Padding (PKC7/PKCS5)
Cipher cipherForEncryption = Cipher.getInstance(UITest.getSendAlg() + "/CBC/PKCS5PADDING"); // Must specify the mode explicitly as most JCE providers default to ECB mode

//Initialize the Cipher for Encryption
cipherForEncryption.init(cipherMode, secretKey, new IvParameterSpec(iv));

//Declare / Initialize the Data, Convert the Input to Bytes and encrypt or decrypt using doFinal.
FileInputStream inputStream = new FileInputStream(inputFile);
byte[] inputBytes = new byte[(int) inputFile.length() - ALG_KEYLENGTH];
inputStream.read(iv);
inputStream.read(inputBytes);
byte[] outputBytes = cipherForEncryption.doFinal(inputBytes);
FileOutputStream outputStream = new FileOutputStream(outputFile);
outputStream.write(iv);
outputStream.write(outputBytes);
inputStream.close();
outputStream.close();
}

public static void encrypt(File inputFile, File outputFile) throws Exception {
mainCrypto(Cipher.ENCRYPT_MODE, inputFile, outputFile); //ENC_MODE = Constant used to initialize cipher to encryption mode.
}

public static void decrypt(File inputFile, File outputFile) throws Exception {
mainCrypto(Cipher.DECRYPT_MODE, inputFile, outputFile); //ENC_MODE = Constant used to initialize cipher to encryption mode.
}

public static void main(String[] args) {}
}

最佳答案

只是扩展@Javier的答案。

看起来您想使用相同的方法进行加密和解密(取决于模式),但是处理 IV 方面存在差异。

您生成了一个随机 IV,然后用(纯)输入的输入覆盖它,最后将其写入输出(无论它是解密的)。

所以你要区分模式是否为

  • 加密 - 生成 IV 并在密文之前写入输出
  • 解密 - 从输入中读取 IV 并用于解密,但不写入输出

类似的东西:

private void encrypt(File inputFile, File outputFile)  {
//Declare / Initialize the Data, Convert the Input to Bytes and encrypt or decrypt using doFinal.
FileInputStream inputStream = new FileInputStream(inputFile);
byte[] inputBytes = new byte[(int) inputFile.length()];
byte[] iv = new byte[16]; // 16 for AES-CBC
SecureRandom prng = new SecureRandom(); //Use SecureRandom to generate random bits. The size of the IV matches the blocksize of the cipher
prng.nextBytes(iv); //Construct the appropriate IvParameterSpec object for the data to pass to Cipher's init() method

//Create a Cipher by specifying the following parameters: Alg name, Mode (CBC), Padding (PKC7/PKCS5)
Cipher cipherForEncryption = Cipher.getInstance(UITest.getSendAlg() + "/CBC/PKCS5PADDING"); // Must specify the mode explicitly as most JCE providers default to ECB mode

//Initialize the Cipher for Encryption
cipherForEncryption.init(cipherMode, secretKey, new IvParameterSpec(iv));
inputStream.read(inputBytes);
byte[] outputBytes = cipherForEncryption.doFinal(inputBytes);
FileOutputStream outputStream = new FileOutputStream(outputFile);
outputStream.write(iv);
outputStream.write(outputBytes);
outputStream.flush();
inputStream.close();
outputStream.close();
}
}

private void decrypt(File inputFile, File outputFile) {
//Declare / Initialize the Data, Convert the Input to Bytes and encrypt or decrypt using doFinal.
FileInputStream inputStream = new FileInputStream(inputFile);
byte[] inputBytes = new byte[(int) inputFile.length()-16];
byte[] iv = new byte[16]; // 16 for AES-CBC

//Create a Cipher by specifying the following parameters: Alg name, Mode (CBC), Padding (PKC7/PKCS5)
Cipher cipherForEncryption = Cipher.getInstance(UITest.getSendAlg() + "/CBC/PKCS5PADDING"); // Must specify the mode explicitly as most JCE providers default to ECB mode

//Initialize the Cipher for Encryption
cipherForEncryption.init(cipherMode, secretKey, new IvParameterSpec(iv));
inputStream.read(iv);
inputStream.read(inputBytes);
byte[] outputBytes = cipherForEncryption.doFinal(inputBytes);
FileOutputStream outputStream = new FileOutputStream(outputFile);
outputStream.write(outputBytes);
outputStream.flush();
inputStream.close();
outputStream.close();
}

为了省略一些细节,也许您可​​以直接使用 Java CipherOutputStream 和 CiptherInputStream,并且实现将为您处理这些细节(如果您不关心确切的格式)。

接下来您缺少的是身份验证标签,至少是保证密文完整性的明文哈希。 (这称为认证加密)

关于java - AES 使用相同的 IV 进行加密和解密,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44971076/

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