Panoramica
Lo SHA (Secure Hash Algorithm) è una delle popolari funzioni di hash crittografico. Un hash crittografico può essere usato per fare una firma per un testo o un file di dati. In questo tutorial, diamo un’occhiata a come possiamo eseguire operazioni di hashing SHA-256 e SHA3-256 usando varie librerie Java.
L’algoritmo SHA-256 genera un hash quasi unico, a dimensione fissa di 256 bit (32 byte). Si tratta di una funzione unidirezionale, quindi il risultato non può essere decifrato per tornare al valore originale.
Attualmente, l’hashing SHA-2 è ampiamente utilizzato in quanto è considerato l’algoritmo di hashing più sicuro in ambito crittografico.
SHA-3 è l’ultimo standard di hashing sicuro dopo SHA-2. Rispetto a SHA-2, SHA-3 fornisce un approccio diverso per generare un hash unico a senso unico, e può essere molto più veloce su alcune implementazioni hardware. Simile a SHA-256, SHA3-256 è l’algoritmo a lunghezza fissa di 256 bit in SHA-3.
NIST ha rilasciato SHA-3 nel 2015, quindi non ci sono molte librerie SHA-3 come SHA-2 per il momento. Non è fino a JDK 9 che gli algoritmi SHA-3 erano disponibili nei provider predefiniti incorporati.
Ora, iniziamo con SHA-256.
Altra lettura:
Locality-Sensitive Hashing in Java Using Java-LSH
MD5 Hashing in Java
Una guida a HashSet in Java
ClasseMessageDigest in Java
Java fornisce la classe MessageDigest integrata per l’hashing SHA-256:
MessageDigest digest = MessageDigest.getInstance("SHA-256");byte encodedhash = digest.digest( originalString.getBytes(StandardCharsets.UTF_8));
Tuttavia, qui dobbiamo usare un convertitore personalizzato da byte a esadecimale per ottenere il valore hash in esadecimale:
private static String bytesToHex(byte hash) { StringBuilder hexString = new StringBuilder(2 * hash.length); for (int i = 0; i < hash.length; i++) { String hex = Integer.toHexString(0xff & hash); if(hex.length() == 1) { hexString.append('0'); } hexString.append(hex); } return hexString.toString();}
Dobbiamo essere consapevoli che il MessageDigest non è thread-safe. Di conseguenza, dovremmo usare una nuova istanza per ogni thread.
Biblioteca Guava
La libreria Guava di Google fornisce anche una classe di utilità per l’hashing.
Primo, definiamo la dipendenza:
<dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>20.0</version></dependency>
Ora, ecco come possiamo usare Guava per l’hash di una stringa:
String sha256hex = Hashing.sha256() .hashString(originalString, StandardCharsets.UTF_8) .toString();
Apache Commons Codecs
Similmente, possiamo anche usare Apache Commons Codecs:
<dependency> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> <version>1.11</version></dependency>
Ecco la classe di utilità – chiamata DigestUtils – che supporta la codifica SHA-256:
String sha256hex = DigestUtils.sha256Hex(originalString);
Bouncy Castle Library
5.1. Dipendenza Maven
<dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15on</artifactId> <version>1.60</version></dependency>
5.2. Hashing usando la libreria Bouncy Castle
L’API Bouncy Castle fornisce una classe di utilità per convertire i dati esadecimali in byte e viceversa.
Tuttavia, è necessario prima popolare un digest usando l’API Java integrata:
MessageDigest digest = MessageDigest.getInstance("SHA-256");byte hash = digest.digest( originalString.getBytes(StandardCharsets.UTF_8));String sha256hex = new String(Hex.encode(hash));
SHA3-256
Ora continuiamo con SHA3-256. L’hashing SHA3-256 in Java non è molto diverso da SHA-256.
6.1. Classe MessageDigest in Java
A partire da JDK 9, possiamo semplicemente usare l’algoritmo integrato SHA3-256:
final MessageDigest digest = MessageDigest.getInstance("SHA3-256");final byte hashbytes = digest.digest( originalString.getBytes(StandardCharsets.UTF_8));String sha3Hex = bytesToHex(hashbytes);
6.2. Apache Commons Codecs
Apache Commons Codecs fornisce un comodo wrapper DigestUtils per la classe MessageDigest. Questa libreria ha iniziato a supportare SHA3-256 dalla versione 1.11, e richiede anche JDK 9+:
String sha3Hex = new DigestUtils("SHA3-256").digestAsHex(originalString);
6.3. Keccak-256
Keccak-256 è un altro popolare algoritmo di hashing SHA3-256. Attualmente, serve come alternativa allo standard SHA3-256. Keccak-256 offre lo stesso livello di sicurezza dello standard SHA3-256, e si differenzia da SHA3-256 solo per la regola del padding. È stato usato in diversi progetti di blockchain, come Monero.
Ancora una volta, dobbiamo importare la libreria Bouncy Castle per usare l’hashing Keccak-256:
Security.addProvider(new BouncyCastleProvider());final MessageDigest digest = MessageDigest.getInstance("Keccak-256");final byte encodedhash = digest.digest( originalString.getBytes(StandardCharsets.UTF_8));String sha3Hex = bytesToHex(encodedhash);
Possiamo anche fare uso dell’API Bouncy Castle per fare l’hashing:
Keccak.Digest256 digest256 = new Keccak.Digest256();byte hashbytes = digest256.digest( originalString.getBytes(StandardCharsets.UTF_8));String sha3Hex = new String(Hex.encode(hashbytes));
Conclusione
In questo rapido articolo, abbiamo dato un’occhiata ad alcuni modi per implementare l’hashing SHA-256 e SHA3-256 in Java, usando sia librerie integrate che di terze parti.