142 votes

Crypter le mot de passe dans les fichiers de configuration ? (Java)

J'ai un programme qui lit les informations du serveur à partir d'un fichier de configuration et je voudrais crypter le mot de passe dans cette configuration qui peut être lu par mon programme et décrypté.

Exigences :

  • Cryptage du mot de passe en texte clair à stocker dans le fichier
  • Décryptez le mot de passe crypté lu dans le fichier à partir de mon programme.

Avez-vous des recommandations sur la façon de procéder ? Je pensais écrire mon propre algorithme mais j'ai l'impression que ce serait terriblement dangereux.

Merci,
-Pete

189voto

Johannes Brodwall Points 3469

Un moyen simple d'y parvenir est d'utiliser le cryptage par mot de passe en Java. Cela vous permet de crypter et de décrypter un texte à l'aide d'un mot de passe.

Cela signifie essentiellement l'initialisation d'un javax.crypto.Cipher avec algorithme "PBEWithMD5AndDES" et obtenir une clé de javax.crypto.SecretKeyFactory avec le même algorithme.

Voici un exemple de code :

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.GeneralSecurityException;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

public class ProtectedConfigFile {

    private static final char[] PASSWORD = "enfldsgbnlsngdlksdsgm".toCharArray();
    private static final byte[] SALT = {
        (byte) 0xde, (byte) 0x33, (byte) 0x10, (byte) 0x12,
        (byte) 0xde, (byte) 0x33, (byte) 0x10, (byte) 0x12,
    };

    public static void main(String[] args) throws Exception {
        String originalPassword = "secret";
        System.out.println("Original password: " + originalPassword);
        String encryptedPassword = encrypt(originalPassword);
        System.out.println("Encrypted password: " + encryptedPassword);
        String decryptedPassword = decrypt(encryptedPassword);
        System.out.println("Decrypted password: " + decryptedPassword);
    }

    private static String encrypt(String property) throws GeneralSecurityException, UnsupportedEncodingException {
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
        SecretKey key = keyFactory.generateSecret(new PBEKeySpec(PASSWORD));
        Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");
        pbeCipher.init(Cipher.ENCRYPT_MODE, key, new PBEParameterSpec(SALT, 20));
        return base64Encode(pbeCipher.doFinal(property.getBytes("UTF-8")));
    }

    private static String base64Encode(byte[] bytes) {
        // NB: This class is internal, and you probably should use another impl
        return new BASE64Encoder().encode(bytes);
    }

    private static String decrypt(String property) throws GeneralSecurityException, IOException {
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
        SecretKey key = keyFactory.generateSecret(new PBEKeySpec(PASSWORD));
        Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");
        pbeCipher.init(Cipher.DECRYPT_MODE, key, new PBEParameterSpec(SALT, 20));
        return new String(pbeCipher.doFinal(base64Decode(property)), "UTF-8");
    }

    private static byte[] base64Decode(String property) throws IOException {
        // NB: This class is internal, and you probably should use another impl
        return new BASE64Decoder().decodeBuffer(property);
    }

}

Un problème subsiste : Où devez-vous stocker le mot de passe que vous utilisez pour crypter les mots de passe ? Vous pouvez le stocker dans le fichier source et l'obscurcir, mais il n'est pas trop difficile de le retrouver. Sinon, vous pouvez le donner comme propriété du système lorsque vous démarrez le processus Java ( -DpropertyProtectionPassword=... ).

Le même problème se pose si vous utilisez le KeyStore, qui est également protégé par un mot de passe. En gros, vous devrez avoir un mot de passe principal quelque part, et il est assez difficile à protéger.

22voto

Vérifiez jasypt qui est une bibliothèque offrant des capacités de cryptage de base avec un effort minimal.

20voto

JeeBee Points 11882

Oui, n'écrivez surtout pas votre propre algorithme. Java dispose de nombreuses API de cryptographie.

Si le système d'exploitation sur lequel vous vous installez dispose d'un keystore, vous pouvez l'utiliser pour stocker les clés cryptographiques dont vous aurez besoin pour crypter et décrypter les données sensibles de votre configuration ou d'autres fichiers.

18voto

oxbow_lakes Points 70013

Je pense que la meilleure approche est de s'assurer que votre fichier de configuration (contenant votre mot de passe) est uniquement accessible à un compte utilisateur spécifique . Par exemple, vous pouvez avoir un utilisateur spécifique à une application. appuser pour lequel seules les personnes de confiance ont le mot de passe (et auquel ils su à).

Ainsi, il n'y a pas de surcharge cryptographique gênante et vous disposez toujours d'un mot de passe sécurisé.

EDIT : Je suppose que vous n'exportez pas la configuration de votre application en dehors d'un environnement de confiance (ce qui n'a pas de sens, compte tenu de la question).

6voto

stolsvik Points 2049

Le point important, l'éléphant dans la pièce et tout ça, c'est que si votre application peut obtenir le mot de passe, alors un pirate ayant accès à la boîte peut aussi l'obtenir !

La seule façon de contourner ce problème est que l'application demande le "mot de passe principal" sur la console en utilisant l'entrée standard, et l'utilise ensuite pour décrypter les mots de passe stockés dans le fichier. Bien sûr, cela rend complètement impossible le lancement de l'application sans surveillance en même temps que le système d'exploitation au démarrage.

Cependant, même avec ce niveau d'inconvénient, si un pirate parvient à obtenir un accès Root (ou même simplement un accès en tant qu'utilisateur exécutant votre application), il pourrait vider la mémoire et y trouver le mot de passe.

La chose à faire est de ne pas laisser toute l'entreprise avoir accès au serveur de production (et donc aux mots de passe), et de s'assurer qu'il est impossible de craquer cette boîte !

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X