【问题标题】:Java: Bad padding error when decrypting from encrypted fileJava:从加密文件解密时出现错误的填充错误
【发布时间】:2014-02-09 10:40:19
【问题描述】:

我正在构建一个文件加密实用程序,这是我的加密代码:

    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding", "SunJCE");
    SecretKeySpec key = new SecretKeySpec(encryptionKey.getBytes("UTF-8"), "AES");
    cipher.init(Cipher.ENCRYPT_MODE, key,new IvParameterSpec(IV.getBytes("UTF-8")));
    for(int i = 0; i < input.size(); i++){
        plainText = input.get(i);
        byte[] b = cipher.doFinal(plainText.getBytes("UTF-8"));
        String outString = new String(b);
        //to be written to file

要加密的字符串从数组中读取(该实用程序进行其他数据处理)然后加密,并在准备好时以字符串数组的形式输出以写入文件。

解密时,我得到一个错误,我的填充错误。我一直在研究并收集这归结为 .getBytes() 没有完全按原样返回字节数组。我正在逐行读取已使用我以前的代码加密的文件。如何确保我的解密函数接收到正确的字节数组?

代码如下:

public void decode(File f) throws Exception{
     BufferedWriter out = new BufferedWriter(new FileWriter("Decrypted Archive "+f.getName()+".txt"));
     BufferedReader br = new BufferedReader(new FileReader(f));
     String line;
     while((line = br.readLine())!=null){
         byte[] b = line.getBytes("UTF-8"); 
         line = Decoder.decrypt(b);
         out.write(line+newline);
     }
     br.close();
     out.close();

还有解密函数:

public static String decrypt(byte[] cipherText) throws Exception{
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding", "SunJCE");
    SecretKeySpec key = new SecretKeySpec(encryptionKey.getBytes("UTF-8"), "AES");
    cipher.init(Cipher.DECRYPT_MODE, key,new IvParameterSpec(IV.getBytes("UTF-8")));
    return new String(cipher.doFinal(cipherText),"UTF-8");
  }

加密密钥等都是一样的。

【问题讨论】:

    标签: java arrays encryption cryptography


    【解决方案1】:

    String outString = new String(b); 将不起作用。如果您必须将密码视为字符串,那么您必须对其进行编码。您可以使用标准 Java 中的 printBase64Binary 和 parseBase64Binary 方法在 base64 字符串之间进行转换。如果您使用的是 Android,则可以改用 android.util.Base64 类。

    此外,您的加密器对Cipher.doFinal(...) 的使用至少可以说有点可疑。通过将每个输入视为单独的明文序列,您最终每次都重用 IV。通常您想使用Cipher.update(...) 方法加密每个输入片段,完成后使用doFinal(...)。

    【讨论】:

      【解决方案2】:

      Java 库 Reader 和 Writer 类旨在处理面向行的未加密文本。但是,文本一旦加密,就不再是文本,因此将其视为文本可能会导致问题。

      您应该改为使用 InputStream 和 OutputStream 类来处理原始数据,而不是使用 Reader 和 Writer 类来进行文件访问。编辑:特别是,您可以使用 CipherInputStream 和 CipherOutputStream 这样您就不必直接调用 Cipher 方法。您还可以在 CipherInputStream 上构造 InputStreamReader,在 CipherOutputStream 上构造 OutputStreamWriter,然后只使用 read() 和 write() 方法,让流负责加密。

      【讨论】:

      • 谢谢,我试试这个。我可以继续照常加密并使用数据流来读取加密文件吗?
      • @user3289385 每当您对密文执行new String(...) 时,您都将加密数据视为文本。
      • @user3289385 如果要继续直接加密,请参阅下面 GregS 的评论。或者,使用 CipherOutputStream 和 CipherInputStream 可能更容易。我已经编辑了我的答案,包括对此的讨论。
      猜你喜欢
      • 2017-12-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多