【问题标题】:Spring Security Crypto final block not properly paddedSpring Security Crypto 最终块未正确填充
【发布时间】:2016-11-08 18:28:47
【问题描述】:

我正在尝试使用弹簧安全加密创建文件加密概念的证明。根据我发现的其他一些帖子,我已经下载了 Unlimited JCE Policy 并将 jar 添加到我的 java_home/jre/lib/security 文件夹中。

调用 bytesEncryptor.decrypt 时出现错误。加密可能正在工作,因为执行后文件中存在加密内容,但我不确定是否有办法确认这不是问题所在。关于此错误的其他一些未使用 Spring 的帖子说密钥不正确,但这不可能是因为我使用的是相同的 bytesEncryptor 对象? (Given final block not properly padded)

堆栈:

Exception in thread "main" java.lang.IllegalStateException: Unable to invoke Cipher due to bad padding
at org.springframework.security.crypto.encrypt.CipherUtils.doFinal(CipherUtils.java:142)
    at org.springframework.security.crypto.encrypt.AesBytesEncryptor.decrypt(AesBytesEncryptor.java:128)
    at com.test.encryption.MyTest.crypt(MyTest.java:45)
    at com.test.encryption.MyTest.decryptFile(MyTest.java:31)
    at com.test.encryption.MyTest.main(MyTest.java:21)
Caused by: javax.crypto.BadPaddingException: Given final block not properly padded
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:811)
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:676)
    at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:313)
    at javax.crypto.Cipher.doFinal(Cipher.java:2087)
    at org.springframework.security.crypto.encrypt.CipherUtils.doFinal(CipherUtils.java:135)
... 4 more

代码:

public static void main(String args[]) throws Exception {
    String salt = KeyGenerators.string().generateKey();
    BytesEncryptor bytesEncryptor = Encryptors.standard("password", salt);

    encryptFile(bytesEncryptor, "C:/test/testIn.txt", "C:/test/testOut.txt");
    decryptFile(bytesEncryptor, "C:/test/testOut.txt", "C:/test/testOutDecode.txt");
}


private static void encryptFile (BytesEncryptor bytesEncryptor, String in, String out) throws Exception {
    crypt(bytesEncryptor, in, out, true);
}

private static void decryptFile (BytesEncryptor bytesEncryptor, String in, String out) throws Exception {
    crypt(bytesEncryptor, in, out, false);
}

private static void crypt (BytesEncryptor bytesEncryptor, String in, String out, boolean encrypt) throws Exception {
    byte[] buffer = new byte[1024];
    int numRead;
    byte[] bytes = null;
    InputStream input = new FileInputStream(in);
    OutputStream output = new FileOutputStream(out);

    while ((numRead = input.read(buffer)) > 0) {
        if(encrypt) {
            bytes = bytesEncryptor.encrypt(buffer);
        } else {
            bytes = bytesEncryptor.decrypt(buffer);
        }

        if (bytes != null) {
            output.write(bytes, 0, numRead);
        }
    }

    input.close();
    output.close();
}

【问题讨论】:

    标签: java encryption spring-security


    【解决方案1】:

    不管怎样,我收到了这条消息,当时我使用了错误的密码/盐来解密(虽然长度相同)

    【讨论】:

      【解决方案2】:

      我怀疑问题出在他们以 1024 字节为单位读取文件的方式上。 AES 是一种分组密码,因此对一定大小的数据块进行操作。当它加密时,它将填充输出以确保它适合适当大小的块。当您向它提供数据以解密时,它希望在必要时对数据进行类似的填充。

      尝试将整个文件读入一个字节数组,然后对其进行加密和解密。或者,您可以尝试使用与您用于 AES 的块大小相匹配的块大小(它将是 128、192 或 256 位)。

      【讨论】:

      • 我尝试将整个文件读入一个单字节数组并加密和解密,但收到了同样的错误。将缓冲区大小更改为 128、196 和 256 位时,我也会遇到同样的错误。查看 Spring 的 AesBytesEncryptor 应该使用 256 位加密。
      【解决方案3】:

      原来你需要为 FileInputStreams 和 FileOutputStreams 使用 CipherInputStream 和 CipherOutputStream。

      以下内容或多或少取自http://www.programcreek.com/java-api-examples/index.php?source_dir=cube-master/cube-common/src/main/java/ch/admin/vbs/cube/common/crypto/AESEncrypter.java

      更新代码:

      import javax.crypto.*;
      import javax.crypto.spec.IvParameterSpec;
      import java.io.FileInputStream;
      import java.io.FileOutputStream;
      import java.io.InputStream;
      import java.io.OutputStream;
      import java.security.SecureRandom;
      
      public class MyTest {
      
          private static String algorithm = "AES/CBC/PKCS5Padding";
      
          public static void main(String args[]) throws Exception {
              KeyGenerator keyGen = KeyGenerator.getInstance("AES");
              keyGen.init(256);
              SecretKey secretKey = keyGen.generateKey();
      
              final int AES_KEYLENGTH = 256;
              byte[] iv = new byte[AES_KEYLENGTH / 16];
              SecureRandom prng = new SecureRandom();
              prng.nextBytes(iv);
      
              Cipher aesCipherForEncryption = Cipher.getInstance(algorithm);
              Cipher aesCipherForDecryption = Cipher.getInstance(algorithm);
              aesCipherForEncryption.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(iv));
              aesCipherForDecryption.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(iv));
      
              encryptFile(aesCipherForEncryption, "C:/test/testIn.txt", "C:/test/testOut.txt");
              decryptFile(aesCipherForDecryption, "C:/test/testOut.txt", "C:/test/testOutDecode.txt");
          }
      
      
          private static void encryptFile (Cipher cipher, String in, String out) throws Exception {
              crypt(cipher, in, out, true);
          }
      
          private static void decryptFile (Cipher cipher, String in, String out) throws Exception {
              crypt(cipher, in, out, false);
          }
      
          private static void crypt (Cipher cipher, String in, String out, boolean encrypt) throws Exception {
              byte[] buffer = new byte[256];
              int numRead;
              InputStream input = new FileInputStream(in);
              OutputStream output = new FileOutputStream(out);
      
              if(encrypt) {
                  output = new CipherOutputStream(output, cipher);
              } else {
                  input = new CipherInputStream(input, cipher);
              }
      
              while ((numRead = input.read(buffer)) >= 0) {
                  output.write(buffer, 0, numRead);
              }
      
              input.close();
              output.close();
          }
      }
      

      注意 - 我最终放弃了使用 Spring Security Crypto 实现。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-12-24
        • 2015-06-18
        • 2011-05-16
        • 2015-07-01
        • 2014-05-29
        • 1970-01-01
        • 2012-05-12
        • 2012-03-03
        相关资源
        最近更新 更多