AES: last block incomplete in decryption

Résolu
moi411 Messages postés 45 Date d'inscription   Statut Membre Dernière intervention   -  
moi411 Messages postés 45 Date d'inscription   Statut Membre Dernière intervention   -
Bonjour,
J'aimerais tester le cryptage/décryptage AES sur un appareil android.
J'ai fait des recherches et j'ai trouvé une solution pour crypter.
Le décryptage, me renvoie une exception: last block incomplete in decryption.

Les fonctions:

//crypter
public byte[] encrypt(byte[] raw, byte[] clear) throws Exception
{
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(clear);
return encrypted;
}

//décypter
public byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception
{
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] decrypted = cipher.doFinal(encrypted);
return decrypted;
}

//utiliser le cryptage dans l'application.
public String AES(String text, boolean crypter) //si true, on crypte sinon on décrypte
{
String finalCrypt = null;
byte[] encryptedData = null;
byte[] decryptedData = null;

try
{
byte[] b = text.getBytes();

byte[] keyStart = (editTextPassword.getText().toString()).getBytes();
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
sr.setSeed(keyStart);
kgen.init(256, sr);
SecretKey skey = kgen.generateKey();
byte[] key = skey.getEncoded();

if(crypter == true)
{
encryptedData = aes.encrypt(key, b);
finalCrypt = Base64.encodeToString(encryptedData,Base64.NO_WRAP);
}
else
{
decryptedData = aes.decrypt(key, b);
finalCrypt = new String(decryptedData);
}
}
catch(Exception e)
{
messageBoxPerso("exception\n\n" + e.getMessage());
//la fameuse exception!
}

return finalCrypt;
}


