Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Sécurité Java Discussion :

Chiffrement/déchiffrement très simple


Sujet :

Sécurité Java

  1. #1
    Nouveau membre du Club
    Chiffrement/déchiffrement très simple
    Bonjour,

    Je cherche un fonctionnement ultra simple de chiffrement / déchiffrement de chaînes de caractères en Java.
    L'idée étant que mon appli doit accéder à une BDD dont les propriétés sont stockées dans un fichier db.properties. Seulement j'aimerais éviter que le mot de passe d'accès root à la base soit en clair dans ce fichier d'où mon besoin de chiffrement.

    J'avais dans l'idée de stocker en dur dans le code la clé, mettre à dispo des admins un petit programme java leur permettant de générer leur mot de passe chiffré qu'ils rentreraient dans le fichier db.properties et donc ensuite mon appli utiliserait une méthode de déchiffrement (qui utiliserait la même clé) pour ouvrir la connexion à la BDD avec les infos du fichier db.properties.

    Ci-dessous ma classe de tests. Pour les tests, j'ai laissé ma méthode de génération de la clé par contre à terme, je pensais figer la valeur de "key"

    Code java :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    import java.security.NoSuchAlgorithmException;
     
    import javax.crypto.Cipher;
    import javax.crypto.KeyGenerator;
    import javax.crypto.NoSuchPaddingException;
    import javax.crypto.SecretKey;
     
    import org.apache.log4j.Logger;
     
    public class AES {
     
    	private static Logger logger = Logger.getLogger(AES.class);
    	private static SecretKey key;
    	private static Cipher cipher;
     
    	private static final String AES_TRANSFORMATION_STRING = "AES";
     
    	private static void setKey() {
    		KeyGenerator keyGen;
    		logger.info("Generation d'une cle pour AES");
    		try {
    			keyGen = KeyGenerator.getInstance(AES_TRANSFORMATION_STRING);
    			key = keyGen.generateKey();
    			logger.info("cle (" + key.getAlgorithm() + "," + key.getFormat() + ") : " + key.getEncoded());
    			// Instantiate the cipher
    			cipher = Cipher.getInstance(AES_TRANSFORMATION_STRING);
    		} catch (NoSuchAlgorithmException e) {
    			// TODO Bloc catch généré automatiquement
    			e.printStackTrace();
    		} catch (NoSuchPaddingException e) {
    			// TODO Bloc catch généré automatiquement
    			e.printStackTrace();
    		}
    	}
     
    	/**
             * Chiffre une chaine de caractère en utilisant l'algo AES128
             * 
             * @param toEncrypt
             *            : texte à chiffrer
             */
    	public static String encryptAES(String toEncrypt) {
    		String encrypted = null;
    		if (key == null) setKey();
    		try {
    			cipher.init(Cipher.ENCRYPT_MODE, key);
    			// Récupère la clé secrète
    			byte[] cipherText = cipher.doFinal(toEncrypt.getBytes());
    			encrypted = new String(cipherText);
    		} catch (Exception e) {
    			logger.error("Impossible to encrypt with AES algorithm: string=(" + toEncrypt + ")");
    		}
    		return encrypted;
    	}
     
    	/**
             * Dechiffre une chaine de caractère en utilisant l'algo AES128
             * 
             * @param toDecrypt
             */
    	public static String decryptAES(String toDecrypt) {
    		String decrypted = null;
    		if (key == null) setKey();
    		try {
    			cipher.init(Cipher.DECRYPT_MODE, key);
    			byte[] original = cipher.doFinal(toDecrypt.getBytes());
    			return new String(original);
    		} catch (Exception e) {
    			e.printStackTrace();
    			logger.error("Impossible to decrypt \"" + toDecrypt + "\"" + " with AES algorithm");
    		}
    		return decrypted;
    	}
     
    	public static void main(String[] args) {
    		setKey();
    		String encryptedString1 = encryptAES("mdp");
    		String encryptedString2 = encryptAES("mdp");
    		String encryptedString3 = encryptAES("mdp");
    		String encryptedString4 = encryptAES("mdp");
    		String encryptedString5 = encryptAES("mdp");
    		logger.info(encryptedString1 + " : " + decryptAES(encryptedString1));
    		logger.info(encryptedString2 + " : " + decryptAES(encryptedString2));
    		logger.info(encryptedString3 + " : " + decryptAES(encryptedString3));
    		logger.info(encryptedString4 + " : " + decryptAES(encryptedString4));
    		logger.info(encryptedString5 + " : " + decryptAES(encryptedString5));
    	}
     
    }


    L'exécution de ce petit programme semble donner ce que je veux
    Code log :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    2014-12-09 18:02:24,816 [INFO ] (AES.java:setKey:22) Generation d'une cle pour AES
    2014-12-09 18:02:25,090 [INFO ] (AES.java:setKey:26) cle (AES,RAW) : [B@2d6a9952
    2014-12-09 18:02:25,111 [INFO ] (AES.java:main:82) ÿr2*C!â”Gž~& : mdp
    2014-12-09 18:02:25,111 [INFO ] (AES.java:main:83) ÿr2*C!â”Gž~& : mdp
    2014-12-09 18:02:25,111 [INFO ] (AES.java:main:84) ÿr2*C!â”Gž~& : mdp
    2014-12-09 18:02:25,111 [INFO ] (AES.java:main:85) ÿr2*C!â”Gž~& : mdp
    2014-12-09 18:02:25,111 [INFO ] (AES.java:main:86) ÿr2*C!â”Gž~& : mdp

    ... par contre je suis surpris, à chaque exécution les valeurs chiffrées changent et parfois j'ai l'erreur suivante :
    Code java :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    javax.crypto.BadPaddingException: Given final block not properly padded
    	at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:966)
    	at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:824)
    	at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:436)
    	at javax.crypto.Cipher.doFinal(Cipher.java:2121)
    	at com.osiris.chiffrement.AES.decryptAES(AES.java:68)
    	at com.osiris.chiffrement.AES.main(AES.java:88)


    Pourriez-vous m'expliquer ces comportements ?
    Auriez-vous une technique plus simple pour faire ce que je cherche à faire ?

    Merci pour votre aide.

  2. #2
    Modérateur

    Hello,

    # À chaque exécution les valeurs chiffrées changent :

    Ben oui, c'est un peu normal, puisqu'à chaque exécution tu génères une nouvelle clé de chiffrage aléatoire -_-°.

    # L'erreur javax.crypto.BadPaddingException :

    C'est parce que tu essaies de convertir des données chiffrées en String.
    Des données chiffrées c'est des octets arbitraire, ce ne sont pas des caractères. Tu ne peux pas les mettre dans une String et espérer que ça marche, il va y avoir corruption des données au moment du décodage octets -> caractères.
    Tu dois utiliser le byte[] que le Cipher te donne, pas le ranger dans une String "hop on le voit plus".
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  3. #3
    Nouveau membre du Club
    Citation Envoyé par thelvin Voir le message
    Citation Envoyé par OphyTe
    À chaque exécution les valeurs chiffrées changent
    Ben oui, c'est un peu normal, puisqu'à chaque exécution tu génères une nouvelle clé de chiffrage aléatoire -_-°.
    J'aurais dû préciser "pourtant la clef de chiffrage ne bouge pas elle !?!" ...

    Citation Envoyé par thelvin Voir le message
    Citation Envoyé par OphyTe
    L'erreur javax.crypto.BadPaddingException
    C'est parce que tu essaies de convertir des données chiffrées en String.
    Des données chiffrées c'est des octets arbitraire, ce ne sont pas des caractères. Tu ne peux pas les mettre dans une String et espérer que ça marche, il va y avoir corruption des données au moment du décodage octets -> caractères.
    Tu dois utiliser le byte[] que le Cipher te donne, pas le ranger dans une String "hop on le voit plus".
    Mais il me faut bien une représentation littéral de cette donnée chiffrée pour mon problème ! Qu'est-ce que je mets comme mot de passe chiffré dans mon db.properties si je ne peux pas convertir ce byte[] en String ? Et pourquoi dans mon exemple, il arrive bien à afficher régulièrement ce que j'attends ?

  4. #4
    Modérateur

    Ce message n'a pas pu être affiché car il comporte des erreurs.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  5. #5
    Expert éminent sénior
    Ha ben dites donc, c'est le soirée je fais n'importe quoi avec les byte[] aujourd'hui.

    Au delà de ton implémentation, je me pose trois question:

    1) En quoi encrypter dans le .properties rend le mdp plus sécurisé selon toi? Le sysadmin a quand même accès à la clé (via ton programme) et au fichier properties. Il est courant lorsque l'on fait tourner des applications système de laisser les clés en clair. Il faut juste configurer correctement les droits d'accès au fichier pour le limiter au personnel autorisé.
    2) Comment compte tu protéger la clé de cryptage
    3) pourquoi tu n'utilise pas des librairies déjà destinées à cela?
    David Delbecq Java developer chez HMS Industrial Networks AB.    LinkedIn | Google+

###raw>template_hook.ano_emploi###