AES: last block incomplete in decryption

Résolu
moi411 Messages postés 179 Date d'inscription   Statut Membre Dernière intervention   -  
moi411 Messages postés 179 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

BunoCS Messages postés 15952 Date d'inscription   Statut Modérateur Dernière intervention   3 918
 
1
BunoCS Messages postés 15952 Date d'inscription   Statut Modérateur Dernière intervention   3 918
 
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
moi411 Messages postés 179 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
BunoCS Messages postés 15952 Date d'inscription   Statut Modérateur Dernière intervention   3 918
 
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
moi411 Messages postés 179 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
BunoCS Messages postés 15952 Date d'inscription   Statut Modérateur Dernière intervention   3 918 > moi411 Messages postés 179 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

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
moi411 Messages postés 179 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
moi411 Messages postés 179 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
moi411 Messages postés 179 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