2013-07-10 4 views
6

In meiner Anwendung verschlüssele und entschlüssele ich Daten mit secretKey. Dafür benutze ich den AES-Algorithmus. Aber ich bekomme eine Ausnahme beim Entschlüsseln, einen Wert von drei bereits verschlüsselten Werten unter Verwendung eines geheimen Schlüssels.Ungültige Ausnahme für Blockgröße Die Eingangslänge muss ein Vielfaches von 16 sein, wenn die Entschlüsselung mit einer gepolsterten Chiffre ausgeführt wird

Ausnahme ist:

Illegal Block Size Exception Input length must be multiple of 16 when decrypting with padded cipher. 

Unten ist mein Code:

Funktionswert encyrpt

public static String symmetricEncrypt(String text, String secretKey) { 
    BASE64Decoder decoder = new BASE64Decoder(); 
    byte[] raw; 
    String encryptedString; 
    SecretKeySpec skeySpec; 
    BASE64Encoder bASE64Encoder = new BASE64Encoder(); 
    byte[] encryptText = text.getBytes(); 
    Cipher cipher; 
    try { 
     raw = decoder.decodeBuffer(secretKey); 
     skeySpec = new SecretKeySpec(raw, "AES"); 
     cipher = Cipher.getInstance("AES"); 
     cipher.init(Cipher.ENCRYPT_MODE, skeySpec); 
     encryptedString = bASE64Encoder.encode(cipher.doFinal(encryptText)); 
    } 
    catch (Exception e) { 
     e.printStackTrace(); 
     return "Error"; 
    } 
    return encryptedString; 
} 

Funktionswert

012 zu entschlüsseln
public static String symmetricDecrypt(String text, String secretKey) { 
    BASE64Decoder decoder = new BASE64Decoder(); 
    BASE64Decoder base64Decoder = new BASE64Decoder(); 
    Cipher cipher; 
    String encryptedString; 
    byte[] encryptText = null; 
    byte[] raw; 
    SecretKeySpec skeySpec; 
    try { 
     raw = decoder.decodeBuffer(secretKey); 
     skeySpec = new SecretKeySpec(raw, "AES"); 
     encryptText = base64Decoder.decodeBuffer(text); 
     cipher = Cipher.getInstance("AES"); 
     cipher.init(Cipher.DECRYPT_MODE, skeySpec); 
     encryptedString = new String(cipher.doFinal(encryptText)); 
    } catch (Exception e) { 
     e.printStackTrace(); 
     return "Error"; 
    } 
    return encryptedString; 
} 

Im Folgenden sind die Werte, die ich Verschlüsselung und

String secretKey = "XMzDdG4D03CKm2IxIWQw7g=="; 
String value1= "ABCD"; 
String enctypedValue1= "3uweh4pzoVyH1uODQmVNJA=="; 
String enctypedValue2= "37PTC20w4DMZYjG3f+GWepSvAbEJUccMXwS/lXilLav1qM/PrCTdontw5/82OdC1zzyhDEsFVRGo rV6gXAQcm+Zai15hliiUQ8l8KRMtUl4="; 
String value4= "20000"; 

/** Ecnryption and decryption of value1 **/ 
String encryptedValue1= symmetricEncrypt(value1, secretKey); 
String decryptedValue1 = symmetricDecrypt(encryptedValue1, secretKey); 

/** Decryption of enctypedValue1 **/ 
String decryptedValue2 = symmetricDecrypt(enctypedValue1, secretKey); 
System.out.println(decryptedValue2); 

/** Decryption of enctypedValue2 (Not decrypted)**/ 
String decryptedValue3 = symmetricDecrypt(enctypedValue2, secretKey); 
System.out.println(decryptedValue3); 

/** Ecnryption and decryption of value4 **/ 
String encryptedValue4= symmetricEncrypt(value4, secretKey); 
String decryptedValue4 = symmetricDecrypt(encryptedValue4, secretKey); 

In der Testfunktion Entschlüsseln ich die folgenden drei Testfälle geschrieben haben.

  1. Ein neuer Wert (Wert1) wird mit einem geheimen Schlüssel verschlüsselt und entschlüsselt.
  2. Zwei verschlüsselte Beispielwerte (enctypedValue1, enctypedValue2), die mit demselben geheimen Schlüssel entschlüsselt werden. chiffrevalValue2, das beim Entschlüsseln mit demselben geheimen Schlüssel ein Problem bekommen hat.
  3. Ein neuer Wert (value4) wird mit einem geheimen Schlüssel verschlüsselt und entschlüsselt.

Auf encryptedValue2 Entschlüsseln ich die folgende Ausnahme bin immer:

Illegal Block Size Exception Input length must be multiple of 16 when decrypting with padded cipher 

Es folgt, was ich bis jetzt abgeleitet haben.

  1. Der problematische Wert scheint ein Problem beim Dekodieren zu haben, es gibt 81 Länge Array zurück, das nicht entschlüsselt werden kann?

  2. Wenn dieses Problem auftreten sollte, sollte es mit allen Werten geschehen sein.

  3. Ist dies ein wertspezifisches Problem oder ist es etwas mit Auffüllen oder kann es ein anderes Verhalten auf verschiedenen Browsern haben, andere os?

+2

