2016-11-06 8 views
0

この質問はおそらくすでに聞かれていたかもしれませんが、暗号化、特にキー処理について理解していないので、例外、解決策を見つける方法/場所javax.crypto.BadPaddingException:CipherInputStreamで最後のブロックが正しく埋められていない場合

暗号化されたファイルとの間でオブジェクトの書き込みと読み取りを試みています。 そのために私はDataInputStreamの下にCipherInputStreamをラップしました。

BadPaddingの例外が発生しています。これはおそらく、私がキーに何か問題があることを意味しています。

私を助けてください。

Main.java:

package main; 

import java.util.Arrays; 

import io.Io; 

public class Main { 
    static final String FIRST_TEXT_TO_CRYPTO = "First text"; 
    static final boolean BOOLEAN_CRYPTO = true; 
    static final String SECOND_TEXT_TO_CRYPTO = "First text"; 
    static final String KEY = "key123"; 

    public static void main(String[] args) { 
     Io.encryptAndWriteAll(Arrays.asList(new Stuff(FIRST_TEXT_TO_CRYPTO, BOOLEAN_CRYPTO, SECOND_TEXT_TO_CRYPTO)), 
       KEY); 

     for (Stuff stuff : Io.readAndDecryptAllFromLocation(KEY)) { 
      System.out.println(stuff); 
     } 
    } 
} 

Stuff.java

package main; 

import javafx.beans.property.SimpleBooleanProperty; 
import javafx.beans.property.SimpleStringProperty; 

public class Stuff { 
    SimpleStringProperty firstString = new SimpleStringProperty(), secondString = new SimpleStringProperty(); 
    SimpleBooleanProperty bool = new SimpleBooleanProperty(); 

    public Stuff(String firstString, boolean bool, String secondString) { 
     this.firstString.set(firstString); 
     this.secondString.set(secondString); 
     this.bool.set(bool); 
    } 

    @Override 
    public String toString() { 
     return String.format("FirstString: %s; Boolean: %B; SecondString: %s", getFirstString(), isBool(), 
       getSecondString()); 
    } 

    public final SimpleStringProperty firstStringProperty() { 
     return this.firstString; 
    } 

    public final String getFirstString() { 
     return this.firstStringProperty().get(); 
    } 

    public final void setFirstString(final String firstString) { 
     this.firstStringProperty().set(firstString); 
    } 

    public final SimpleStringProperty secondStringProperty() { 
     return this.secondString; 
    } 

    public final String getSecondString() { 
     return this.secondStringProperty().get(); 
    } 

    public final void setSecondString(final String secondString) { 
     this.secondStringProperty().set(secondString); 
    } 

    public final SimpleBooleanProperty boolProperty() { 
     return this.bool; 
    } 

    public final boolean isBool() { 
     return this.boolProperty().get(); 
    } 

    public final void setBool(final boolean bool) { 
     this.boolProperty().set(bool); 
    } 

} 

Io.java:

package io; 

import java.io.BufferedInputStream; 
import java.io.BufferedOutputStream; 
import java.io.DataInputStream; 
import java.io.DataOutputStream; 
import java.io.EOFException; 
import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.UTFDataFormatException; 
import java.util.ArrayList; 
import java.util.List; 

import javax.crypto.CipherInputStream; 
import javax.crypto.CipherOutputStream; 

import main.Stuff; 

public class Io { 
    private static final File FILE = new File("file.file"); 

