Crypter le mot de passe dans les fichiers de configuration en Java
Le cryptage est le processus de transformation d’informations en clair en une forme illisible à l’aide d’un algorithme de cryptage combiné à un paramètre appelé clé de cryptage
. Le format illisible est souvent appelé format ciphertext
. Seuls ceux qui possèdent la clé de décryptage
peuvent décrypter les données et récupérer le texte brut d’origine.
Nous pouvons diviser le problème du chiffrement des mots de passe dans les fichiers de configuration en deux sous-tâches suivantes.
- Cryptez le mot de passe en clair qui se trouve dans le fichier.
- Décryptez le mot de passe crypté lu à partir du fichier.
Commençons par créer un fichier de configuration nommé fichier config.properties
au chemin src/conf/
.
password = TestPassword123
Maintenant, pour lire le fichier de configuration, instanciez la classe Properties
. Nous pouvons créer une instance de la classe FileInputStream
à l’aide de son constructeur. Il prend le chemin du fichier de configuration comme entrée. Maintenant, une instance de la classe de propriétés est utilisée pour charger les propriétés. Utilisez la méthode load
pour charger le fichier de propriétés dans la classe, et cela prend l’instance InputStreamReader
comme paramètre. Il lance IllegalArgumentException
si ce flux d’entrée contient une séquence d’échappement Unicode malformée et IOException
si une erreur est survenue lors de la lecture du flux d’entrée.
Une fois les propriétés chargées, utilisez la méthode getProperty()
pour rechercher la propriété avec la clé spécifiée dans la liste des propriétés. La méthode renvoie null
si elle ne parvient pas à trouver les propriétés. Placez une vérification externe pour gérer une telle situation et lancez IllegalArgumentException
si un mot de passe est trouvé nul dans le fichier.
salt
est créé avec n’importe quelle chaîne aléatoire à ajouter à la chaîne de mot de passe.
createSecretKey
est une méthode définie par l’utilisateur qui renvoie la clé SecretKeySpec
, et l’utilisation de la clé consiste à chiffrer et déchiffrer le mot de passe. Les méthodes encrypt
et decrypt
sont des méthodes static
définies par l’usage qui ont été données dans la classe Encryption
.
Voici l’exemple de code qui illustre la même chose.
package fileDataEncryption;
import static fileDataEncryption.Encryption.*;
import java.io.FileInputStream;
import java.util.Properties;
import javax.crypto.spec.SecretKeySpec;
public class ConfigFileEncryption {
public static void main(String[] args) throws Exception {
Properties properties = new Properties();
FileInputStream inputStream = new FileInputStream("src/conf/config.properties");
properties.load(inputStream);
String password = properties.getProperty("password");
if (password == null) {
throw new IllegalArgumentException("No such parameter present in config file");
}
byte[] salt = new String("12345678").getBytes();
int iterationCount = 40000;
int keyLength = 128;
SecretKeySpec key = createSecretKey(password.toCharArray(), salt, iterationCount, keyLength);
String originalPassword = password;
System.out.println("Original password: " + originalPassword);
String encryptedPassword = encrypt(originalPassword, key);
System.out.println("Encrypted password: " + encryptedPassword);
String decryptedPassword = decrypt(encryptedPassword, key);
System.out.println("Decrypted password: " + decryptedPassword);
}
}
Une description détaillée des méthodes définies par l’utilisateur dans la classe Encryption
se trouve ci-dessous.
- Le
createSecretKey
est une fonction qui prend des paramètres commepassword
,salt
,iterationCount
etkeyLength
.password
est le mot de passe réel dans le fichier de configuration. En cryptographie, unsalt
est une donnée aléatoire que nous utilisons comme entrée supplémentaire qui hache des données, un mot de passe ou une phrase de passe. L’utilisation desalts
consiste à sauvegarder les mots de passe dans le stockage. Nous utilisons la variableiterationCount
comme le nombre d’itérations qu’un algorithme doit prendre. Diminuer la valeur de la variable accélère le temps de démarrage et est donc utile pendant les tests, mais cela facilite également la tâche des attaquants par force brute. La variablekeyLength
est la longueur de la clé que nous devons finalement dériver. Lève l’exception levée à partir des méthodes utilisées. - La méthode
getInstance
parcourt la liste des fournisseurs de sécurité enregistrés, en commençant par le fournisseur le plus préféré. Il prend le nom standard de l’algorithme de clé secrète demandé et renvoie le nouvel objetSecretKeyFactory
. Il lanceNullPointerException
si l’algorithme spécifié est nul etNoSuchAlgorithmException
si aucun fournisseur ne prend en charge une implémentationSecretKeyFactorySpi
pour l’algorithme spécifié. PBEKeySpec
est un constructeur de classe qui prend un mot de passe, un sel, un nombre d’itérations et une longueur de clé à dériver pour générer desPBEKey
de chiffrements PBE de taille de clé variable. Il lanceNullPointerException
sisalt
estnull
etIllegalArgumentException
si salt est vide.generateSecret
génère un objetSecretKey
à partir de la spécification de clé fournie ou du matériel de clé. Il prend la spécification de la clé secrète. Il lanceInvalidKeySpecException
si la spécification donnée est inappropriée pour que cette fabrique de clés secrètes produise une valeur de clé classifiée.
Détails de la méthode encrypt
dans la classe Encryption
.
- La méthode
encrypt
prend deux paramètres, les données à crypter et la clé. Cette méthode lève des exceptions levées à partir des méthodes enfants qu’elle contient. - La méthode
getInstance
parcourt la liste des fournisseurs de sécurité enregistrés, en commençant par le fournisseur le plus préféré. Il prend le nom de la transformation, c’est-à-dire AES / CBC / PKCS5Padding. Il lanceNoSuchAlgorithmException
si un changement est nul, vide, dans un format invalide etNoSuchPaddingException
si le changement contient un schéma de remplissage qui n’est pas disponible. - La méthode
init
initialise leCipher
pour l’une des quatre opérations suivantes: cryptage, décryptage, encapsulation de clé ou déballage de clé, selon la valeur du mode de fonctionnement.ENCRYPT_MODE
dans notre cas. La méthode lanceUnsupportedOperationException
si le mode de fonctionnement n’est pas valide etInvalidKeyException
si la clé donnée est inappropriée. - Le
getParameters
renvoie les paramètres utilisés avec ce chiffrement. - Le
getParameterSpec
renvoie une spécification de l’objet paramètre. Le paramètreparamSpec
identifie la classe de spécification dans laquelle les paramètres doivent retourner. Par exemple, ce pourrait être leDSAParameterSpec.class
pour indiquer que les paramètres doivent retourner dans une instance de la classeDSAParameterSpec
. - La méthode
doFinal
crypte ou décrypte les données en une seule pièce de travail ou termine une opération en plusieurs parties. Les données sont chiffrées ou déchiffrées, selon la façon dont nous initialisons le chiffrement. base64Encode
est une méthode privée qui encode le tableau d’octets spécifié dans une chaîne en utilisant le schéma d’encodageBase64
. Les fonctions utilisées dans la méthodedecrypt
sont similaires à la méthode mentionnée ci-dessus. La seule différence est qu’ils se comportent différemment en fonction dumode
spécifié dans la fonction,DECRYPT_MODE
comme mode de fonctionnement.
package fileDataEncryption;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.AlgorithmParameters;
import java.security.GeneralSecurityException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
public class Encryption {
public static SecretKeySpec createSecretKey(char[] password, byte[] salt, int iterationCount,
int keyLength) throws NoSuchAlgorithmException, InvalidKeySpecException {
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512");
PBEKeySpec keySpec = new PBEKeySpec(password, salt, iterationCount, keyLength);
SecretKey keyTmp = keyFactory.generateSecret(keySpec);
return new SecretKeySpec(keyTmp.getEncoded(), "AES");
}
public static String encrypt(String dataToEncrypt, SecretKeySpec key)
throws GeneralSecurityException, UnsupportedEncodingException {
Cipher pbeCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
pbeCipher.init(Cipher.ENCRYPT_MODE, key);
AlgorithmParameters parameters = pbeCipher.getParameters();
IvParameterSpec ivParameterSpec = parameters.getParameterSpec(IvParameterSpec.class);
byte[] cryptoText = pbeCipher.doFinal(dataToEncrypt.getBytes("UTF-8"));
byte[] iv = ivParameterSpec.getIV();
return base64Encode(iv) + ":" + base64Encode(cryptoText);
}
private static String base64Encode(byte[] bytes) {
return Base64.getEncoder().encodeToString(bytes);
}
public static String decrypt(String string, SecretKeySpec key)
throws GeneralSecurityException, IOException {
String iv = string.split(":")[0];
String property = string.split(":")[1];
Cipher pbeCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
pbeCipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(base64Decode(iv)));
return new String(pbeCipher.doFinal(base64Decode(property)), "UTF-8");
}
private static byte[] base64Decode(String property) throws IOException {
return Base64.getDecoder().decode(property);
}
}
Vous trouverez ci-dessous la sortie du code écrit pour crypter et décrypter le mot de passe dans le fichier de configuration.
Original password: TestPassword123
Encrypted password: Hy7fbIwpyKgp0oileu+oLg==:WNRknMJz/8u8GmWlCZFPFA==
Decrypted password: TestPassword123
Rashmi is a professional Software Developer with hands on over varied tech stack. She has been working on Java, Springboot, Microservices, Typescript, MySQL, Graphql and more. She loves to spread knowledge via her writings. She is keen taking up new things and adopt in her career.
LinkedIn