2010-06-23 10 views
99

Patrząc tutaj, jak również ogólnie w Internecie, znalazłem Bouncy Castle. Chcę użyć Bouncy Castle (lub jakiegoś innego ogólnodostępnego narzędzia) do wygenerowania SHA-256 Hash String w Javie. Patrząc na ich dokumentację, nie mogę znaleźć dobrych przykładów tego, co chcę zrobić. Czy ktoś może mi pomóc?Hash String przez SHA-256 w Javie

Odpowiedz

226

hash ciąg, użyj wbudowanej MessageDigest klasy:

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

W powyższym fragmencie, digest zawiera zaszyfrowany ciąg i hex zawiera szesnastkowy ciąg ASCII z lewej wypełnianie zerami.

+0

Z tego samego tekstu jawnego, czy hash przypuszczać, aby być inna za każdym razem? Ponieważ tak się ze mną dzieje –

+2

@Harry Pham, hash powinien zawsze być taki sam, ale bez większej ilości informacji trudno byłoby powiedzieć, dlaczego dostajesz inne. Powinieneś prawdopodobnie otworzyć nowe pytanie. –

+2

@Harry Pham: Po wywołaniu 'digest' stan wewnętrzny jest resetowany; więc jeśli wywołasz go ponownie bez wcześniejszej aktualizacji, otrzymasz skrót z pustego łańcucha. – Debilski

7

Podczas korzystania hashcodes z dowolnego dostawcy JCE najpierw spróbować uzyskać wystąpienie algorytmu, następnie zaktualizować go z danymi chcesz być mieszany i po zakończeniu nazywasz strawienia, aby uzyskać wartość hash.

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

można użyć likwidacji, aby uzyskać wersji base64 lub hex kodowane zgodnie ze swoimi potrzebami

+0

Z ciekawości, możesz przejść od razu do 'digest()' z tablicą bajtów wejściowych, pomijając 'update()'? – ladenedge

+0

Jedną z rzeczy, którą zauważyłem jest to, że działa to z "SHA-256", podczas gdy "SHA256" generuje wyjątek NoSuchAlgorithmException. Bez wielkiej wagi. – KPthunder

+8

Zgodnie z moim komentarzem do Brandona, ** nie używaj 'String.getBytes()' bez określenia kodowania. Obecnie ten kod może dawać różne wyniki na różnych platformach - co jest wadliwym zachowaniem dla dobrze zdefiniowanego skrótu. –

28

ten jest już realizowany w libs uruchomieniowych.

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

W środowisku JEE6 + można również wykorzystać JAXB DataTypeConverter:

import javax.xml.bind.DatatypeConverter; 

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

ta wersja ma błąd (przynajmniej od dzisiaj i z java8 @ win7). spróbuj hasza "1234". wynik musi zaczynać się od "03ac67 ...", ale tak naprawdę zaczyna się od "3ac67 ..." – Chris

+0

@Chris dzięki, naprawiłem to tutaj, ale znalazłem lepsze rozwiązanie moje ulubione na tym jest obecnie: http: // stackoverflow .pl/pytania/415953/how-can-i-generate-an-md5-hash/23273249 # 23273249 – stacker

+1

Dla nowych czytelników tego starego wątku: ulubiony (skrót MD5), do którego odnosi się @stacker, jest obecnie uważany za niezabezpieczony (http://en.wikipedia.org/wiki/MD5). – mortensi

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

Bez informacji o pakiecie/dostawcy klasa "Hex" nie jest bardzo pomocna. A jeśli to jest Hex z Codec Apache Commons, użyłbym 'return Hex.encodeHexString (digest)'. – eckes

5

Przypuszczam używasz stosunkowo stare Java wersja bez SHA-256. Musisz więc dodać dostawcę BouncyCastle do już dostarczonych "dostawców zabezpieczeń" w swojej wersji 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 za wzmiankę o BouncyCastle, która dodaje całkiem sporo nowych MessageDigestów w porównaniu do stosunkowo marnej selekcji dostępnej w JDK. – mjuarez

-1

To będzie pracować z "org.bouncycastle.util.encoders.Hex" po opakowaniu

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

ITS w BouncyCastle słoika.

14

Nie potrzebujesz biblioteki BouncyCastle. Poniższy kod pokazuje, jak to zrobić za pomocą funkcji 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); 
    } 
} 

Specjalne podziękowania dla user1452273 z tego postu: How to hash some string with sha256 in Java?

Bądź dobrej pracy!

7

Java 8: Base64 dostępny:

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

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