in Ihrem decrypt-Methode, verwendet man 'Chiffre = Cipher.getInstance ("AES/ECB/PKCS5Padding"); 'Allerdings haben Sie in Ihrer Verschlüsselungsmethode' cipher = Cipher.getInstance ("AES"); '. Sie müssen gleich sein. Fügen Sie der Chiffriermethode in der Methode encrypt eine Auffüllung hinzu. – Multithreader

+0

Dieser Link kann hilfreich sein: http: //stackoverflow.com/questions/7640463/encryptionexception-javax-crypto-illegalblocksizeexception-input-length-must-b –

+0

@Multithreader danke für die Korrektur. Eigentlich ist es ein Schreibfehler. Bitte sehen Sie sich die bearbeitete Frage an. – RAS

Antwort

11

Ich konnte den Code ohne jedes Problem ausführen. Allerdings habe ich Apache Base64 für die Codierung/Decodierung verwendet ... vielleicht hat Ihr Base64 Fehler. Wenn Sie es selbst geschrieben haben, besteht eine große Chance, dass Sie einige Fälle verpasst haben. Verwenden Sie für echten Produktionscode stark getestete Bibliotheken wie Apache.

Sie können die Bibliothek, die ich für Base64 hier verwendet: http://commons.apache.org/proper/commons-codec/download_codec.cgi

Hier ist die vollständige Arbeits Code:

package security.symmatric; 

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

    import org.apache.commons.codec.binary.Base64; 

    public class AES { 
     public static String symmetricEncrypt(String text, String secretKey) { 
      byte[] raw; 
      String encryptedString; 
      SecretKeySpec skeySpec; 
      byte[] encryptText = text.getBytes(); 
      Cipher cipher; 
      try { 
       raw = Base64.decodeBase64(secretKey); 
       skeySpec = new SecretKeySpec(raw, "AES"); 
       cipher = Cipher.getInstance("AES"); 
       cipher.init(Cipher.ENCRYPT_MODE, skeySpec); 
       encryptedString = Base64.encodeBase64String(cipher.doFinal(encryptText)); 
      } 
      catch (Exception e) { 
       e.printStackTrace(); 
       return "Error"; 
      } 
      return encryptedString; 
     } 

     public static String symmetricDecrypt(String text, String secretKey) { 
      Cipher cipher; 
      String encryptedString; 
      byte[] encryptText = null; 
      byte[] raw; 
      SecretKeySpec skeySpec; 
      try { 
       raw = Base64.decodeBase64(secretKey); 
       skeySpec = new SecretKeySpec(raw, "AES"); 
       encryptText = Base64.decodeBase64(text); 
       cipher = Cipher.getInstance("AES"); 
       cipher.init(Cipher.DECRYPT_MODE, skeySpec); 
       encryptedString = new String(cipher.doFinal(encryptText)); 
      } catch (Exception e) { 
       e.printStackTrace(); 
       return "Error"; 
      } 
      return encryptedString; 
     } 

     public static void main(String[] args) { 
      String secretKey = "XMzDdG4D03CKm2IxIWQw7g=="; 
      String value1= "ABCD"; 
      String enctypedValue1= "3uweh4pzoVyH1uODQmVNJA=="; 
      String enctypedValue2= "37PTC20w4DMZYjG3f+GWepSvAbEJUccMXwS/lXilLav1qM/PrCTdontw5/82OdC1zzyhDEsFVRGo rV6gXAQcm+Zai15hliiUQ8l8KRMtUl4="; 
      String value4= "20000"; 

      /** Ecnryption and decryption of value1 **/ 
      String encryptedValue1= symmetricEncrypt(value1, secretKey); 
      String decryptedValue1 = symmetricDecrypt(encryptedValue1, secretKey); 
      System.out.println(decryptedValue1); 

      /** Decryption of enctypedValue1 **/ 
      String decryptedValue2 = symmetricDecrypt(enctypedValue1, secretKey); 
      System.out.println(decryptedValue2); 

      /** Decryption of enctypedValue2 **/ 
      String decryptedValue3 = symmetricDecrypt(enctypedValue2, secretKey); 
      System.out.println(decryptedValue3); 

      /** Ecnryption and decryption of value4 **/ 
      String encryptedValue4= symmetricEncrypt(value4, secretKey); 
      String decryptedValue4 = symmetricDecrypt(encryptedValue4, secretKey); 
      System.out.println(decryptedValue4); 
     } 
    } 
+0

Vielen Dank Es hat funktioniert. Ich benutze Suns Base64. Ich wollte fragen, was ist der Unterschied zwischen Apache Base64 und Sun Base64? Soll ich es in meinem Programm durch Apache Base64 ersetzen? – JankiPanwala

+2

Ja, ich empfehle dringend, Apache zu verwenden. Versuchen Sie, die Bibliotheken von Sun um jeden Preis zu vermeiden. Warum? weil ihre Bibliotheken nur für die interne Verwendung bei Sun ausgelegt sind (nicht als "öffentliche API"). Daher könnten sie die API ändern, die Abwärtskompatibilität aufheben und die Unterstützung einer API jederzeit und ohne vorherige Ankündigung beenden. Zumindest das, was ich verstehe ... – Multithreader

+0

Dieser Code funktioniert gut von der Hauptmethode, aber nicht, wenn ich in der Applet-Klasse schrieb. Geben Sie die Aufrufzielausnahme.Alle Unterstützung? –