Comment hacher une chaîne avec sha256 en Java?

Réponses:

308

SHA-256 n'est pas un "encodage" - c'est un hachage unidirectionnel.

Vous convertiriez essentiellement la chaîne en octets (par exemple en utilisant text.getBytes(StandardCharsets.UTF_8)), puis hacheriez les octets. Notez que le résultat du hachage serait également des données binaires arbitraires, et si vous voulez représenter cela dans une chaîne, vous devez utiliser base64 ou hex ... n'essayez pas d'utiliser le String(byte[], String)constructeur.

par exemple

MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hash = digest.digest(text.getBytes(StandardCharsets.UTF_8));
Jon Skeet
la source
18
"SHA-256 n'est pas un encodage" tout à fait raison, mais je dois dire que je préfère le titre de la question actuelle à "comment chiffrer avec sha" (beaucoup semblent penser que c'est du chiffrement). Peut-être devrions-nous le traiter comme un encodage au lieu de quelque chose à voir avec la cryptographie, car en pratique, c'est plus proche de la façon dont il est utilisé.
Luc
5
@Luc: Eh bien , il est un hachage cryptographique, donc je ne pense pas qu'il soit déraisonnable de dire qu'il n'a quelque chose à voir avec la cryptographie ... chiffrement et cryptographie ne sont pas ... interchangable
Jon Skeet
8
Remarque: c'est une bonne idée d'utiliser StandardCharsets.UTF_8 au lieu du "UTF-8"littéral dans Java 7+: une exception vérifiée de moins à se soucier.
kryger
3
Pourquoi devriez-vous éviter le constructeur String (byte [], String) lorsque vous traitez le résultat de hachage?
Isaac van Bakel
5
@IsaacvanBakel: Parce qu'un hachage n'est pas du texte encodé. Ce sont des données binaires arbitraires.
Jon Skeet
172

Je pense que la solution la plus simple consiste à utiliser Apache Common Codec :

String sha256hex = org.apache.commons.codec.digest.DigestUtils.sha256Hex(stringText);   
seba
la source
1
Meilleure réponse, facile à utiliser, propre. Je vous remercie!
fl0w
99

Une autre alternative est Guava qui a une suite d' utilitaires de hachage facile à utiliser . Par exemple, pour hacher une chaîne en utilisant SHA256 comme chaîne hexadécimale, vous feriez simplement:

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

Exemple complet de hachage à chaîne comme une autre chaîne.

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);
    }
}
user1452273
la source
7
Pour encoder les résultats de Jon en hexadécimal, pensez à utiliser une bibliothèque existante comme apache commons plutôt que de rouler la vôtre.
Leigh
1
Pourquoi StringBuffer? (pas un stringBuilder)? et peut-être qu'il serait préférable de définir la taille par défaut de stringbuilder?
Bogdan
36
@Leigh: certaines personnes ne veulent pas ajouter une dépendance de bibliothèque entière simplement parce qu'elles en ont besoin d'une seule fonction, donc rouler la vôtre est parfois une bonne idée.
Chris
4
@Chris - Vrai. C'est pourquoi j'ai dit "envisagez" de l'utiliser ;-) Les bibliothèques existantes peuvent ajouter du volume. D'un autre côté, ils sont généralement plus testés que le code filé à la maison et, bien sûr, gagnent du temps. Mais il n'y a pas de réponse unique pour tout le monde.
Leigh
1
Vous pouvez également lire le code source de la bibliothèque et copier son code!
Olav Grønås Gjerde
47

Si vous utilisez Java 8, vous pouvez encoder le byte[]en faisant

MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hash = digest.digest(text.getBytes(StandardCharsets.UTF_8));
String encoded = Base64.getEncoder().encodeToString(hash);
Eduardo Dennis
la source
1
Cette façon me convient. Cependant, vous devez utiliser le Base64.encodeToString suivant (hachage, Base64.DEFAULT);
Motassem Jalal
@MotassemJalal Base64.DEFAULT n'est pas disponible dans la dernière version de Java8, j'utilise actuellement jdk1.8.0_144, pouvez-vous me dire comment vous l'avez créé?
rajadilipkolli du
2
@rajadilipkolli Je pense que c'est l'implémentation 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();
 }
}
Chathura Wijesinghe
la source
À quoi sert une valeur d'octet au niveau du bit 0xff? Cela ne rapporte rien, n'est-ce pas?
yktoo
2
@yktoo: Il le convertit en un entier positif (les octets sont signés en Java, malheureusement) stackoverflow.com/questions/11380062/…
leonbloy
StringBuffer peut être remplacé par un StringBuilder
User8461
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;
}
Ezd
la source
7

J'ai tracé le code Apache DigestUtilset sha256semble revenir par défaut au java.security.MessageDigestcalcul. Apache n'implémente pas de sha256solution indépendante . Je cherchais une implémentation indépendante pour comparer avec la java.securitybibliothèque. Pour info seulement.

garyn
la source
3

C'était mon approche en utilisant 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)})
}
Samuel Luís
la source
Salut, je viens d'essayer votre code car je dois hacher un mot de passe dans Android Studio et votre code renvoie quelque chose comme ceci: [B@188363epas le mot de passe crypté. De plus, il semble différent chaque fois que cette fonction est appelée.
Adrian2895
1
Corrigé, vous avez oublié return hash.fold("", { str, it -> str + "%02x".format(it)})qui renvoie le mot de passe crypté et non l'objet lui-même.
Adrian2895
1
oui vous avez raison, permettez-moi de mettre à jour la réponse avec votre correctif. Merci :)
Samuel Luís
2

Voici une façon légèrement plus performante de transformer le résumé en une chaîne hexadécimale:

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);
}

Quelqu'un connaît-il un moyen plus rapide en Java?

et moi
la source
1

Vous pouvez utiliser MessageDigest de la manière suivante:

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();
}
cet homme
la source
1

Dans 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());
MST
la source
0

En Java, la classe MessageDigest est utilisée pour calculer la valeur de hachage cryptographique. Cette classe fournit une fonction de hachage cryptographique ( MD5 , SHA-1 et SHA-256 ) pour trouver la valeur de hachage du texte.

Exemple de code pour l'utilisation de l'algorithme 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);

  }
}
Ravi
la source
0

C'est ce que j'ai utilisé pour le hachage:

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);

Sortie: 5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8

MrBitwise
la source
-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;
}

Vous pouvez appeler la méthode ci-dessus avec différents algorithmes comme ci-dessous.

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

Vous pouvez renvoyer ce lien pour une demande complète.

Hari Krishna
la source