2016-07-06 2 views
1

Ich versuche, einen Proof of Concept der Dateiverschlüsselung mit Feder Sicherheit Crypto zu erstellen. Für einige der anderen Posts, die ich gefunden habe, habe ich die Unlimited JCE Policy heruntergeladen und die Jars zu meinem java_home/jre/lib/security-Ordner hinzugefügt.Spring Security Crypto letzten Block nicht richtig gepolstert

Der Fehler tritt beim Aufruf von BytesEncryptor.decrypt auf. Die Verschlüsselung funktioniert möglicherweise, da in der Datei nach der Ausführung verschlüsselter Inhalt vorhanden ist, aber ich bin mir nicht sicher, ob das nicht der Fall ist, wo das Problem liegt. Einige andere Posts über diesen Fehler, die Spring nicht verwenden, sagen, dass der Schlüssel nicht richtig ist, aber das kann nicht sein, da ich dasselbe bytesEncryptor Objekt verwende? (Given final block not properly padded)

Stack:

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 

Code:

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(); 
} 

Antwort

0

Es stellt sich heraus, dass Sie einen CipherInputStream und CipherOutputStream für FileInputStreams und FileOutputStreams verwenden müssen.

Unten mehr oder weniger von diesem genommen 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

Aktualisiert Code:

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(); 
    } 
} 

Hinweis - ich habe am Ende gehen weg die Spring Security Crypto Implementierung verwenden.

0

Ich vermute, das Problem kommt aus sie so, wie Sie Ihre Datei in Blöcken von 1024 Bytes lesen. AES ist eine Blockchiffre, die auf Datenblöcke einer bestimmten Größe wirkt. Wenn es chiffriert, puffert es die Ausgabe, um sicherzustellen, dass es in Stücke der passenden Größe passt. Wenn Sie ihm Daten zum Entschlüsseln geben, erwartet er, dass die Daten bei Bedarf ähnlich aufgefüllt werden.

Versuchen Sie, die gesamte Datei in ein Byte-Array zu lesen und dann zu verschlüsseln und zu entschlüsseln. Alternativ könnten Sie versuchen, eine Chunk-Größe zu verwenden, die der Blockgröße entspricht, die Sie für AES verwenden (es sind 128, 192 oder 256 Bits).

+0

Ich habe versucht, die gesamte Datei in einem einzigen Byte-Array zu lesen und zu verschlüsseln und zu entschlüsseln, erhielt aber den gleichen Fehler. Ich bekomme auch den gleichen Fehler für die Änderung der Puffergröße auf 128, 196 und 256 Bits. Wenn man AesBytesEncryptor von Spring betrachtet, sollte es eine 256-Bit-Verschlüsselung verwenden. – user1134179

Verwandte Themen