¿Cómo hash alguna cadena con sha256 en Java?


Respuestas:


308

SHA-256 no es una "codificación", es un hash unidireccional.

Básicamente, convertirías la cadena en bytes (por ejemplo, usando text.getBytes(StandardCharsets.UTF_8)) y luego hash los bytes. Tenga en cuenta que el resultado del hash también serían datos binarios arbitrarios, y si desea representar eso en una cadena, debe usar base64 o hexadecimal ... no intente usar el String(byte[], String)constructor.

p.ej

MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hash = digest.digest(text.getBytes(StandardCharsets.UTF_8));

18
"SHA-256 no es una codificación" absolutamente correcto, pero debo decir que prefiero el título de la pregunta actual a "cómo encriptar con sha" (muchos parecen pensar que es encriptación). Tal vez deberíamos tratarlo como codificación en lugar de algo relacionado con la criptografía porque en la práctica está más cerca de cómo se usa.
Luc

55
@Luc: Bueno, es un hash criptográfico, así que no creo que es razonable decir que no tiene algo que ver con la criptografía ... cifrado y criptografía no son intercambiables ...
Jon Skeet

8
Nota: es una buena idea usar StandardCharsets.UTF_8 en lugar del "UTF-8"literal en Java 7+: una excepción marcada menos de la que preocuparse.
kryger

3
¿Por qué debería evitar el constructor String (byte [], String) al tratar con el resultado hash?
Isaac van Bakel

55
@IsaacvanBakel: Porque un hash no es texto codificado. Son datos binarios arbitrarios.
Jon Skeet

172

Creo que la solución más fácil es usar Apache Common Codec :

String sha256hex = org.apache.commons.codec.digest.DigestUtils.sha256Hex(stringText);   

1
La mejor respuesta, fácil de usar, limpia. ¡Gracias!
fl0w

99

Otra alternativa es Guava, que tiene un conjunto de utilidades Hashing fáciles de usar . Por ejemplo, para trocear una cadena usando SHA256 como una cadena hexadecimal, simplemente haría:

final String hashed = Hashing.sha256()
        .hashString("your input", StandardCharsets.UTF_8)
        .toString();

85

Ejemplo completo de hash para encadenar como otra cadena.

public static String sha256(String base) {
    try{
        MessageDigest digest = MessageDigest.getInstance("SHA-256");
        byte[] hash = digest.digest(base.getBytes("UTF-8"));
        StringBuffer hexString = new StringBuffer();

        for (int i = 0; i < hash.length; i++) {
            String hex = Integer.toHexString(0xff & hash[i]);
            if(hex.length() == 1) hexString.append('0');
            hexString.append(hex);
        }

        return hexString.toString();
    } catch(Exception ex){
       throw new RuntimeException(ex);
    }
}

77
Para codificar los resultados de Jon como hexadecimales, considere usar una biblioteca existente como apache commons en lugar de crear la suya propia.
Leigh

1
¿Por qué StringBuffer? (no es un stringBuilder)? y tal vez sería mejor establecer el tamaño predeterminado de stringbuilder?
Bogdan

36
@Leigh: algunas personas no quieren agregar una dependencia completa de la biblioteca solo porque necesitan una sola función, por lo que rodar la suya es a veces una buena idea.
Chris

44
@ Chris - Cierto. Es por eso que dije "considerar" usarlo ;-) Las bibliotecas existentes pueden agregar volumen. Por otro lado, generalmente son más probados que el código de inicio y, por supuesto, ahorran tiempo. Pero no hay una respuesta única para todos.
Leigh

1
¡También puede leer el código fuente de la biblioteca y copiar su código!
Olav Grønås Gjerde

47

Si está utilizando Java 8, puede codificarlo byte[]haciendo

MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hash = digest.digest(text.getBytes(StandardCharsets.UTF_8));
String encoded = Base64.getEncoder().encodeToString(hash);

1
Este camino es conveniente para mí. Sin embargo, debe usar el siguiente Base64.encodeToString (hash, Base64.DEFAULT);
Motassem Jalal

@MotassemJalal Base64.DEFAULT no está disponible en la última versión de Java8, actualmente estoy usando jdk1.8.0_144, ¿puede decirme cómo lo ha creado?
rajadilipkolli

2
@rajadilipkolli Creo que es la implementación de Android: developer.android.com/reference/android/util/Base64
dbm

12
import java.security.MessageDigest;

public class CodeSnippets {

 public static String getSha256(String value) {
    try{
        MessageDigest md = MessageDigest.getInstance("SHA-256");
        md.update(value.getBytes());
        return bytesToHex(md.digest());
    } catch(Exception ex){
        throw new RuntimeException(ex);
    }
 }
 private static String bytesToHex(byte[] bytes) {
    StringBuffer result = new StringBuffer();
    for (byte b : bytes) result.append(Integer.toString((b & 0xff) + 0x100, 16).substring(1));
    return result.toString();
 }
}

¿Cuál es el punto de bit a bit y con un valor de byte 0xff? No produce nada, ¿verdad?
yktoo

2
@yktoo: lo convierte en un entero positivo (los bytes están firmados en Java, desafortunadamente) stackoverflow.com/questions/11380062/…
leonbloy

