IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
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

Contribuez Discussion :

Windev : Chiffrer une chaine en AES-256 depuis Java et la déchiffrer avec Windev, et inversement.


Sujet :

Contribuez

  1. #1
    Membre actif
    Inscrit en
    Août 2005
    Messages
    96
    Détails du profil
    Informations forums :
    Inscription : Août 2005
    Messages : 96
    Points : 205
    Points
    205
    Par défaut Windev : Chiffrer une chaine en AES-256 depuis Java et la déchiffrer avec Windev, et inversement.
    Voici un ensemble de méthodes permettant d'effectuer le chiffrement d'une chaine en AES-256 avec Java et d'effectuer le déchiffrement avec Windev, et inversement.

    L'idée est de voir comment rendre les méthodes de chiffrement interopérables entre les deux langages, ce qui n'est pas forcément évident au premier abord.

    La première étape consiste à générer une clé de chiffrement.

    Pour des raisons de sécurité, cette clé sera générée en hachant un mot de passe avec l'algo de hachage SHA-256.

    Ensuite, pour des raisons d'inter-compatibilité, cette clé sera encodée en base64.

    Génération de la clé de chiffrement en Windev :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    PROCÉDURE GenererCleSHA256_Base64(_sMotDePasse est une chaîne)
     
    LOCAL
    	buffCle		est un Buffer	//Clé de chiffrement
    	sCleBase64	est une chaîne	//Clé de chiffrement encodée en base64
     
    //Pour une meilleure sécurité, je vais générer la clé en hachant un mot de passe avec un algorithme de hachage de la famille SHA-1
    buffCle		= HashChaîne(HA_HMAC_SHA_256,_sMotDePasse)
    //Pour des raisons d’inter-compatibilité Windev / JAVA, j'encode le résultat du hachage en base64.
    sCleBase64	= Encode(buffCle,encodeBASE64)
     
    RENVOYER sCleBase64
    Génération de la clé de chiffrement en Java :

    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
    import java.security.NoSuchAlgorithmException;
    import java.security.spec.InvalidKeySpecException;
    import java.security.spec.KeySpec;
    import java.util.Base64;
    import javax.crypto.SecretKey;
    import javax.crypto.SecretKeyFactory;
    import javax.crypto.spec.PBEKeySpec;
     
    public String GenererCleSHA256_Base64(String _sMotDePasse,String _sSel) throws NoSuchAlgorithmException, InvalidKeySpecException
    {
    	SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
    	KeySpec spec = new PBEKeySpec(_sMotDePasse.toCharArray(),_sSel.getBytes(),65536,256);
    	SecretKey tmp = factory.generateSecret(spec);
    	String sCleBase64 = Base64.getEncoder().encodeToString(tmp.getEncoded());
    	return sCleBase64;
    }

    Dans un cas comme dans l'autre, les clés générées peuvent être utilisées indifférement pour chiffrer ou déchiffrer avec Java ou Windev.

    Je vais maintenant utiliser la clé pour chiffrer un message.

    Chiffrement avec Windev :

    Code : 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
    PROCÉDURE Chiffrer_AES256(LOCAL _sMessageAChiffrer est une chaîne,LOCAL _sCleBase64 est une chaîne)
     
    LOCAL
    	buffCle 				est un Buffer
    	buffMessageAChiffrer	est une Buffer	//Message en clair à chiffrer
    	buffContenuChiffre		est un Buffer	//Vecteur d'initialisation + message chiffrés
    //	bufIV					est un Buffer	//Partie chiffrée du vecteur d'initialisation
    //	bufDonnees				est un Buffer	//Partie chiffrée du message
    	sMessageChiffreBase64	est une chaîne
     
    //Je décode la clé depuis l'encode base64
    buffCle					= Décode(_sCleBase64,encodeBASE64)
    //Je passe le message d'un encodage ANSI à un encodage UTF-8
    buffMessageAChiffrer	= ChaîneVersUTF8(_sMessageAChiffrer)
    //Je chiffre le message à l'aide de la clé
    buffContenuChiffre		= CrypteStandard(buffMessageAChiffrer,buffCle,crypteAES256,crypteCBC,cryptePaddingPKCS)
    ////Récupérer la partie chiffrée du vecteur d'initialisation
    //bufIV					= buffContenuChiffre[[ À 16]]
    ////Récupérer la partie chiffrée des données
    //bufDonnees				= buffContenuChiffre[[16+1 À]]
    //J'encode les deux parties en base64
    sMessageChiffreBase64	= Encode(buffContenuChiffre,encodeBASE64)
     
    RENVOYER sMessageChiffreBase64
    Chiffrement avec Java :

    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
    import java.nio.charset.Charset;
    import java.security.InvalidAlgorithmParameterException;
    import java.security.InvalidKeyException;
    import java.security.NoSuchAlgorithmException;
    import java.security.SecureRandom;
    import java.util.Base64;
    import javax.crypto.BadPaddingException;
    import javax.crypto.Cipher;
    import javax.crypto.IllegalBlockSizeException;
    import javax.crypto.NoSuchPaddingException;
    import javax.crypto.spec.IvParameterSpec;
    import javax.crypto.spec.SecretKeySpec;
     
    public String Chiffrer_AES256(String _sMessageAChiffrer,String _sCleBase64) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException
    {
    	byte[] keyData = Base64.getDecoder().decode(_sCleBase64);
    	SecretKeySpec secretKey = new SecretKeySpec(keyData,"AES");
    	Cipher cipher = null;
    	cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
     
    	//Générer le vecteur d'initialisation sur 16 octets
    	int ivSize = 16;
    	byte[] iv = new byte[ivSize];
    	SecureRandom random = new SecureRandom();
    	random.nextBytes(iv);
    	IvParameterSpec ivspec = new IvParameterSpec(iv);
     
    	cipher.init(Cipher.ENCRYPT_MODE,secretKey,ivspec);
     
    	//On ajoute le vecteur d'initialisation, car Windev s'attend à ce que les 16 premiers octets de la chaine retournée contiennent le vecteur, lors du décryptage avec DecrypteStandard.
    	byte[] mess 				= _sMessageAChiffrer.getBytes(Charset.forName("UTF-8"));
    	byte[] encrypted 			= cipher.doFinal(mess);
    	byte[] encryptedIVAndText 	= new byte[ivSize + encrypted.length];
    	System.arraycopy(iv, 0, encryptedIVAndText, 0, ivSize);
    	System.arraycopy(encrypted, 0, encryptedIVAndText, ivSize, encrypted.length);
     
    	String sMessageChiffreBase64 = Base64.getEncoder().encodeToString(encryptedIVAndText);
     
    	return sMessageChiffreBase64;
    }

    Je récupère le message chiffré encodé en base64, que je peux déchiffrer de la même manière avec Windev ou Java :

    Déchiffrement avec Windev :

    Code : 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
    PROCÉDURE Dechiffrer_AES256(LOCAL _sMessageChiffreBase64 est une chaîne,LOCAL _sCleBase64 est une chaîne)
     
    LOCAL
    	buffCle					est un Buffer
    	buffMessageChiffre		est un Buffer//Message chiffré après décodage base64
    	buffMessageDechiffre	est un Buffer//Message déchiffré sous forme de buffer
    	sMessageDechiffre 		est une chaîne//Message déchiffré sous forme de chaine
     
    //Je décode la clé depuis l'encodage base64
    buffCle					= Décode(_sCleBase64,encodeBASE64)
    //je décode le message depuis l'encodage base64
    buffMessageChiffre		= Décode(_sMessageChiffreBase64,encodeBASE64)
    //je déchiffre le message à l'aide de la clé
    buffMessageDechiffre	= DécrypteStandard(buffMessageChiffre,buffCle,crypteAES256,crypteCBC,cryptePaddingPKCS)
    //Je passe le message d'un encodage UTF-8 à un encodage ANSI
    sMessageDechiffre		= UTF8VersChaîne(buffMessageDechiffre,alphabetAnsi)
     
    RENVOYER sMessageDechiffre
    Déchiffrement avec Java :

    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
    import java.nio.charset.Charset;
    import java.security.InvalidAlgorithmParameterException;
    import java.security.InvalidKeyException;
    import java.security.NoSuchAlgorithmException;
    import java.util.Base64;
    import javax.crypto.BadPaddingException;
    import javax.crypto.Cipher;
    import javax.crypto.IllegalBlockSizeException;
    import javax.crypto.NoSuchPaddingException;
    import javax.crypto.spec.IvParameterSpec;
    import javax.crypto.spec.SecretKeySpec;
     
    public String Dechiffrer_AES256(String _sMessageChiffreBase64,String _sCleBase64) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException
    {
    	byte[] keyData = Base64.getDecoder().decode(_sCleBase64);
    	SecretKeySpec secretKey = new SecretKeySpec(keyData,"AES");
    	Cipher cipher = null;
     
    	cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
     
    	int ivSize = 16;
     
    	byte[] encryptedIvTextBytes = Base64.getDecoder().decode(_sMessageChiffreBase64);
     
    	//Récupérer la partie chiffrée du vecteur d'initialisation
    	byte[] iv = new byte[ivSize];
    	System.arraycopy(encryptedIvTextBytes, 0, iv, 0, iv.length);
    	IvParameterSpec ivspec = new IvParameterSpec(iv);
     
    	//Récupérer la partie chiffrée des données
    	int encryptedSize = encryptedIvTextBytes.length - ivSize;
    	byte[] encryptedBytes = new byte[encryptedSize];
    	System.arraycopy(encryptedIvTextBytes, ivSize, encryptedBytes, 0, encryptedSize);
     
    	cipher.init(Cipher.DECRYPT_MODE,secretKey,ivspec);
     
    	byte[] decrypted = cipher.doFinal(encryptedBytes);
    	String sMessageDechiffre = new String(decrypted,Charset.forName("UTF-8"));
    	return sMessageDechiffre;
    }

    Voici un code Windev final de test :

    Code : 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
    //-------------------------------------------------------------
    //Création de la clé de chiffrement
     
    LOCAL
     
    	sCleBase64 est une chaîne//Clé de chiffrement encodée en base64
     
    sCleBase64 = GenererCleSHA256_Base64("MotDePasse")
     
    //-------------------------------------------------------------
    //Chiffrement Windev
     
    LOCAL
    	sMessageAChiffrer est une chaîne//Message en clair à chiffrer
    	sMessageChiffreBase64 est une chaîne	//Message chiffré encodé en base64
     
    sMessageAChiffrer		= "Ce message peut être chiffré avec Java et déchiffré avec Windev."
    sMessageChiffreBase64 	= Chiffrer_AES256(sMessageAChiffrer,sCleBase64)
     
    Info("Message chiffré : "+sMessageChiffreBase64)
     
    //-------------------------------------------------------------
    //Déchiffrement Windev
     
    LOCAL
    	sMessageDechiffre est une chaîne
     
    sMessageDechiffre = Dechiffrer_AES256(sMessageChiffreBase64,sCleBase64)
     
    Info("Message déchiffré : "+sMessageDechiffre)
    Et la classe Java :

    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 java.security.spec.InvalidKeySpecException;
    import java.security.spec.KeySpec;
    import java.util.Base64;
    import javax.crypto.SecretKey;
    import javax.crypto.SecretKeyFactory;
    import javax.crypto.spec.PBEKeySpec;
     
    import java.nio.charset.Charset;
    import java.security.InvalidAlgorithmParameterException;
    import java.security.InvalidKeyException;
    import java.security.SecureRandom;
    import javax.crypto.BadPaddingException;
    import javax.crypto.Cipher;
    import javax.crypto.IllegalBlockSizeException;
    import javax.crypto.NoSuchPaddingException;
    import javax.crypto.spec.IvParameterSpec;
    import javax.crypto.spec.SecretKeySpec;
     
    public class AES256 {
     
    	public String GenererCleSHA256_Base64(String _sMotDePasse,String _sSel) throws NoSuchAlgorithmException, InvalidKeySpecException
    	{
    		SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
    		KeySpec spec = new PBEKeySpec(_sMotDePasse.toCharArray(),_sSel.getBytes(),65536,256);
    		SecretKey tmp = factory.generateSecret(spec);
    		String sCleBase64 = Base64.getEncoder().encodeToString(tmp.getEncoded());
    		return sCleBase64;
    	}
     
    	public String Chiffrer_AES256(String _sMessageAChiffrer,String _sCleBase64) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException
    	{
    		byte[] keyData = Base64.getDecoder().decode(_sCleBase64);
    		SecretKeySpec secretKey = new SecretKeySpec(keyData,"AES");
    		Cipher cipher = null;
    		cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
     
    		//Générer le vecteur d'initialisation sur 16 octets
    		int ivSize = 16;
    		byte[] iv = new byte[ivSize];
    		SecureRandom random = new SecureRandom();
    		random.nextBytes(iv);
    		IvParameterSpec ivspec = new IvParameterSpec(iv);
     
    		cipher.init(Cipher.ENCRYPT_MODE,secretKey,ivspec);
     
    		//On ajoute le vecteur d'initialisation, car Windev s'attend à ce que les 16 premiers octets de la chaine retournée contiennent le vecteur, lors du décryptage avec DecrypteStandard.
    		byte[] mess 				= _sMessageAChiffrer.getBytes(Charset.forName("UTF-8"));
    		byte[] encrypted 			= cipher.doFinal(mess);
    		byte[] encryptedIVAndText 	= new byte[ivSize + encrypted.length];
    		System.arraycopy(iv, 0, encryptedIVAndText, 0, ivSize);
    		System.arraycopy(encrypted, 0, encryptedIVAndText, ivSize, encrypted.length);
     
    		String sMessageChiffreBase64 = Base64.getEncoder().encodeToString(encryptedIVAndText);
     
    		return sMessageChiffreBase64;
    	}
     
    	public String Dechiffrer_AES256(String _sMessageChiffreBase64,String _sCleBase64) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException
    	{
    		byte[] keyData = Base64.getDecoder().decode(_sCleBase64);
    		SecretKeySpec secretKey = new SecretKeySpec(keyData,"AES");
    		Cipher cipher = null;
     
    		cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
     
    		int ivSize = 16;
     
    		byte[] encryptedIvTextBytes = Base64.getDecoder().decode(_sMessageChiffreBase64);
     
    		//Récupérer la partie chiffrée du vecteur d'initialisation
    		byte[] iv = new byte[ivSize];
    		System.arraycopy(encryptedIvTextBytes, 0, iv, 0, iv.length);
    		IvParameterSpec ivspec = new IvParameterSpec(iv);
     
    		//Récupérer la partie chiffrée des données
    		int encryptedSize = encryptedIvTextBytes.length - ivSize;
    		byte[] encryptedBytes = new byte[encryptedSize];
    		System.arraycopy(encryptedIvTextBytes, ivSize, encryptedBytes, 0, encryptedSize);
     
    		cipher.init(Cipher.DECRYPT_MODE,secretKey,ivspec);
     
    		byte[] decrypted = cipher.doFinal(encryptedBytes);
    		String sMessageDechiffre = new String(decrypted,Charset.forName("UTF-8"));
    		return sMessageDechiffre;
    	}
     
     
    }

    Voilà

  2. #2
    Futur Membre du Club
    Inscrit en
    Novembre 2007
    Messages
    2
    Détails du profil
    Informations forums :
    Inscription : Novembre 2007
    Messages : 2
    Points : 7
    Points
    7
    Par défaut
    Super intéressant comme tuto.

    Mais il y a un argument de plus entre Windev et Java pour la génération de la clé : Le sel.

    Quelle doit être sa valeur ?

Discussions similaires

  1. Extinction d'une machine sur le LAN depuis Java
    Par junior222 dans le forum Général Java
    Réponses: 14
    Dernier message: 11/08/2014, 19h11
  2. Raccourcir et chiffrer une chaine de caractères
    Par vnk600 dans le forum Langage
    Réponses: 4
    Dernier message: 16/07/2010, 21h27
  3. Réponses: 2
    Dernier message: 22/08/2009, 17h09
  4. chiffrer une chaine de caractère
    Par zulkifli dans le forum Langage
    Réponses: 2
    Dernier message: 29/08/2007, 14h59
  5. [débutant]lancement d'une commande Unix ou LInux depuis Java
    Par msiramy dans le forum API standards et tierces
    Réponses: 6
    Dernier message: 30/09/2005, 18h10

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