dernière information: Si j'utilise le cryptage et le décryptage dans la même fonction, sans aucune action entre les deux, je n'ai aucun problème (mais niveau utilité c'est 0!!!)
Je m'explique:

 try
{
AESCrypt aes = new AESCrypt();
String test = "My text.";
byte[] b = test.getBytes();

byte[] keyStart = "Une clef au hasard".getBytes();
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
sr.setSeed(keyStart);
kgen.init(256, sr);
SecretKey skey = kgen.generateKey();
byte[] key = skey.getEncoded();

// encrypt
byte[] encryptedData = aes.encrypt(key, b);
// decrypt
byte[] decryptedData = aes.decrypt(key, encryptedData);

//le cryptage et le décryptage sont fait à la suite
messageBoxPerso("Crypt: " + Base64.encodeToString(encryptedData,Base64.NO_WRAP) + "\nDecrypt: " + new String(decryptedData));
}
catch(Exception e)
{
messageBoxPerso("exception: " + e.getMessage());
}


Merci à ceux qui auront une idée!
A bientôt.



--

7 réponses

  1. BunoCS Messages postés 5036 Date d'inscription   Statut Modérateur Dernière intervention   3 931
     
    Hello,

    As-tu testé la validité de tes chaines en entrée de la decryption par exemple? N'y a-t-il pas des caractères farfelus?
    0
  2. moi411 Messages postés 45 Date d'inscription   Statut Membre Dernière intervention   2
     
    Re,
    Alors effectivement j'ai des caractères un peu bizarre que j'arrive à "voir" grâce à java.util.Arrays.toString(a.getBytes()). Apparemment se sont des espaces mais j'arrive à les supprimer en utilisant le paramètre "Base64.NO_WRAP" lors du cryptage...
    En dehors de ça je ne vois rien de spécial!

    Voilà je te remercie!
    --
    0
  3. BunoCS Messages postés 5036 Date d'inscription   Statut Modérateur Dernière intervention   3 931
     
    Des espaces à l'intérieur de la chaine? Bizarre...
    Si c'est des espaces aux extrémités, tu peux utiliser la fonction trim() de String.
    0
    1. moi411 Messages postés 45 Date d'inscription   Statut Membre Dernière intervention   2
       
      Re,
      Alors effectivement je n'avais pas pensé à la fonction trim (honte à moi!)...
      Sinon le cryptage et le décryptage fonctionnent si je n'enregistre pas les chaines (dans un fichier par exemple).
      Par contre si je crypte un mot et que j'enregistre ce cryptage dans un fichier, lors du décryptage j'obtiens l'exception: last block incomplete in decryption!

      pour enregistrer:

      public void fichierAjouter(String valeur)
      {
      valeur = valeur + System.getProperty("line.separator");
      try
      {
      FileWriter writer = new FileWriter("fichier.txt", true);
      writer.write(valeur, 0, valeur.length());
      writer.close();
      }
      catch(IOException exc)
      {
      messageBoxPerso("Problème avec le fichier!");
      }
      }


      En attendant je te remercie ! Je pense que je n'ai rien oublié!
      0
      1. BunoCS Messages postés 5036 Date d'inscription   Statut Modérateur Dernière intervention   3 931 > moi411 Messages postés 45 Date d'inscription   Statut Membre Dernière intervention  
         
        L'écriture dans un fichier rajoute des caractères, EOF notamment (End Of File).
        Une fois que tu as lu le fichier, regarde la chaine reçue en debug et compare avec ce que tu y avais écrit pour voir les différences.
        0
  4. Vous n’avez pas trouvé la réponse que vous recherchez ?

    Posez votre question
  5. moi411 Messages postés 45 Date d'inscription   Statut Membre Dernière intervention   2
     
    Donc j'ai bien testé à plusieurs endroits de mes fonctions et mes chaines sont bien identiques à chaque fois... En revanche j'ai toujours la même erreur au même endroit...
    Dans la fonction decrypt à la ligne:
    byte[] decrypted = cipher.doFinal(encrypted);

    A bientôt!
    --
    0
  6. moi411 Messages postés 45 Date d'inscription   Statut Membre Dernière intervention   2
     
    Bonjour,
    Petite modification et évidemment nouvelle question. Juste une!!!
    Tout d'abord le code:

    //les variables utilisées pour lier l'activity au code
        private EditText editTextClef;              //la clef de 32 caractères
        private EditText editTextPassword;      //le mot à crypter
        private TextView textViewCrypte;        //le résultat du cryptage
        private TextView textViewDecrypte;     //le résultat du décryptage
        private Button buttonCrypter;              //bouton pour crypter
        private Button buttonDecrypter;           //bouton pour décrypter
    
    
        //utilisées pour le cryptage / decryptage
    
        private String password;          //la clef
        private byte[] ivBytes;
        private static String salt;
        private int pswdIterations = 65536;
        private int keySize = 256;
    
    
    //une fonction pour remplir la variable salt
    public String genererSalt()
        {
            byte bytes[] = new byte[]
            {
                0x01, 0x05, 0x07, 0x08, 0x08, 0x02, 0x04, 0x09
            };
            String s = new String(bytes);
            return s;
        }
    
    
    @override
    protected void  onCreate etc.{...
    
    password  = editTextClef.getText().toString();
    
    
    //un bouton qui va crypter et afficher le résultat dans un textView
    buttonCrypter.setOnClickListener(new View.OnClickListener()
            {
                @Override
                public void onClick(View v)
                {
                    try
                    {
                        //remplir salt
                        salt = genererSalt();
                        byte[] saltBytes = salt.getBytes("iso-8859-1");
    
                        //derive the key
                        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
                        PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), saltBytes, pswdIterations, keySize);
                        SecretKey secretKey = factory.generateSecret(spec);
                        SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");
    
                        //encrypt the message
                        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
                        cipher.init(Cipher.ENCRYPT_MODE, secret);
                        AlgorithmParameters params = cipher.getParameters();
                        ivBytes = params.getParameterSpec(IvParameterSpec.class).getIV();
    
                        byte[] encryptedTextBytes = cipher.doFinal((editTextPassword.getText().toString()).getBytes("iso-8859-1"));
                        textViewCrypte.setText(new String(encryptedTextBytes, Charset.forName("iso-8859-1")));
    
                    }
                    catch(Exception e)
                    {
                        messageBoxPerso("Crypter:\n" + e.getMessage());
                    }
                }
            });
    
    
    //un bouton qui va décrypter et afficher le résultat dans un textView
      buttonDecrypter.setOnClickListener(new View.OnClickListener()
            {
                @Override
                public void onClick(View v)
                {
                    try
                    {
                        //get salt
                        salt = genererSalt();
                        byte[] saltBytes = salt.getBytes("iso-8859-1");
                        byte[] encryptedTextBytes = (textViewCrypte.getText().toString()).getBytes("iso-8859-1");
    
                        //derive the key
                        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
                        PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), saltBytes, pswdIterations, keySize);
    
                        SecretKey secretKey = factory.generateSecret(spec);
                        SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");
    
                        //decrypt the message
                        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
                        cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(ivBytes));
    
                        byte[] decryptedTextBytes = cipher.doFinal(encryptedTextBytes);
                        textViewDecrypte.setText(new String(decryptedTextBytes, Charset.forName("iso-8859-1")));
                    }
                    catch(Exception e)
                    {
                        messageBoxPerso("Decrypter:\n" + e.getMessage());
                    }
                }
            });


    Utilisée comme ça tout fonctionne correctement... Mais, sur tous les site où je suis allé, ils utilisent une classe, Base64, pour convertir en String...
    Et toutes mes erreurs comme "last block incomplete in decryption" viennent de l'utilisation de cette classe!

    D'ou ma question: Pourquoi?!?

    --
    0
  7. moi411 Messages postés 45 Date d'inscription   Statut Membre Dernière intervention   2
     
    Bonsoir,
    Donc effectivement maintenant, ça marche...
    Toujours pareil, c'est d'une logique imparable mais pas pensé!
    Si on termine le cryptage par un encodage "Base64" alors on débute le décryptage par le décodage "Bas64".
    Au cas où, je précise que sous android studio la classe Base64 est incluse.

    La solution définitive:

    //CRYPTAGE
                    try
                    {
                        //get salt
                        salt = generateSalt();
                        byte[] saltBytes = salt.getBytes("iso-8859-1");
    
                        //derive the key
                        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
                        PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), saltBytes, pswdIterations, keySize);
                        SecretKey secretKey = factory.generateSecret(spec);
                        SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");
    
                        //encrypt the message
                        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
                        cipher.init(Cipher.ENCRYPT_MODE, secret);
                        AlgorithmParameters params = cipher.getParameters();
                        ivBytes = params.getParameterSpec(IvParameterSpec.class).getIV();
    
                        byte[] encryptedTextBytes = cipher.doFinal((editTextPassword.getText().toString()).getBytes("iso-8859-1"));
                        byte[] tmp = Base64.encode(encryptedTextBytes, Base64.NO_WRAP);
                        textViewCrypte.setText(new String(tmp, Charset.forName("iso-8859-1")));
                    }
                    catch(Exception e)
                    {
                        messageBoxPerso("Crypter:\n" + e.getMessage());
                    }
    
    
    
    //DECRYPTAGE
                    try
                    {
                        //get salt
                        salt = generateSalt();
                        byte[] saltBytes = salt.getBytes("iso-8859-1");
                        byte[] encryptedTextBytes = (textViewCrypte.getText().toString()).getBytes("iso-8859-1");
                        byte[] tmp = Base64.decode(encryptedTextBytes, Base64.NO_WRAP);
    
                        //derive the key
                        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
                        PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), saltBytes, pswdIterations, keySize);
    
                        SecretKey secretKey = factory.generateSecret(spec);
                        SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");
    
                        //decrypt the message
                        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
                        cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(ivBytes));
    
                        byte[] decryptedTextBytes = cipher.doFinal(tmp);
                        textViewDecrypte.setText(new String(decryptedTextBytes, Charset.forName("iso-8859-1")));
                    }
                    catch(Exception e)
                    {
                        messageBoxPerso("Decrypter:\n" + e.getMessage());
                    }
    


    Pour finir, je te remercie du coup de main!
    Bonne soirée.
    --
    0