Kennwort in Konfigurationsdateien verschlüsseln in Java
Bei der Verschlüsselung werden Klartextinformationen mithilfe eines Verschlüsselungsalgorithmus in Kombination mit einem Parameter namens Verschlüsselungsschlüssel
in eine unlesbare Form umgewandelt. Das unlesbare Format wird häufig als ciphertext
-Format bezeichnet. Nur wer den Entschlüsselungsschlüssel
besitzt, kann die Daten entschlüsseln und den ursprünglichen Klartext wiederherstellen.
Wir können das Problem der Verschlüsselung von Passwörtern in Konfigurationsdateien in zwei folgende Unteraufgaben aufteilen.
- Verschlüsseln Sie das in der Datei enthaltene Klartextkennwort.
- Entschlüsseln Sie das aus der Datei eingelesene verschlüsselte Passwort.
Lassen Sie uns zuerst eine Konfigurationsdatei mit dem Namen config.properties
im Pfad src/conf/
erstellen.
password = TestPassword123
Um nun die Konfigurationsdatei zu lesen, instanziieren Sie die Klasse Properties
. Wir können eine Instanz der Klasse FileInputStream
mit ihrem Konstruktor erstellen. Es nimmt den Pfad der Konfigurationsdatei als Eingabe. Jetzt wird eine Instanz der Eigenschaftenklasse verwendet, um die Eigenschaften zu laden. Verwenden Sie die Methode load
, um die Eigenschaftendatei in die Klasse zu laden. Dabei wird die Instanz InputStreamReader
als Parameter verwendet. Es wird IllegalArgumentException
ausgelöst, wenn dieser Eingabestream eine fehlerhafte Unicode-Escape-Sequenz enthält, und IOException
, wenn beim Lesen aus dem Eingabestream ein Fehler aufgetreten ist.
Verwenden Sie nach dem erfolgreichen Laden der Eigenschaften die Methode getProperty()
, um nach der Eigenschaft mit dem angegebenen Schlüssel in der Eigenschaftenliste zu suchen. Die Methode gibt null
zurück, wenn die Eigenschaften nicht gefunden werden können. Führen Sie eine externe Prüfung durch, um eine solche Situation zu behandeln, und lösen Sie IllegalArgumentException
aus, wenn in der Datei ein Kennwort gefunden wird, das null ist.
salt
wird mit einer beliebigen zufälligen Zeichenkette erstellt, die der KennwortZeichenkette hinzugefügt wird.
createSecretKey
ist eine benutzerdefinierte Methode, die den SecretKeySpec
-Schlüssel zurückgibt. Mit dem Schlüssel wird das Kennwort verschlüsselt und entschlüsselt. Die Methoden encrypt
und decrypt
sind benutzerdefinierte static
Methoden, die in der Klasse Encryption
angegeben wurden.
Unten finden Sie den Beispielcode, der dasselbe demonstriert.
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);
}
}
Eine detaillierte Beschreibung der benutzerdefinierten Methoden in der Klasse Verschlüsselung
finden Sie unten.
- Der
createSecretKey
ist eine Funktion, die Parameter wiepassword
,salt
,iterationCount
undkeyLength
akzeptiert.password
ist das eigentliche Passwort in der Konfigurationsdatei. In der Kryptographie sind einsalt
zufällige Daten, die wir als zusätzliche Eingabe verwenden, die Daten, ein Kennwort oder eine Passphrase hasht. Die Verwendung vonsalts
dient zum Schutz von Passwörtern bei der Lagerung. Wir verwenden die VariableiterationCount
als Anzahl der Iterationen, die ein Algorithmus ausführen soll. Das Verringern des Werts der Variablen beschleunigt die Startzeit und ist daher beim Testen hilfreich, erleichtert aber auch Brute-Force-Angreifern. Die VariablekeyLength
ist die Länge des Schlüssels, den wir letztendlich ableiten müssen. Löst die Ausnahme aus, die von den verwendeten Methoden ausgelöst wurde. - Die Methode
getInstance
durchläuft die Liste der registrierten Sicherheitsanbieter, beginnend mit dem am meisten bevorzugten Anbieter. Es nimmt den Standardnamen des angeforderten Secret-Key-Algorithmus und gibt das neue ObjektSecretKeyFactory
zurück. Es wirdNullPointerException
ausgelöst, wenn der angegebene Algorithmus null ist, undNoSuchAlgorithmException
, wenn kein Anbieter eineSecretKeyFactorySpi
-Implementierung für den angegebenen Algorithmus unterstützt. PBEKeySpec
ist ein Klassenkonstruktor, der ein Kennwort, einen Salt, eine Iterationszahl und eine abzuleitende Schlüssellänge zum Generieren vonPBEKey
von PBE-Chiffren mit variabler Schlüsselgröße verwendet. Es wirdNullPointerException
ausgelöst, wennsalt
null
ist, undIllegalArgumentException
, wenn salt leer ist.generateSecret
generiert aus der angegebenen Schlüsselspezifikation oder dem Schlüsselmaterial einSecretKey
-Objekt. Es braucht die Angabe des geheimen Schlüssels. Es wirdInvalidKeySpecException
ausgelöst, wenn die angegebene Spezifikation für diese Fabrik mit geheimen Schlüsseln nicht geeignet ist, um einen klassifizierten Schlüsselwert zu erzeugen.
Details zur Methode encrypt
in der Klasse Encryption
.
- Die Methode
encrypt
verwendet zwei Parameter, die zu verschlüsselnden Daten und den Schlüssel. Diese Methode löst Ausnahmen aus, die von untergeordneten Methoden ausgelöst werden. - Die Methode
getInstance
durchläuft die Liste der registrierten Sicherheitsanbieter, beginnend mit dem am meisten bevorzugten Anbieter. Es wird der Name der Transformation verwendet, dh AES / CBC / PKCS5Padding. Es wirdNoSuchAlgorithmException
ausgelöst, wenn eine Änderung null und leer in einem ungültigen Format ist, undNoSuchPaddingException
, wenn die Änderung ein Auffüllschema enthält, das nicht verfügbar ist. - Die Methode
init
initialisiert dieVerschlüsselung
für eine der folgenden vier Operationen: Verschlüsselung, Entschlüsselung, Schlüsselumbruch oder Schlüsselentpackung, abhängig vom Wert des Betriebsmodus.ENCRYPT_MODE
in unserem Fall. Die Methode löstUnsupportedOperationException
aus, wenn der Betriebsmodus ungültig ist, undInvalidKeyException
, wenn der angegebene Schlüssel unangemessen ist. - Der
getParameters
gibt die mit dieser Chiffre verwendeten Parameter zurück. - Die
getParameterSpec
gibt eine Spezifikation des Parameterobjekts zurück. Der ParameterparamSpec
gibt die Spezifikationsklasse an, in der die Parameter zurückgegeben werden müssen. Beispielsweise könnte es dieDSAParameterSpec.class
sein, die angibt, dass die Parameter in einer Instanz der KlasseDSAParameterSpec
zurückgegeben werden müssen. - Die Methode
doFinal
verschlüsselt oder entschlüsselt Daten in einer einteiligen Arbeit oder beendet eine mehrteilige Operation. Die Daten werden verschlüsselt oder entschlüsselt, je nachdem, wie wir die Verschlüsselung initialisieren. base64Encode
ist eine private Methode, die das angegebene Bytearray mithilfe des CodierungsschemasBase64
in eine Zeichenkette codiert. Die in der Methodedecrypt
verwendeten Funktionen ähneln der oben genannten Methode. Der einzige Unterschied besteht darin, dass sie sich je nach dem in der FunktionDECRYPT_MODE
als Betriebsmodus angegebenenModus
unterschiedlich verhalten.
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);
}
}
Unten sehen Sie die Ausgabe des Codes, der zum Ver- und Entschlüsseln des Kennworts in der Konfigurationsdatei geschrieben wurde.
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