En Java, podemos utilizar MessageDigest
para obtener un SHA-256
o SHA3-256
algoritmo de hash para hashear una cadena.
MessageDigest md = MessageDigest.getInstance("SHA3-256"); byte result = md.digest(input);
Este artículo muestra cómo utilizar los algoritmos Java SHA-256
y SHA3-256
para generar un valor hash a partir de una cadena dada y una suma de comprobación de un archivo.
Nota
El hashing es una función de compresión unidireccional para convertir entradas de diferentes longitudes en una salida de longitud fija (valor hash).
SHA-2 y SHA-3
1.1 El SHA-2 (Secure Hash Algorithm 2) está definido en FIPS PUB 180-4. El SHA-2 es un algoritmo de hashing ampliamente utilizado y diseñado por la Agencia Nacional de Seguridad (NSA).
Java soporta los siguientes SHA-2
algoritmos:
SHA-224
SHA-256
SHA-384
SHA-512
SHA-512/224
SHA-512/256
El SHA-256
produce una salida de 256bits de salida, 32 bytes, mientras que SHA-512
produce una salida de 512 bits, 64 bytes.
String : Hello WorldSHA-256a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146eSHA-5122c74fd17edafd80e8447b0d46741ee243b7eb74dd2149a0ab1b9246fb30382f27e853d8585719e0e67cbda0daa8f51671064615d645ae27acb15bfb1447f459b
1.2 El SHA-3 (Secure Hash Algorithm 3) está definido en FIPS PUB 202. El SHA-3 es el último miembro de los Algoritmos Hash Seguros, publicado por el Instituto Nacional de Estándares y Tecnología (NIST).
Java soporta los siguientes SHA-3
algoritmos:
SHA3-224
SHA3-256
SHA3-384
SHA3-512
String : Hello WorldSHA3-256e167f68d6563d75bb25f3aa49c29ef612d41352dc00606de7cbd630bb2665f51SHA3-5122c74fd17edafd80e8447b0d46741ee243b7eb74dd2149a0ab1b9246fb30382f27e853d8585719e0e67cbda0daa8f51671064615d645ae27acb15bfb1447f459b
- Lee esto ¿Cuál es la diferencia entre SHA-3 y SHA-256?
- Lee esta Comparación de las funciones SHA
Java SHA3-256 Hashing
Este ejemplo de Java hace el hash de una cadena con el algoritmo SHA3-256
.
package com.mkyong.crypto.hash;import java.nio.charset.Charset;import java.nio.charset.StandardCharsets;import java.security.MessageDigest;import java.security.NoSuchAlgorithmException;public class ShaUtils { private static final Charset UTF_8 = StandardCharsets.UTF_8; private static final String OUTPUT_FORMAT = "%-20s:%s"; public static byte digest(byte input, String algorithm) { MessageDigest md; try { md = MessageDigest.getInstance(algorithm); } catch (NoSuchAlgorithmException e) { throw new IllegalArgumentException(e); } byte result = md.digest(input); return result; } public static String bytesToHex(byte bytes) { StringBuilder sb = new StringBuilder(); for (byte b : bytes) { sb.append(String.format("%02x", b)); } return sb.toString(); } public static void main(String args) { //String algorithm = "SHA-256"; // if you perfer SHA-2 String algorithm = "SHA3-256"; String pText = "Hello World"; System.out.println(String.format(OUTPUT_FORMAT, "Input (string)", pText)); System.out.println(String.format(OUTPUT_FORMAT, "Input (length)", pText.length())); byte shaInBytes = ShaUtils.digest(pText.getBytes(UTF_8), algorithm); System.out.println(String.format(OUTPUT_FORMAT, algorithm + " (hex) ", bytesToHex(shaInBytes))); // fixed length, 32 bytes, 256 bits. System.out.println(String.format(OUTPUT_FORMAT, algorithm + " (length)", shaInBytes.length)); }}
Salida
Input (string) :Hello WorldInput (length) :11SHA3-256 (hex) :e167f68d6563d75bb25f3aa49c29ef612d41352dc00606de7cbd630bb2665f51SHA3-256 (length) :32
Trata de hacer el hash de otra cadena, de diferente longitud, para SHA3-256
, la salida fija a 256 bits, 32 bytes.
Salida
Input (string) :Hello SHA HashingInput (length) :17SHA3-256 (hex) :72fbf4f3a807d344a1ee492ff4183edf72e45fab8dfa6a6e5447226233633bf8SHA3-256 (length) :32
Suma de comprobación de archivos SHA3-256 de Java
Un archivo en la carpeta resources.
Hello World
Este ejemplo utiliza el algoritmo SHA3-256
para generar una suma de comprobación para el archivo anterior.
package com.mkyong.crypto.hash;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream;import java.nio.charset.Charset;import java.nio.charset.StandardCharsets;import java.security.DigestInputStream;import java.security.MessageDigest;import java.security.NoSuchAlgorithmException;public class ShaUtils { private static byte checksum(String filePath, String algorithm) { MessageDigest md; try { md = MessageDigest.getInstance(algorithm); } catch (NoSuchAlgorithmException e) { throw new IllegalArgumentException(e); } try (InputStream is = new FileInputStream(filePath); DigestInputStream dis = new DigestInputStream(is, md)) { while (dis.read() != -1) ; //empty loop to clear the data md = dis.getMessageDigest(); } catch (IOException e) { throw new IllegalArgumentException(e); } return md.digest(); } public static String bytesToHex(byte bytes) { StringBuilder sb = new StringBuilder(); for (byte b : bytes) { sb.append(String.format("%02x", b)); } return sb.toString(); } public static void main(String args) { String algorithm = "SHA3-256"; // get file path from resources String filePath = ClassLoader.getSystemResource("sha-file.txt").getFile(); byte hashInBytes = checksum(filePath, algorithm); System.out.println(bytesToHex(hashInBytes)); }}
Salida
e167f68d6563d75bb25f3aa49c29ef612d41352dc00606de7cbd630bb2665f51
NoSuchAlgorithmException
Lee esto para todos los Algoritmos MessageDigest soportados por Java. Si proporcionamos un algoritmo no existente, por ejemplo, SHA4-256
, Java lanza java.security.NoSuchAlgorithmException
.
MessageDigest md = MessageDigest.getInstance("SHA4-256");
java.security.NoSuchAlgorithmException: SHA4-256 MessageDigest not availableat com.mkyong.crypto.hash.ShaUtils.digest(ShaUtils.java:22)at com.mkyong.crypto.hash.ShaUtils.main(ShaUtils.java:65)Caused by: java.security.NoSuchAlgorithmException: SHA4-256 MessageDigest not availableat java.base/sun.security.jca.GetInstance.getInstance(GetInstance.java:159)at java.base/java.security.Security.getImpl(Security.java:700)at java.base/java.security.MessageDigest.getInstance(MessageDigest.java:178)at com.mkyong.crypto.hash.ShaUtils.digest(ShaUtils.java:20)... 1 more
Apache Commons Codec
Este ejemplo utiliza el popular Apache Commons Codec para hacer hash de una cadena con los algoritmos SHA.
<dependency> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> <version>1.14</version></dependency>
import org.apache.commons.codec.digest.DigestUtils; // SHA-2 byte hash1 = DigestUtils.sha256(""); // returns byte arrays String hash2 = DigestUtils.sha256Hex(""); // returns encoded hex // SHA-3 byte hash3 = DigestUtils.sha3_256(""); // returns byte arrays String hash4 = DigestUtils.sha3_256Hex(""); // returns encoded hex
Añadir Sal al hashing SHA
La sal es un dato aleatorio, una técnica para evitar los ataques rainbow. En Java, podemos utilizar SecureRandom
para generar una sal (bytes aleatorios).
public static byte getRandomNonce(int numBytes) { byte nonce = new byte; new SecureRandom().nextBytes(nonce); return nonce; }
Este ejemplo genera una sal aleatoria de 16 bytes y utiliza ByteBuffer
para anteponerla a una cadena. Al final, utilizamos el algoritmo SHA3-256
para generar un valor hash a partir del salt + string
.
// get a 16 bytes random salt. byte salt = CryptoUtils.getRandomNonce(16); byte pText = "Hello World".getBytes(StandardCharsets.UTF_8); // combine two byte arrays byte input = ByteBuffer.allocate(salt.length + pText.length) .put(salt) .put(pText) .array(); // no salt, SHA3-256 System.out.println(bytesToHex(ShaUtils.digest(pText, "SHA3-256"))); // 16 bytes salt, SHA3-256 System.out.println(bytesToHex(ShaUtils.digest(input, "SHA3-256")));
Salida
# no salte167f68d6563d75bb25f3aa49c29ef612d41352dc00606de7cbd630bb2665f51# 16 bytes salta6c589937ea475fc942d31d154d359ff569ff99fa32ee5d996ff64eca2e7551b
Nota
Para el hash de las contraseñas, podemos utilizar Bcrypt o Argon2.
Descarga el código fuente
$ git clone https://github.com/mkyong/core-java
$ cd java-crypto
- Wikipedia – SHA-3
- Wikipedia – Algoritmos Hash seguros
- Algoritmos MessageDigest
- Java – Cómo convertir matrices de bytes a Hex
- Java MD5 Hashing. Ejemplo
- Java – Cómo unir y dividir matrices de bytes
mkyong
Fundador de Mkyong.com, amante de Java y de las cosas de código abierto. Síguelo en Twitter. Si te gustan mis tutoriales, considera hacer una donación a estas organizaciones benéficas.
0 comentarios