Comment chiffrer et déchiffrer un champs AES128 en Java

[ 4 ] Commentaires
Share

Le chiffrage/déchiffrage AES128 nécessite souvent d’être traité au niveau applicatif (et pas forcément uniquement au niveau base-de-donnée, dont le tuto est ici), donc voici quelques méthodes testées, qui fonctionnent, utilisant d’un côté une clef MD5 pour générer une clef de 128bits, et de l’autre l’algo AES pour chiffrer le tout. Notez au passage que, comme MD5 n’est pas bijectif (il existe plusieurs clefs de départ pour un seul résultat MD5), on peut considérer qu’il existera plusieurs clefs de départ, qui, générées au format MD5, fourniront la clefs final de hashage MD5.

Méthode de génération de la clef en 128bits (utilisation d’un hash MD5) :

Cette méthode prend une chaine de caractère en paramètre, et renvoie l’objet SecretKeySpec (qui est dans javax.crypto.spec.SecretKeySpec). Il utilise la méthode MessageDigest, avec l’algo MD5 pour générer le hash (NB : ça fonctionne aussi avec SHA). On met en paramètre du constructeur de SecretKeySpec l’algo qui sera utilisé, mais ça n’influe pas sur la création de la clef en elle-même. Donc on peut considérer que vous pourriez mettre ce que vous voulez à la place de AES_TRANSFORMATION_STRING.

    /**
     * Fournit une chaine de caractère en utilisant le hashage MD5
     *
     * @param toEncrypt : texte à chiffrer
     */
    private static SecretKeySpec getKey(String secretKey) {
        MessageDigest digest = null;
        try {
            digest = MessageDigest.getInstance("MD5");

        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }

        try {
            return new SecretKeySpec(digest.digest(new String(secretKey.getBytes(),"UTF8").getBytes()), AES_TRANSFORMATION_STRING);
        }
        catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            return null;
        }
    }

Méthode de chiffrage AES128 :

Là on utilise l’objet Cipher, auquel on fournit la clef de chiffrage (générée par le getKey() ci-dessus), ainsi que l’algo, et enfin le texte à chiffrer avec l’encodage de celui-ci (ici : « ISO-8859-1 »). ON remarque que c’est la méthode doFinal qui sort la chaine de bytes chiffrés. Notez enfin que l’encryptage se fait car on a initialisé Cipher avec Cipher.ENCRYPT_MODE.

private static final String AES_TRANSFORMATION_STRING = "AES";

    /**
     * Chiffre une chaine de caractère en utilisant l'algo AES128
     * @param toEncrypt : texte à chiffrer
     */
    public static String encryptAES(String toEncrypt) {
        String encrypted = null;
        try {
           // Instantiate the cipher
           Cipher cipher = Cipher.getInstance(AES_TRANSFORMATION_STRING);
           cipher.init(Cipher.ENCRYPT_MODE, getKey());
           // Récupère la clé secrète
            byte[] cipherText = cipher.doFinal(toEncrypt.getBytes("ISO-8859-1"));
            encrypted = new String(cipherText);
        }
        catch (Exception e) {
            System.out.println("Impossible to encrypt with AES algorithm: string=(" + toEncrypt + ")");
        }
        return encrypted;
    }

Méthode de déchiffrage du contenu AES128 :

Pour notre exemple, on déchiffre avec la clef, bien sûr, sauf qu’on met Cipher.DECRYPT_MODE dans l’initialisation du Cipher.

    /**
     * Dechiffre une chaine de caractère en utilisant l'algo AES128
     * @param toDecrypt
     */
    public static String decryptAES(String toDecrypt, String secretKey) {
        String decrypted = null;
        try {
            // Instantiate the cipher
            Cipher cipher = Cipher.getInstance(AES_TRANSFORMATION_STRING);
            cipher.init(Cipher.DECRYPT_MODE, getKey(secretKey));
            byte[] original = cipher.doFinal(toDecrypt.getBytes("ISO-8859-15"));
            return new String(original);
        }
        catch (Exception e) {
            e.printStackTrace();
            System.out.println("Impossible to decrypt with AES algorithm: string=(" + toDecrypt + ") message=(" + e.getMessage() + ")");
        }
        return decrypted;
    }

Rappelez vous bien que le Java manipule ici des byte[] et non des String.

Si vous voyez une erreur dans le code donnez ici, n’hésitez pas à la faire remarquer dans les commentaires !

Voilà voilà !

Vous serez peut-être intéressé :

4 commentaires sur ce billet

  1. seb dit :

    bonjour j’ai testé le code mais j ai cette erreur

    javax.crypto.BadPaddingException: Given final block not properly padded

    private static SecretKeySpec getKey(String secretKey) {
    MessageDigest digest = null;
    try {
    digest = MessageDigest.getInstance("MD5");

    } catch (NoSuchAlgorithmException e) {
    throw new RuntimeException(e);
    }

    try {
    return new SecretKeySpec(digest.digest(new String(secretKey.getBytes(),"UTF8").getBytes()), AES_TRANSFORMATION_STRING);
    }
    catch (UnsupportedEncodingException e) {
    e.printStackTrace();
    return null;
    }
    }

    public static String decryptAES(String toDecrypt, String secretKey) {
    String decrypted = null;
    try {
    // Instantiate the cipher
    Cipher cipher = Cipher.getInstance(AES_TRANSFORMATION_STRING);
    cipher.init(Cipher.DECRYPT_MODE, getKey(secretKey));
    byte[] original = cipher.doFinal(toDecrypt.getBytes("ISO-8859-1"));

    StringBuilder hashString = new StringBuilder();
    for (int i = 0; i < original.length; i++)
    {
    String hex = Integer.toHexString(original[i]);
    if (hex.length() == 1) {
    hashString.append('0');
    hashString.append(hex.charAt(hex.length() - 1));
    }else{hashString.append(hex.substring(hex.length() - 2));}
    }

    return hashString.toString();
    }
    catch (Exception e) {
    e.printStackTrace();
    System.out.println("Impossible to decrypt with AES algorithm: string=(" + toDecrypt + ") message=(" + e.getMessage() + ")");
    }
    return decrypted;
    }

    et l appel de la fonction

    System.out.println(decryptAES(fieldPass.getText(), fieldPass.getText()));

    le fieldPass.getText c’est le String du password en MD5 a decrypter

    RépondreRépondre
  2. Louis dit :

    @seb: Heu, je me note qu’il faut que je regarde ça, je reviendrai vers toi quand j’aurai trouvé. Si j’ai pas de réponse d’ici 2 semaines, hésites pas à reposter un commentaire pour me rappeler à l’ordre.

    RépondreRépondre
  3. Lama dit :

    @Louis: Bonjour, je sais que ça fait quelques années … mais ce code ne marche toujours pas, et je débute en java. Auriez vous une idée? Merci d’avance …

    RépondreRépondre
  4. Lama dit :

    @Louis: Hum, j’ai modifié le code de manière a conserver des byte[] entre le cryptage et le décryptage … et ça semble fonctionner … Dans tous les cas, débutant en java, je ne sais pas si ce langage permet de stocker des données binaires dans une String?

    RépondreRépondre

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *