Usa char Array su una stringa per manipolare le password in Java?

1. Panoramica

In questo articolo, spiegheremo perché dovremmo usare l' array char [] per rappresentare le password invece di String in Java.

Si noti che questo tutorial si concentra sui modi di manipolare le password nella memoria, non sui modi effettivi di memorizzarle, che di solito è gestito nel livello di persistenza.

Supponiamo inoltre di non poter controllare il formato della password (ad esempio, la password proviene dall'API di terze parti sotto forma di stringa ). Sebbene sembri ovvio utilizzare un oggetto di tipo java.lang.String per la manipolazione delle password, è consigliato dal team Java stesso di utilizzare invece char [] .

Ad esempio, se diamo uno sguardo al JPasswordField di javax.swing , possiamo vedere che il metodo getText () che restituisce String è deprecato da Java 2 ed è sostituito dal metodo getPassword () che restituisce char [] .

Quindi, esploriamo alcuni validi motivi per cui è così.

2. Le stringhe sono immutabili

Le stringhe in Java non sono modificabili, il che significa che non è possibile modificarle utilizzando API di alto livello. Qualsiasi modifica su un oggetto String produrrà una nuova String , mantenendo quella vecchia in memoria.

Pertanto, la password archiviata in una stringa sarà disponibile in memoria finché Garbage Collector non la cancella. Non possiamo controllare quando accade, ma questo periodo può essere notevolmente più lungo rispetto agli oggetti normali poiché le stringhe sono conservate in un pool di stringhe per scopi di riutilizzabilità.

Di conseguenza, chiunque abbia accesso al dump della memoria può recuperare la password dalla memoria.

Con un array char [] invece di String , possiamo cancellare esplicitamente i dati dopo aver terminato con il lavoro previsto. In questo modo, ci assicureremo che la password venga rimossa dalla memoria anche prima che abbia luogo la garbage collection.

Diamo ora un'occhiata agli snippet di codice, che dimostrano ciò di cui abbiamo appena discusso.

Primo per String :

System.out.print("Original String password value: "); System.out.println(stringPassword); System.out.println("Original String password hashCode: " + Integer.toHexString(stringPassword.hashCode())); String newString = "********"; stringPassword.replace(stringPassword, newString); System.out.print("String password value after trying to replace it: "); System.out.println(stringPassword); System.out.println( "hashCode after trying to replace the original String: " + Integer.toHexString(stringPassword.hashCode()));

L'output sarà:

Original String password value: password Original String password hashCode: 4889ba9b String value after trying to replace it: password hashCode after trying to replace the original String: 4889ba9b

Ora per char [] :

char[] charPassword = new char[]{'p', 'a', 's', 's', 'w', 'o', 'r', 'd'}; System.out.print("Original char password value: "); System.out.println(charPassword); System.out.println( "Original char password hashCode: " + Integer.toHexString(charPassword.hashCode())); Arrays.fill(charPassword, '*'); System.out.print("Changed char password value: "); System.out.println(charPassword); System.out.println( "Changed char password hashCode: " + Integer.toHexString(charPassword.hashCode()));

L'output è:

Original char password value: password Original char password hashCode: 7cc355be Changed char password value: ******** Changed char password hashCode: 7cc355be

Come possiamo vedere, dopo aver provato a sostituire il contenuto della String originale , il valore rimane lo stesso e il metodo hashCode () non ha restituito un valore diverso nella stessa esecuzione dell'applicazione, il che significa che la String originale è rimasta intatta.

E per l' array char [] , siamo stati in grado di modificare i dati nello stesso oggetto.

3. Possiamo stampare accidentalmente le password

Un altro vantaggio di lavorare con le password nell'array char [] è la prevenzione della registrazione accidentale della password in console, monitor o altri luoghi più o meno insicuri.

Controlliamo il codice successivo:

String passwordString = "password"; char[] passwordArray = new char[]{'p', 'a', 's', 's', 'w', 'o', 'r', 'd'}; System.out.println("Printing String password -> " + passwordString); System.out.println("Printing char[] password -> " + passwordArray);

Con l'uscita:

Printing String password -> password Printing char[] password -> [[email protected]

Vediamo che il contenuto stesso viene stampato nel primo caso, mentre nel secondo caso i dati non sono così utili, il che rende char [] meno vulnerabile.

4. Conclusione

In questo rapido articolo, abbiamo sottolineato diversi motivi per cui non dovremmo usare String s per raccogliere le password e perché dovremmo usare invece gli array char [] .

Come sempre, gli snippet di codice possono essere trovati su GitHub.