2010-06-23 43 views
99

En regardant autour d'ici ainsi que l'Internet en général, j'ai trouvé Bouncy Castle. Je veux utiliser Bouncy Castle (ou un autre utilitaire disponible gratuitement) pour générer un hachage SHA-256 d'une chaîne en Java. En regardant leur documentation, je n'arrive pas à trouver de bons exemples de ce que je veux faire. Quelqu'un peut-il m'aider?Chaîne de hachage via SHA-256 en Java

Répondre

226

Hash une chaîne, utilisez le haut-MessageDigest classe: Dans l'extrait ci-dessus

import java.security.MessageDigest; 
import java.security.NoSuchAlgorithmException; 
import java.nio.charset.StandardCharsets; 
import java.math.BigInteger; 

public class CryptoHash { 
    public static void main(String[] args) throws NoSuchAlgorithmException { 
    MessageDigest md = MessageDigest.getInstance("SHA-256"); 
    String text = "Text to hash, cryptographically."; 

    // Change this to UTF-16 if needed 
    md.update(text.getBytes(StandardCharsets.UTF_8)); 
    byte[] digest = md.digest(); 

    String hex = String.format("%064x", new BigInteger(1, digest)); 
    System.out.println(hex); 
    } 
} 

, digest contient la chaîne hachée et hex contient une chaîne ASCII hexadécimal gauche padding zéro.

+0

Pour la même plaintext, ne le hachage supposé être différent à chaque fois? Parce que c'est ce qui m'arrive –

+2

@Harry Pham, le hachage devrait toujours être le même, mais sans plus d'informations, il serait difficile de dire pourquoi vous obtenez différents. Vous devriez probablement ouvrir une nouvelle question. –

+2

@Harry Pham: Après avoir appelé 'digest', l'état interne est réinitialisé; donc quand vous l'appelez à nouveau sans mise à jour avant, vous obtenez le hachage de la chaîne vide. – Debilski

7

Lorsque vous utilisez hashcodes avec un fournisseur de jce vous essayez d'abord d'obtenir une instance de l'algorithme, puis mettre à jour avec les données que vous voulez être haché et quand vous avez terminé, vous appelez digérer pour obtenir la valeur de hachage.

MessageDigest sha = MessageDigest.getInstance("SHA-256"); 
sha.update(in.getBytes()); 
byte[] digest = sha.digest(); 

vous pouvez utiliser la digestion pour obtenir une version base64 ou hexagonal selon vos besoins

+0

Par curiosité, pouvez-vous aller directement à 'digest()' avec le tableau d'octets en entrée, en ignorant 'update()'? – ladenedge

+0

Une chose que j'ai remarquée est que cela fonctionne avec "SHA-256" alors que "SHA256" lance une exception NoSuchAlgorithmException. Pas de biggie. – KPthunder

+8

Selon mon commentaire à Brandon, ** n'utilisez pas ** String.getBytes() 'sans spécifier d'encodage. Actuellement, ce code peut donner des résultats différents sur différentes plates-formes - ce qui est un comportement cassé pour un hachage bien défini. –

28

Ceci est déjà mis en œuvre dans les libs d'exécution.

public static String calc(InputStream is) { 
    String output; 
    int read; 
    byte[] buffer = new byte[8192]; 

    try { 
     MessageDigest digest = MessageDigest.getInstance("SHA-256"); 
     while ((read = is.read(buffer)) > 0) { 
      digest.update(buffer, 0, read); 
     } 
     byte[] hash = digest.digest(); 
     BigInteger bigInt = new BigInteger(1, hash); 
     output = bigInt.toString(16); 
     while (output.length() < 32) { 
      output = "0"+output; 
     } 
    } 
    catch (Exception e) { 
     e.printStackTrace(System.err); 
     return null; 
    } 

    return output; 
} 

Dans un environnement JEE6 + on pourrait aussi utiliser JAXB DataTypeConverter:

import javax.xml.bind.DatatypeConverter; 

String hash = DatatypeConverter.printHexBinary( 
      MessageDigest.getInstance("MD5").digest("SOMESTRING".getBytes("UTF-8"))); 
+1

cette version a un bug (au moins à ce jour et avec java8 @ win7). essayez de hacher '1234'. le résultat doit commencer par '03ac67 ...' mais il commence réellement par '3ac67 ...' – Chris

+0

@Chris merci, j'ai corrigé ça ici, mais j'ai trouvé une meilleure solution mon préféré sur ceci est actuellement: http: // stackoverflow .com/questions/415953/how-can-i-generate-an-md5-hash/23273249 # 23273249 – stacker

+1

Pour les nouveaux lecteurs de ce vieux fil: Le favori (hash MD5) référencé par @stacker est maintenant considéré comme non sécurisé (http://en.wikipedia.org/wiki/MD5). – mortensi

1
return new String(Hex.encode(digest)); 
+3

Sans informations sur le paquet/fournisseur, la classe "Hex" n'est pas très utile. Et si c'est Hex d'Apache Commons Codec, j'utiliserai 'return Hex.encodeHexString (digest)' à la place. – eckes

5

Je suppose que vous utilisez une version relativement ancienne Java sans SHA-256. Vous devez donc ajouter le fournisseur BouncyCastle aux fournisseurs de sécurité déjà fournis dans votre version java.

// NEEDED if you are using a Java version without SHA-256  
    Security.addProvider(new BouncyCastleProvider()); 

    // then go as usual 
    MessageDigest md = MessageDigest.getInstance("SHA-256"); 
    String text = "my string..."; 
    md.update(text.getBytes("UTF-8")); // or UTF-16 if needed 
    byte[] digest = md.digest(); 
+0

+1 pour mentionner BouncyCastle, qui ajoute un certain nombre de nouveaux MessageDigest par rapport à la sélection relativement dérisoire disponible dans le JDK. – mjuarez

-1

Cela fonctionne avec "org.bouncycastle.util.encoders.Hex" package suivant

return new String(Hex.encode(digest)); 

Son dans bouncycastle pot.

14

Vous n'avez pas nécessairement besoin de la bibliothèque BouncyCastle. Le code suivant montre comment le faire en utilisant la fonction Integer.toHexString

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

grâce à user1452273 spéciales de ce poste: How to hash some string with sha256 in Java?

Gardez le bon travail!

7

Java 8: base64 disponible:

MessageDigest md = MessageDigest.getInstance("SHA-512"); 
    md.update(inbytes); 
    byte[] aMessageDigest = md.digest(); 

    String outEncoded = Base64.getEncoder().encodeToString(aMessageDigest); 
    return(outEncoded);