Astuce Chiffrer et déchiffrer une chaîne en Java

Si vous avez besoin de chiffrer une chaîne de caractères en Java, vous pouvez utiliser ces deux méthodes :

/**
 * Chiffre la chaîne en argument en utilisant la clé fournie.
 * Ajoute le suffixe à la chaîne chiffrée puis convertit le tout en base64.
 * 
 * @param string Chaîne à chiffrer
 * @param keyString Clé de chiffrement
 * @param suffix Suffixe à ajouter à la chaîne (ex: la date au format yyyyMMdd)
 * @return la chaîne chiffrée + le suffixe, en base64
 * @throws RESTTechnicalException
 */
public static String encrypt(String string, String keyString, String suffix) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException {

    String encryptedB64String = null;

    // Chiffrement de la chaîne
    Key key = new SecretKeySpec(keyString.getBytes("UTF-8"), "Blowfish");
    Cipher cipher = Cipher.getInstance("Blowfish");
    cipher.init(Cipher.ENCRYPT_MODE, key);
    byte[] encryptedString = cipher.doFinal(string.getBytes("UTF-8"));

    // Ajout du suffixe
    encryptedString = JavaUtil.mergeArray(encryptedString, suffix.getBytes());

    // Encodage de la chaîne en base 64
    encryptedB64String = Base64.encodeBase64String(encryptedString);

    return encryptedB64String;
}

/**
 * Déchiffre la chaîne en argument en utilisant la clé fournie.
 * 
 * @param b64String Chaîne chiffrée + le suffixe, en base 64
 * @param keyString Clé de déchiffrement
 * @param suffix Suffixe à ajouter à la chaîne (ex: la date au format yyyyMMdd)
 * @return la chaîne déchiffrée
 * @throws RESTTechnicalException
 */
public static String decrypt(String b64String, String keyString, String suffix) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException {

    String decryptedString = null;

    // Décodage de la chaîne en base 64
    byte[] string = Base64.decodeBase64(b64String);

    // Suppression du suffixe
    string = JavaUtil.truncateArray(string, suffix.length());

    // Déchiffrement de la chaîne
    Key key         = new SecretKeySpec(keyString.getBytes("UTF-8"), "Blowfish");
    Cipher cipher     = Cipher.getInstance("Blowfish");
    cipher.init(Cipher.DECRYPT_MODE, key);
    decryptedString = new String(cipher.doFinal(string));

    return decryptedString;
}

Explications :

  • La chaîne est (dé)chiffrée grâce à la bibliothèque Cipher de Java, en utilisant la technique de chiffrement Blowfish.
  • Le suffixe en argument est ensuite concaténée à la chaîne chiffrée.
  • La chaîne résultante est finalement convertie en base64.

Remarques :

  • La clé de chiffrement ne doit pas excéder 12 caractères, ou des paramètres doivent être changés dans la JVM.
  • Ces méthodes utilisent la bibliothèque org.apache.commons.codec, qui n'est pas forcément disponible dans le JDK.
  • Le suffixe permet de gérer l'expiration du chiffrement. Par exemple, pour une validité de 24h, il suffit de passer la date au format yyyyMMdd en argument.
  • La conversion en base64 n'est pas indispensable mais permet d'obtenir une chaîne de caractères plus simple et exploitable dans une URL par exemple.
  • Le code des méthodes JavaUtil.truncateArray() et JavaUtil.mergeArray() est disponible ci-dessous :

    /**
     * Tronque le tableau de byte en arguments.
     * 
     * @param array Tableau à tronquer
     * @param maxSize Taille maximale du tableau à conserver
     * @return le tableau tronqué
     */
    public static byte[] truncateArray(byte[] array, int maxSize) {
    
        int newArraySize = Math.min(array.length, maxSize);
        byte[] newArray = new byte[newArraySize];
        System.arraycopy(array, 0, newArray, 0, maxSize);
    
        return newArray;
    }
    
    /**
     * Merge les deux tableaux en arguments.
     * 
     * @param first Premier tableau
     * @param second Second tableau
     * @return
     */
    public static byte[] mergeArray(byte[] first, byte[] second) {
    
        byte[] result = Arrays.copyOf(first, first.length + second.length);
        System.arraycopy(second, 0, result, first.length, second.length);
    
        return result;
    }