2016-05-04 56 views
-1

我有以下的代碼來定義一個密碼類錯誤的密碼解密,最後一個塊未正確填充

import java.util.*; 
import javax.crypto.Cipher; 
import java.security.SecureRandom; 
import java.security.NoSuchAlgorithmException; 
import java.security.AlgorithmParameters; 
import javax.crypto.*; 
import javax.crypto.SecretKeyFactory; 
import javax.crypto.SecretKey; 
import javax.crypto.spec.PBEKeySpec; 
import javax.crypto.spec.SecretKeySpec; 
import javax.crypto.spec.IvParameterSpec; 

public class Cipher{ 
    private SecureRandom rand; 
    private SecretKeyFactory kFact; 
    private Cipher AESCipher; 
    private SecretKey key; 

    public Cipher(char[] mpw, byte[] salt){ 
      try{ 
        kFact = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); 
        rand = SecureRandom.getInstance("SHA1PRNG"); 
        AESCipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
        PBEKeySpec spec = new PBEKeySpec(mpw, salt, 1024, 256); 
        key = new SecretKeySpec(kFact.generateSecret(spec).getEncoded(),"AES"); 
      }catch(Exception e){ 
        System.out.println("no such algorithm"); 
      } 
    } 
    /*Henc[k,m] will return c such that Hdec[k,HEnc[k,m]] = m 
    */ 
    public ArrayList<byte[]> HEnc(byte[] message) throws Exception{ 
      ArrayList<byte[]> res = new ArrayList<byte[]>(2); 
      AESCipher.init(Cipher.ENCRYPT_MODE ,key); 
      AlgorithmParameters params = AESCipher.getParameters(); 
      byte[] iv = params.getParameterSpec(IvParameterSpec.class).getIV(); 
      byte[] ctxt = AESCipher.doFinal(message); 
      res.add(0,iv); 
      res.add(1,ctxt); 
      return res; 
    } 
    public byte[] HDec(byte[] iv, byte[] cipher) throws Exception{ 
      AESCipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv)); 
      System.out.println("decrypting"); 
      return AESCipher.doFinal(cipher); 
    } 
    /*public abstract byte[] HDec(SecretKey k, byte[] cipher); 
    */ 

我感興趣的解密密文不正確的密碼,這樣做我定義如下測試類,

import java.util.*; 
import java.io.*; 

public class testCipher{ 
    public static void main(String[] args) throws Exception{ 
      while(true){ 
        Scanner sc = new Scanner(System.in); 
        System.out.println("Enter master password"); 
        String pass = sc.nextLine(); 
        System.out.println("Enter incorrect password"); 
        String fakepass = sc.nextLine(); 
        System.out.println("Enter message to encrypt"); 
        String message = sc.next(); 
        String salt = "123"; 
        HCipher goodEnc = new HCipher(pass.toCharArray(),salt.getBytes()); 
        HCipher badEnc = new HCipher(fakepass.toCharArray(),salt.getBytes()); 
        byte[] toEncrypt = message.getBytes(); 
        ArrayList<byte[]> cipher = goodEnc.HEnc(toEncrypt); 
        byte[] ciphertxt = cipher.get(1); 
        byte[] iv = cipher.get(0); 

        while(true){ 
          System.out.println("Enter 1 to decrypt with correct pass, 2 to decrypt with incorrect pass and 0 to end simulation"); 
          int i = sc.nextInt(); 
          if(i == 1){ 
            System.out.println("Decrypting with correct password"); 
            byte[] plaintxt = goodEnc.HDec(iv, ciphertxt); 
            System.out.println(new String(plaintxt)); 
          } 
          if(i == 2){ 
            System.out.println("Decrypting with incorrect password"); 
            byte[] plaintxt = badEnc.HDec(iv, ciphertxt); 
            System.out.println(new String(plaintxt)); 

          } 
          if(i == 0){ 
            break; 
          } 
        } 
      } 
    } 
} 

使用正確的密碼進行加密和解密效果很好。然而,當我嘗試使用不正確的密碼解密,我得到的follwing錯誤:

Exception in thread "main" 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:420) 
at javax.crypto.Cipher.doFinal(Cipher.java:1966) 
at HCipher.HDec(HCipher.java:54) 
at testCipher.main(testCipher.java:52) 

我猜它是與我的IV但林不知道如何解決它。有沒有人有什麼建議?

回答

0

AES是塊密碼,在16個字節塊進行加密。填充用於在加密之前填滿您的最後一個塊,因此它適合於偶數個塊。

您指定PKCS5Padding用這樣的:在這樣一種方式,它可以識別和解密過程中刪除創建

AESCipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 

的填充。如果你用錯誤的鑰匙解密密碼將無法識別有效墊,從而給你BadPaddingException

如果你實例化你的解密Cipher沒有填充(並因此承擔這個責任你自己),你能避免這例外。

相關問題