2016-07-06 69 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