StringBuffer puede ser reemplazado por un StringBuilder
Usuario8461

10
String hashWith256(String textToHash) {
    MessageDigest digest = MessageDigest.getInstance("SHA-256");
    byte[] byteOfTextToHash = textToHash.getBytes(StandardCharsets.UTF_8);
    byte[] hashedByetArray = digest.digest(byteOfTextToHash);
    String encoded = Base64.getEncoder().encodeToString(hashedByetArray);
    return encoded;
}

7

Rastreé el código de Apache DigestUtilsy sha256parece volver a los valores predeterminados java.security.MessageDigestpara el cálculo. Apache no implementa una sha256solución independiente . Estaba buscando una implementación independiente para comparar con la java.securitybiblioteca. Solo para tu información.


3

Este fue mi enfoque usando Kotlin:

private fun getHashFromEmailString(email : String) : String{
    val charset = Charsets.UTF_8
    val byteArray = email.toByteArray(charset)
    val digest = MessageDigest.getInstance("SHA-256")
    val hash = digest.digest(byteArray)

    return hash.fold("", { str, it -> str + "%02x".format(it)})
}

Hola, acabo de probar tu código porque necesito introducir una contraseña en Android Studio y tu código devuelve algo como esto: [B@188363eno la contraseña cifrada. Además, parece ser diferente cada vez que se llama a esta función.
Adrian2895

1
Solucionado, olvidó return hash.fold("", { str, it -> str + "%02x".format(it)})cuál devuelve la contraseña cifrada y no el objeto en sí.
Adrian2895

1
Sí, tienes razón, déjame actualizar la respuesta con tu solución. Gracias :)
Samuel Luís

2

Aquí hay una forma un poco más eficaz de convertir el resumen en una cadena hexadecimal:

private static final char[] hexArray = "0123456789abcdef".toCharArray();

public static String getSHA256(String data) {
    StringBuilder sb = new StringBuilder();
    try {
        MessageDigest md = MessageDigest.getInstance("SHA-256");
        md.update(data.getBytes());
        byte[] byteData = md.digest();
        sb.append(bytesToHex(byteData);
    } catch(Exception e) {
        e.printStackTrace();
    }
    return sb.toString();
}

private static String bytesToHex(byte[] bytes) {
    char[] hexChars = new char[bytes.length * 2];
    for ( int j = 0; j < bytes.length; j++ ) {
        int v = bytes[j] & 0xFF;
        hexChars[j * 2] = hexArray[v >>> 4];
        hexChars[j * 2 + 1] = hexArray[v & 0x0F];
    }
    return String.valueOf(hexChars);
}

¿Alguien sabe de una manera más rápida en Java?


1

Puede usar MessageDigest de la siguiente manera:

public static String getSHA256(String data){
    StringBuffer sb = new StringBuffer();
    try{
        MessageDigest md = MessageDigest.getInstance("SHA-256");
        md.update(data.getBytes());
        byte byteData[] = md.digest();

        for (int i = 0; i < byteData.length; i++) {
         sb.append(Integer.toString((byteData[i] & 0xff) + 0x100, 16).substring(1));
        }
    } catch(Exception e){
        e.printStackTrace();
    }
    return sb.toString();
}

1

En Java 8

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Scanner;
import javax.xml.bind.DatatypeConverter;


Scanner scanner = new Scanner(System.in);
String password = scanner.nextLine();
scanner.close();

MessageDigest digest = null;
try {
    digest = MessageDigest.getInstance("SHA-256");
} catch (NoSuchAlgorithmException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}
byte[] hash = digest.digest(password.getBytes(StandardCharsets.UTF_8));
String encoded = DatatypeConverter.printHexBinary(hash);        
System.out.println(encoded.toLowerCase());

0

En Java, la clase MessageDigest se usa para calcular el valor de cifrado criptográfico. Esta clase proporciona la función hash criptográfica ( MD5 , SHA-1 y SHA-256 ) para encontrar el valor hash del texto.

Ejemplo de código para usar el algoritmo SHA-256.

public void printHash(String str) throws NoSuchAlgorithmException {

MessageDigest md=MessageDigest.getInstance("SHA-256");

byte[] sha256=md.digest(str.getBytes(StandardCharsets.UTF_8));

   for(byte b : sha256){

      System.out.printf("%02x",b);

  }
}

0

Esto es lo que me han utilizado para el hash:

String pass = "password";

MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
byte hashBytes[] = messageDigest.digest(pass.getBytes(StandardCharsets.UTF_8));
BigInteger noHash = new BigInteger(1, hashBytes);
String hashStr = noHash.toString(16);

Salida: 5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8


-2
private static String getMessageDigest(String message, String algorithm) {
 MessageDigest digest;
 try {
  digest = MessageDigest.getInstance(algorithm);
  byte data[] = digest.digest(message.getBytes("UTF-8"));
  return convertByteArrayToHexString(data);
 } catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
  // TODO Auto-generated catch block
  e.printStackTrace();
 }
 return null;
}

Puede llamar al método anterior con diferentes algoritmos, como a continuación.

getMessageDigest(message, "MD5");
getMessageDigest(message, "SHA-256");
getMessageDigest(message, "SHA-1");

Puede consultar este enlace para completar la solicitud.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.