2016-05-04 12 views
-1

ich den folgenden Code habe eine Chiffre KlasseEntschlüsseln mit dem falschen Passwort, letzter Block nicht richtig gepolstert

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); 
    */ 

Ich interessiere mich für das Entschlüsseln Chiffre-Textes mit falschen Passwörtern zu definieren, zu tun, so definiere ich die folgend Testklasse,

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

Verschlüsseln und Entschlüsseln mit dem richtigen Kennwort funktioniert gut. Aber wenn ich versuche, ein falsches Passwort zu entschlüsseln, verwenden, erhalte ich die follwing Fehler:

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) 

Ich vermute, bin es etwas zu tun mit meinem IV hat, aber ich bin nicht sicher, wie es zu beheben. Hat jemand irgendwelche Vorschläge?

Antwort

0

AES ist eine Blockchiffre, die Blöcke von 16 Bytes verschlüsselt. Padding wird verwendet, um den letzten Block vor der Verschlüsselung aufzufüllen, sodass er in eine gerade Anzahl von Blöcken passt.

Sie angeben PKCS5Padding mit diesem:

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

Die Polsterung ist so angelegt, dass sie während der Entschlüsselung erkannt und entfernt werden können. Wenn Sie mit dem falschen Schlüssel entschlüsseln werden die Cipher nicht in der Lage sein, eine gültige Pad zu identifizieren und Ihnen so gibt die BadPaddingException

Wenn Sie Ihr decrypt Cipher ohne Polsterung instanziiert (und damit diese Verantwortung übernehmen selbst) Sie dies vermeiden können Ausnahme.