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
    Inscrit en
    mars 2005
    Messages
    60
    Détails du profil
    Informations forums :
    Inscription : mars 2005
    Messages : 60
    Points : 33
    Points
    33
    Par défaut 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

    Profil pro
    Inscrit en
    septembre 2004
    Messages
    11 813
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : septembre 2004
    Messages : 11 813
    Points : 20 035
    Points
    20 035
    Par défaut
    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
    Inscrit en
    mars 2005
    Messages
    60
    Détails du profil
    Informations forums :
    Inscription : mars 2005
    Messages : 60
    Points : 33
    Points
    33
    Par défaut
    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

    Profil pro
    Inscrit en
    septembre 2004
    Messages
    11 813
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : septembre 2004
    Messages : 11 813
    Points : 20 035
    Points
    20 035
    Par défaut
    Citation Envoyé par OphyTe Voir le message
    J'aurais dû préciser "pourtant la clef de chiffrage ne bouge pas elle !?!" ...
    Ben si c'était le cas, ce serait ça ton vrai problème. Une plate-forme de crypto qui te sert toujours la même clé de chiffrage quand tu lui demandes d'en générer une nouvelle, ça me semble pas trop digne de confiance.

    Mais je me demande comment tu saurais si ta clé de chiffrage bouge ou pas. Pour rappel, key.getEncoded() renvoie un byte[], et les tableaux ne redéfinissent pas toString() de manière pertinente. Ça veut dire que si tu veux l'afficher, tu dois programmer toi-même son affichage, tu ne peux pas juste le concaténer à un message.

    Ce "[B@2d6a9952" n'est qu'un identifiant d'objet, et il n'est pas étonnant que lancer plusieurs fois le même programme le fasse générer à chaque fois des objets qui ont le même identifiant. Leur contenu étant, par contre, aléatoire, il change certainement d'une exécution à l'autre.

    Citation Envoyé par OphyTe Voir le message
    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 ?
    En général on l'encode en Base64 ou en hexadécimal. C'est bien un genre de conversion en String, mais surtout pas en faisant new String() sur le tableau de bytes. Il faut utiliser un encodeur de données binaires en texte.

    Citation Envoyé par OphyTe Voir le message
    Et pourquoi dans mon exemple, il arrive bien à afficher régulièrement ce que j'attends ?
    Dans le cas où tous les octets correspondent à des caractères valides, ce qui est assez courant avec le charset windows-1252, il n'y a pas corruption de données et ça va marcher. Le problème c'est que tu ne peux pas compter dessus.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  5. #5
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    avril 2007
    Messages
    25 461
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : avril 2007
    Messages : 25 461
    Points : 48 733
    Points
    48 733
    Par défaut
    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?

Discussions similaires

  1. Réponses: 14
    Dernier message: 20/09/2006, 21h07
  2. [lacncement application] très simple
    Par requin01 dans le forum Eclipse Java
    Réponses: 11
    Dernier message: 29/05/2006, 08h46
  3. [Tableaux] question très simple
    Par H-bil dans le forum Langage
    Réponses: 14
    Dernier message: 28/05/2006, 13h29
  4. [FLASH 8] Pour un Slide show très simple
    Par obatala dans le forum Flash
    Réponses: 2
    Dernier message: 04/04/2006, 16h34
  5. Application Web Client/Serveur très très simple
    Par n_tony dans le forum Langages de programmation
    Réponses: 2
    Dernier message: 07/03/2006, 14h29

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo