使用 AES-256/CBC/PKCS7PADDING 时,空空格被添加到解密的 D01 文件中

问题描述 投票:0回答:1

我正在使用 AES-256/CBC/PKCS7PADDING 加密 d01 文件。加密文件后,我正在解密同一文件以进行测试,但在解密文件时,额外的空值将添加到 do1 文件中。我在这里使用 bouncycastle 库。

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.security.SecureRandom;
import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.BufferedBlockCipher;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.DataLengthException;
import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.engines.AESEngine;
import org.bouncycastle.crypto.engines.AESFastEngine;
import org.bouncycastle.crypto.modes.CBCBlockCipher;
import org.bouncycastle.crypto.paddings.BlockCipherPadding;
import org.bouncycastle.crypto.paddings.PKCS7Padding;
import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;
import org.springframework.stereotype.Component;

@Component
public class CryptoUtilsV2 {

   public static byte[] iv = generateIV();
  public int encryptDCRenewal(String keyText, File inputFile, File outputFile)
      throws Exception {
    //inputFile is d01 file and outfile is the d01 file to which encrypted data is written
   // initialize key and iv
    byte[] secretKey = keyText.getBytes(StandardCharsets.UTF_8);
    FileInputStream inputStream = new FileInputStream(inputFile);
    byte[] inputBytes = new byte[(int) inputFile.length()];
    inputStream.read(inputBytes);
    inputStream.close();
    // Encrypt the message
    byte[] ciphertext = encrypt(inputBytes, secretKey, iv);
    FileOutputStream outputStream = new FileOutputStream(outputFile);
    outputStream.write(ciphertext);
    outputStream.close();
    return 0;
  }

  public int decryptDCRenewal(String keyText, File inputFile, File outputFile)
      throws Exception {
    // initialize key and iv
    //inputFile is encrypted d01 file and outfile is the do1 file to which decrypted data is written
    byte[] secretKey = keyText.getBytes(StandardCharsets.UTF_8);
    FileInputStream inputStream = new FileInputStream(inputFile);
    byte[] inputBytes = new byte[(int) inputFile.length()];
    inputStream.read(inputBytes);
    inputStream.close();
    // Encrypt the message
    byte[] decryptedText = decrypt(inputBytes, secretKey, iv);
    FileOutputStream outputStream = new FileOutputStream(outputFile);
    outputStream.write(decryptedText);
    outputStream.close();
    return 0;
  }

  private static byte[] decrypt(byte[] ciphertext, byte[] key, byte[] iv) throws Exception {
    BufferedBlockCipher cipher = createCipher(false, key, iv);
    byte[] output = new byte[cipher.getOutputSize(ciphertext.length)];
    int bytesWritten = cipher.processBytes(ciphertext, 0, ciphertext.length, output, 0);
    bytesWritten += cipher.doFinal(output, bytesWritten);
    return output;
  }
  private static byte[] encrypt(byte[] input, byte[] key, byte[] iv) throws Exception {
    BufferedBlockCipher cipher = createCipher(true, key, iv);
    byte[] output = new byte[cipher.getOutputSize(input.length)];
    int bytesWritten = cipher.processBytes(input, 0, input.length, output, 0);
    bytesWritten += cipher.doFinal(output, bytesWritten);
    return output;
  }

  private static BufferedBlockCipher createCipher(boolean forEncryption, byte[] key, byte[] iv) {
    BlockCipherPadding padding = new PKCS7Padding();
    BufferedBlockCipher cipher = new PaddedBufferedBlockCipher(
        new CBCBlockCipher(new AESEngine()), padding);
    CipherParameters params = new ParametersWithIV(new KeyParameter(key), iv);
    cipher.init(forEncryption, params);
    return cipher;
  }
  private static byte[] generateIV() {
    byte[] iv = new byte[16]; // AES 256 use 16 byte IV
    new SecureRandom().nextBytes(iv);
    return iv;
  }
}

关键值为:Qxyyywqg1UdBRpUV

原始d01文件内容

解密后的d01文件内容:

java spring-boot encryption aes pkcs#7
1个回答
0
投票

getOutputSize(..)
不要返回你所期望的:

int getOutputSize(int len)
返回更新所需的输出缓冲区的大小以及输入为 len 字节的 doFinal。

该方法用于计算加密后消息的大小..而不是用于解密。

您只能在删除填充后才能看到解密消息的大小,这是在解密过程中发生的。您实际上计算了

bytesWritten
中解密消息的大小,然后忽略结果。

© www.soinside.com 2019 - 2024. All rights reserved.