2016-07-06 41 views
1

我试图用spring security crypto创建文件加密概念的证明。根据我发现的其他一些帖子,我已经下载了无限JCE策略,并将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(); 
} 

回答

0

原来,您需要为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的加密实现走开。

0

我怀疑问题来自于他们的方式,你在读的1024个字节的块文件。 AES是一种分组密码,因此可对特定大小的数据块进行操作。加密时,它会填充输出以确保它适合合适大小的块。当你给它的数据进行解密时,如果需要的话,它希望数据被类似地填充。

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

+0

我试着将整个文件读入单个字节数组并加密和解密,但收到相同的错误。我也得到了将缓冲区大小更改为128,196和256位的错误。看着Spring的AesBytesEncryptor,它应该使用256位加密。 – user1134179