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 come- password,- salt,- iterationCounte- keyLength.- passwordè la password effettiva nel file di configurazione. In crittografia, un- saltè un dato casuale che utilizziamo come input aggiuntivo che esegue l’hashing dei dati, una password o una passphrase. L’uso dei- saltsserve a salvaguardare le password in deposito. Usiamo la variabile- iterationCountcome 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 variabile- keyLengthè la lunghezza della chiave che alla fine dobbiamo derivare. Genera l’eccezione generata dai metodi utilizzati.
- Il metodo getInstanceattraversa 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. LanciaNullPointerExceptionse l’algoritmo specificato è nullo eNoSuchAlgorithmExceptionse nessun Provider supporta un’implementazioneSecretKeyFactorySpiper l’algoritmo specificato.
- PBEKeySpecè un costruttore di classi che accetta una password, salt, numero di iterazioni e lunghezza della chiave da derivare per generare- PBEKeydi cifrari PBE a dimensione di chiave variabile. Lancia- NullPointerExceptionse- saltè- nulle- IllegalArgumentExceptionse salt è vuoto.
- generateSecretgenera un oggetto- SecretKeydalla specifica della chiave fornita o dal materiale della chiave. Accetta la specifica della chiave segreta. Genera- InvalidKeySpecExceptionse 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 encryptrichiede due parametri, i dati da crittografare e la chiave. Questo metodo genera eccezioni generate da metodi figlio in esso.
- Il metodo getInstanceattraversa la lista dei provider di sicurezza registrati, a partire dal provider più preferito. Prende il nome della trasformazione, ovvero AES / CBC / PKCS5Padding. GeneraNoSuchAlgorithmExceptionse una modifica è nulla, vuota, in un formato non valido eNoSuchPaddingExceptionse la modifica contiene uno schema di riempimento non disponibile.
- Il metodo initinizializza ilCipherper una delle seguenti quattro operazioni: crittografia, decrittografia, avvolgimento della chiave o scartamento della chiave, a seconda del valore della modalità di operazione.ENCRYPT_MODEnel nostro caso. Il metodo generaUnsupportedOperationExceptionse la modalità operativa non è valida eInvalidKeyExceptionse la chiave fornita è inappropriata.
- Il getParametersrestituisce i parametri usati con questo cifrario.
- Il getParameterSpecrestituisce una specifica dell’oggetto parametro. Il parametroparamSpecidentifica la classe di specifica in cui i parametri devono tornare. Ad esempio, potrebbe essereDSAParameterSpec.classper indicare che i parametri devono tornare in un’istanza della classeDSAParameterSpec.
- Il metodo doFinalcrittografa 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 codifica- Base64. Le funzioni usate nel metodo- decryptsono simili al metodo sopra menzionato. L’unica differenza è che si comportano in modo diverso in base alla- modespecificata nella funzione,- DECRYPT_MODEcome 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