    public static void encryptAndWriteAll(List<Stuff> stuffs, String key) { 
     try (FileOutputStream fos = new FileOutputStream(FILE); 
       BufferedOutputStream bos = new BufferedOutputStream(fos); 
       CipherOutputStream cos = new CipherOutputStream(bos, new Crypto(key).getEncryptionCipher()); 
       DataOutputStream dos = new DataOutputStream(cos)) { 
      for (Stuff stuff : stuffs) { 
       dos.writeUTF(stuff.getFirstString()); 
       dos.writeBoolean(stuff.isBool()); 
       dos.writeUTF(stuff.getSecondString()); 
      } 
     } catch (FileNotFoundException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

    public static List<Stuff> readAndDecryptAllFromLocation(String key) { 
     try (FileInputStream fis = new FileInputStream(FILE); 
       BufferedInputStream bis = new BufferedInputStream(fis); 
       CipherInputStream cis = new CipherInputStream(bis, new Crypto(key).getDecryptionCipher()); 
       DataInputStream dis = new DataInputStream(cis)) { 
      ArrayList<Stuff> stuffs = new ArrayList<>(); 
      try { 
       for (;;) 
        // The next line throws 
        // ("at io.Io.readAndDecryptAllFromLocation(Io.java:52)") 
        stuffs.add(new Stuff(dis.readUTF(), dis.readBoolean(), dis.readUTF())); 
      } catch (EOFException e) { 
       System.out.println("EOF"); 
       e.printStackTrace(); 
      } catch (UTFDataFormatException e) { 
       e.printStackTrace(); 
      } 
      return stuffs; 
     } catch (FileNotFoundException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
     return null; 
    } 
} 

Crypto.java:

package io; 

import java.security.InvalidKeyException; 
import java.security.Key; 
import java.security.MessageDigest; 
import java.security.NoSuchAlgorithmException; 
import java.util.Arrays; 

import javax.crypto.Cipher; 
import javax.crypto.NoSuchPaddingException; 
import javax.crypto.spec.SecretKeySpec; 

public class Crypto { 

    private static final String TRANSFORMATION = "AES/CBC/PKCS5Padding"; 
    private static final String ALGORITHM = "AES"; 
    private byte[] paddedKey; 

    public Crypto(String key) { 
     paddedKey = addPaddingToKey(key); 
    } 

    private byte[] addPaddingToKey(String key) { 
     try { 
      MessageDigest digest = MessageDigest.getInstance("SHA-256"); 
      return Arrays.copyOf(digest.digest(key.getBytes()), 16); 
     } catch (NoSuchAlgorithmException e) { 
      e.printStackTrace(); 
     } 
     return null; 
    } 

    private Key getKey() { 
     return new SecretKeySpec(paddedKey, ALGORITHM); 
    } 

    public Cipher getEncryptionCipher() { 
     try { 
      Cipher cipher = Cipher.getInstance(TRANSFORMATION); 
      cipher.init(Cipher.ENCRYPT_MODE, getKey()); 
      return cipher; 
     } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException e) { 
      e.printStackTrace(); 
     } 
     return null; 
    } 

    public Cipher getDecryptionCipher() { 
     try { 
      Cipher cipher = Cipher.getInstance(ALGORITHM); 
      cipher.init(Cipher.DECRYPT_MODE, getKey()); 
      return cipher; 
     } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException e) { 
      e.printStackTrace(); 
     } 
     return null; 
    } 

} 

例外:

java.io.IOException: javax.crypto.BadPaddingException: Given final block not properly padded 
    at javax.crypto.CipherInputStream.getMoreData(CipherInputStream.java:121) 
    at javax.crypto.CipherInputStream.read(CipherInputStream.java:239) 
    at java.io.DataInputStream.readFully(DataInputStream.java:195) 
    at java.io.DataInputStream.readUTF(DataInputStream.java:609) 
    at java.io.DataInputStream.readUTF(DataInputStream.java:564) 
    at io.Io.readAndDecryptAllFromLocation(Io.java:52) 
    at main.Main.main(Main.java:17) 
Caused by: javax.crypto.BadPaddingException: Given final block not properly padded 
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:975) 
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:833) 
    at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:446) 
    at javax.crypto.Cipher.doFinal(Cipher.java:2048) 
    at javax.crypto.CipherInputStream.getMoreData(CipherInputStream.java:118) 
    ... 6 more 
Exception in thread "main" java.lang.NullPointerException 
    at main.Main.main(Main.java:17) 
+0

[mcve]、IOWに必要なコードを入力してください。 – zaph

答えて

2

IVパラメータが必要なAES/CBCを使用しています。暗号化中にIVパラメータを指定しなかった場合は、ランダムIVが生成されて使用されます。

IVは無作為に生成する必要はないので、ランダムにIVを生成して暗号化されたデータの前に追加することができます。

+2

暗号化されたデータにIVを付加する前に暗号化しておく方が、秘密にする必要はありません。そうすれば、それは復号化のために利用可能です。 – zaph

+1

ランダムIVを使用しないことは安全ではありません.IVを格納して再利用するのは、暗号化/復号化が同じ場所で実行される場合のみです。だから、あなたが問題を明らかにしたかもしれないが、提示された解決法はそれを解決しない(安全に)。 –

+0

データが暗号化されるたびに無作為に生成されたIVをファイルの先頭に追加しても問題ありませんか?または、ランダムに生成されたIVをどのように保存する必要がありますか? – SlumpA

関連する問題