Crittografa la password nei file di configurazione in Java
La crittografia è il processo di trasformazione delle informazioni di testo in chiaro in una forma illeggibile utilizzando un algoritmo di crittografia combinato con un parametro chiamato “chiave di crittografia”. Il formato illeggibile è spesso noto come formato ciphertext
. Solo chi possiede la chiave di decrittazione
può decrittare i dati e recuperare il testo in chiaro originale.
Possiamo suddividere il problema della crittografia delle password nei file di configurazione in due sotto-attività seguenti.
- Crittografare la password in testo normale presente nel file.
- Decrittografare la password crittografata letta dal file.
Creiamo prima un file di configurazione chiamato file config.properties
nel percorso src/conf/
.
password = TestPassword123
Ora per leggere il file di configurazione, istanziare la classe Properties
. Possiamo creare un’istanza della classe FileInputStream
usando il suo costruttore. Prende il percorso del file di configurazione come input. Ora un’istanza della classe properties viene utilizzata per caricare le proprietà. Usa il metodo load
per caricare il file delle proprietà nella classe, e questo prende l’istanza InputStreamReader
come parametro. Genera IllegalArgumentException
se questo flusso di input contiene una sequenza di escape Unicode non valida e IOException
se si è verificato un errore durante la lettura dal flusso di input.
Una volta caricate con successo le proprietà, utilizzare il metodo getProperty()
per cercare la proprietà con la chiave specificata nella lista delle proprietà. Il metodo restituisce null
se non è in grado di trovare le proprietà. Posiziona un controllo esterno per gestire una situazione del genere e lancia IllegalArgumentException
se una password viene trovata nulla dal file.
salt
viene creato con qualsiasi stringa casuale da aggiungere alla stringa della password.
createSecretKey
è un metodo definito dall’utente che restituisce la chiave SecretKeySpec
e l’uso della chiave è crittografare e decrittografare la password. I metodi encrypt
e decrypt
sono metodi statici
definiti usati che sono stati forniti, nella classe Encryption
.
Di seguito è il codice di esempio che dimostra lo stesso.
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);
}
}
Di seguito viene fornita una descrizione dettagliata dei metodi definiti dall’utente nella classe Encryption
.
createSecretKey
è una funzione che accetta parametri comepassword
,salt
,iterationCount
ekeyLength
.password
è la password effettiva nel file di configurazione. In crittografia, unsalt
è un dato casuale che utilizziamo come input aggiuntivo che esegue l’hashing dei dati, una password o una passphrase. L’uso deisalts
serve a salvaguardare le password in deposito. Usiamo la variabileiterationCount
come numero di iterazioni che un algoritmo dovrebbe prendere. La diminuzione del valore della variabile accelera il tempo di avvio e quindi è utile durante i test, ma rende anche più facile per gli attaccanti di forza bruta. La variabilekeyLength
è la lunghezza della chiave che alla fine dobbiamo derivare. Genera l’eccezione generata dai metodi utilizzati.- Il metodo
getInstance
attraversa la lista dei provider di sicurezza registrati, a partire dal provider più preferito. Prende il nome standard dell’algoritmo della chiave segreta richiesta e restituisce il nuovo oggettoSecretKeyFactory
. LanciaNullPointerException
se l’algoritmo specificato è nullo eNoSuchAlgorithmException
se nessun Provider supporta un’implementazioneSecretKeyFactorySpi
per l’algoritmo specificato. PBEKeySpec
è un costruttore di classi che accetta una password, salt, numero di iterazioni e lunghezza della chiave da derivare per generarePBEKey
di cifrari PBE a dimensione di chiave variabile. LanciaNullPointerException
sesalt
ènull
eIllegalArgumentException
se salt è vuoto.generateSecret
genera un oggettoSecretKey
dalla specifica della chiave fornita o dal materiale della chiave. Accetta la specifica della chiave segreta. GeneraInvalidKeySpecException
se la specifica data non è appropriata per questa factory di chiavi segrete per produrre un valore chiave classificato.
Dettagli del metodo encrypt
nella classe Encryption
.
- Il metodo
encrypt
richiede due parametri, i dati da crittografare e la chiave. Questo metodo genera eccezioni generate da metodi figlio in esso. - Il metodo
getInstance
attraversa la lista dei provider di sicurezza registrati, a partire dal provider più preferito. Prende il nome della trasformazione, ovvero AES / CBC / PKCS5Padding. GeneraNoSuchAlgorithmException
se una modifica è nulla, vuota, in un formato non valido eNoSuchPaddingException
se la modifica contiene uno schema di riempimento non disponibile. - Il metodo
init
inizializza ilCipher
per una delle seguenti quattro operazioni: crittografia, decrittografia, avvolgimento della chiave o scartamento della chiave, a seconda del valore della modalità di operazione.ENCRYPT_MODE
nel nostro caso. Il metodo generaUnsupportedOperationException
se la modalità operativa non è valida eInvalidKeyException
se la chiave fornita è inappropriata. - Il
getParameters
restituisce i parametri usati con questo cifrario. - Il
getParameterSpec
restituisce una specifica dell’oggetto parametro. Il parametroparamSpec
identifica la classe di specifica in cui i parametri devono tornare. Ad esempio, potrebbe essereDSAParameterSpec.class
per indicare che i parametri devono tornare in un’istanza della classeDSAParameterSpec
. - Il metodo
doFinal
crittografa o decrittografa i dati in una singola parte di lavoro o termina un’operazione in più parti. I dati vengono crittografati o decrittografati, a seconda di come inizializziamo la crittografia. base64Encode
è un metodo privato che codifica l’array di byte specificato in una stringa utilizzando lo schema di codificaBase64
. Le funzioni usate nel metododecrypt
sono simili al metodo sopra menzionato. L’unica differenza è che si comportano in modo diverso in base allamode
specificata nella funzione,DECRYPT_MODE
come modalità operativa.
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);
}
}
Di seguito è riportato l’output del codice scritto per crittografare e decrittografare la password nel file di configurazione.
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