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

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

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

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

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

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

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

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.


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

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?


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

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

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

  }
}

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


-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.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.