2010-07-05 4 views
-1

Il s'agit du code pour crypter et décrypter une chaîne dans Java en utilisant l'algorithme AES. Il lance une exception illégaleblocksize lors du décryptage. Je sais que cela se produit parce que la longueur de la chaîne d'entrée de la méthode de déchiffrement ne correspond pas au remplissage. Je n'ai aucune idée de comment résoudre cela. Je suis un nouveau bie au décryptage de cryptage. Plz help me ....Exception dans l'algorithme de décryptage AES dans Java

StackTrace:

javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher 
    at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..) 
    at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..) 
    at com.sun.crypto.provider.AESCipher.engineDoFinal(DashoA13*..) 
    at javax.crypto.Cipher.doFinal(DashoA13*..) 
    at test.AES.AESdecryptalgo(AES.java:76) 
    at test.AES.main(AES.java:95) 

code:

package test; 
import javax.crypto.*; 
import javax.crypto.spec.*; 
import java.security.*; 

public class AES 
{ 
    public byte[] encrypted; 
    public byte[] original; 

    public String originalString; 
    Cipher cipher; 
    SecretKeySpec skeySpec; 
    IvParameterSpec spec; 
    byte [] iv; 
    /*public static String asHex (byte buf[]) 
    { 
    StringBuffer strbuf = new StringBuffer(buf.length * 2); 
    int i; 
    for (i = 0; i < buf.length; i++) { 
    if (((int) buf[i] & 0xff) < 0x10) 
    strbuf.append("0"); 
    strbuf.append(Long.toString((int) buf[i] & 0xff, 16)); 
    } 
    return strbuf.toString(); 
}*/ 
    public AES() 
    { 
     try 
     { 
      KeyGenerator kgen = KeyGenerator.getInstance("AES"); 
      kgen.init(128); 
      SecretKey skey = kgen.generateKey(); 
      byte[] raw = skey.getEncoded(); 
      skeySpec = new SecretKeySpec(raw, "AES"); 
      cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 

     } 
     catch(Exception ex) 
     {ex.printStackTrace();} 
    } 
public String AESencryptalgo(byte[] text) 
{ 
    String newtext=""; 
    try 
    { 
     // byte[] raw = skey.getEncoded(); 
     //SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); 
     cipher.init(Cipher.ENCRYPT_MODE, skeySpec); 
      AlgorithmParameters param = cipher.getParameters(); 
      IvParameterSpec ivspec=param.getParameterSpec(IvParameterSpec.class); 
      iv=ivspec.getIV(); 
      spec=new IvParameterSpec(iv); 
     //AlgorithmParameters params = cipher.getParameters(); 
     //iv = params.getParameterSpec(IvParameterSpec.class).getIV(); 
     encrypted = cipher.doFinal(text); 

    } 
    catch(Exception e) 
    { 
     e.printStackTrace(); 
    } 
    finally 
    { 
     newtext=new String(encrypted); 
     //System.out.println("ENCRYPTED "+newtext); 
     return newtext; 
    } 
} 
public String AESdecryptalgo(byte[] text) 
{ 
    try 
    { 

     cipher.init(Cipher.DECRYPT_MODE, skeySpec,spec); 
     original = cipher.doFinal(text); //Exception occurs here 
     originalString = new String(original); 

    } 
    catch(Exception e) 
    { 
     e.printStackTrace(); 
    } 
    finally 
    { 

     return originalString; 
    } 
} 
public static void main(String[] args) 
{ 
    AES a=new AES(); 
    String encrypt=a.AESencryptalgo("hello".getBytes()); 
    System.out.println(encrypt); 
    String decrypt=a.AESdecryptalgo(encrypt.getBytes()); 
    System.out.println(decrypt); 
} 

} `

+4

repost ... par le même utilisateur !: http://stackoverflow.com/questions/3180878/exception-in-aes-decryption-algorithm-in-java –

+2

@GregS - Ceci est en fait une exception différente, car il ne suit pas assez l'exemple fourni sur l'autre question. – erickson

+1

@erickson: Je suis à peu près sûr que c'est le même code. Et aucun ne jette aucune exception sur ma machine. Bien sûr, son exemple n'appelle pas la fonction où il dit que l'exception est en. –

Répondre

4

Vous devez fournir un vecteur d'initialisation lors de l'utilisation du mode CBC.

Lors du chiffrement, laissez le fournisseur choisir le IV pour vous:

… 
cipher.init(Cipher.ENCRYPT_MODE, key); 
AlgorithmParameters params = cipher.getParameters(); 
byte[] iv = params.getParameterSpec(IvParameterSpec.class).getIV(); 
… 

Plus tard, lors du déchiffrement, utilisez le même IV pour initialiser l'algorithme de chiffrement:

… 
IvParameterSpec spec = new IvParameterSpec(iv); 
cipher.init(Cipher.DECRYPT_MODE, key, spec); 
… 
+0

J'ai fait ce changement ... mais alors il lance une exception de pointeur nul à byte [] iv = params.getParameterSpec (IvParameterSpec.class). getIV(); – sparkle

+0

@ user372066 - Veuillez remplacer le code de votre question par votre version actuelle. – erickson

+0

j'ai remplacé le code – sparkle

1

Vous devez changer AESencryptalgo pour renvoyer byte[] plutôt qu'un String. C'est là que les ennuis commencent:

newtext = new String(encrypted); 
// System.out.println("ENCRYPTED "+newtext); 
return newtext; 

Après avoir modifié le type de retour de la méthode, vous devez faire le changement suivant:

//newtext = new String(encrypted); 
// System.out.println("ENCRYPTED "+newtext); 
//return newtext; 
return encrypted; 

Le problème est qu'un String est une séquence de caractères , alors que le texte crypté est une séquence de octets (pour un bon résumé de cette différence, voir The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)).

Lorsque vous essayez de construire un String à partir d'un tableau d'octets, Java essaie de son mieux pour convertir ces octets en caractères, en utilisant le jeu de caractères par défaut du système. Malheureusement, cette correspondance toujours fonctionne correctement (généralement lorsque les octets cryptés tombent en dehors du jeu de caractères ASCII). Vous ne jamais remarquer le problème quand vient le temps de votre nouveau décrypter String (qui ne parviendra pas à convertir correctement la séquence de caractères retour dans la séquence d'origine de octets).

Questions connexes