Java sha256 ile bazı dize karma nasıl?


Yanıtlar:


308

SHA-256 bir "kodlama" değildir - tek yönlü bir karmadır.

Temel olarak dizeyi bayta dönüştürürsünüz (örneğin kullanarak text.getBytes(StandardCharsets.UTF_8)) ve sonra baytları toplarsınız. Karma sonucu olacağını Not da keyfi ikili veri olabilir ve bir dizede o temsil etmek istiyorsanız, ... base64 veya onaltılık kullanmalıdır yok kullanmayı deneyin String(byte[], String)yapıcısı.

Örneğin

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

18
"SHA-256 bir kodlama değil" kesinlikle doğru, ama ben şu anki sorunun başlığını "sha ile nasıl şifreleme" ye tercih ettiğimi söylemeliyim (çoğu şifreleme olduğunu düşünüyor). Belki de kriptografi ile ilgili bir şey yerine kodlama olarak ele almalıyız çünkü pratikte nasıl kullanıldığına daha yakın.
Luc

5
@Luc: Ben söylemek mantıksız olduğunu sanmıyorum bu yüzden Eh bu bir kriptografik hash gelmez şifreleme ... şifreleme ve şifreleme yöntemiyle değiştirilebilir değildir ilgisi var ...
Jon Skeet

8
Not: Java 7+'daki değişmez değer yerine StandardCharsets.UTF_8 kullanmak iyi bir fikirdir "UTF-8": endişelenmek için işaretlenmiş bir istisna daha az.
kryger

3
Hash sonucuyla uğraşırken neden String (byte [], String) yapıcısından kaçınmalısınız?
Isaac van Bakel

5
@IsaacvanBakel: Çünkü bir karma kodlanmış metin değil . Bu keyfi ikili verilerdir.
Jon Skeet

172

Bence en kolay çözüm Apache Common Codec kullanmaktır :

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

1
En iyi cevap, kullanımı kolay, temiz. Teşekkür ederim!
fl0w

99

Diğer bir alternatif ise Guava bir kolay kullanımlı paketi olan Karma yarar. Örneğin, SHA256'yı hex-string olarak kullanarak bir dizeyi hash etmek için yapmanız gerekenler:

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

85

Başka bir dize olarak hash to string tam örnek.

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
Jon'un sonuçlarını onaltılık olarak kodlamak için kendi kütüphanenizi döndürmek yerine apache commons gibi mevcut bir kütüphaneyi kullanmayı düşünün .
Leigh

1
Neden StringBuffer? (stringBuilder değil)? ve belki stringbuilder varsayılan boyutunu ayarlamak daha iyi olurdu?
Bogdan

36
@Yüksek: Bazı insanlar sadece tek bir işleve ihtiyaç duydukları için bütün bir lib bağımlılığı eklemek istemezler, bu yüzden kendi rollerinizi almak bazen iyi bir fikirdir.
Chris

4
@Chris - Doğru. Bu yüzden bunu kullanarak "düşün" dediğim ;-) Mevcut kütüphaneler toplu ekleyebilirsiniz. Kapak tarafında genellikle ev bükme kodundan daha yüksek test edilirler ve elbette zaman kazanırlar. Ancak herkese uygun tek bir cevap yoktur.
Leigh

1
Ayrıca kaynak kodu kütüphaneden okuyabilir ve kodunu kopyalayabilirsiniz!
Olav Grønås Gjerde

47

Java 8 kullanıyorsanız, kodlamak byte[]yaparak

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

1
Bu şekilde benim için uygun. Ancak, aşağıdaki Base64.encodeToString (hash, Base64.DEFAULT);
Motassem Jalal

@MotassemJalal Base64.DEFAULT, Java8'in en son sürümünde mevcut değil, şu anda jdk1.8.0_144 kullanıyorum, lütfen nasıl oluşturduğunuzu söyleyebilir misiniz?
rajadilipkolli

2
@rajadilipkolli Sanırım bu Android uygulaması: 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();
 }
}

Bir bayt değerini bitsel olarak & -inglemenin anlamı nedir 0xff? Hiçbir şey vermez, değil mi?
yktoo

2
@yktoo: Bunu pozitif bir tamsayıya dönüştürür (ne yazık ki bayt Java'da imzalanmıştır, maalesef) stackoverflow.com/questions/11380062/…
leonbloy

StringBuffer bir StringBuilder ile değiştirilebilir
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

Apache kodunu takip ettim DigestUtilsve sha256varsayılan olarak geri java.security.MessageDigesthesaplama için görünüyor . Apache bağımsız bir sha256çözüm uygulamaz . java.securityKütüphaneyle karşılaştırmak için bağımsız bir uygulama arıyordum . Sadece FYI.


3

Kotlin'i kullanmak benim yaklaşımımdı:

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

Merhaba, ben sadece kod denedim çünkü Android Studio'da bir şifre hash gerekir ve kodunuz böyle bir şey döndürür: [B@188363eşifrelenmiş şifre değil. Ayrıca, bu işlev her çağrıldığında farklı görünüyor.
Adrian2895

1
Düzeltildi, return hash.fold("", { str, it -> str + "%02x".format(it)})nesnenin kendisini değil şifrelenmiş parolayı döndüren şeyi unuttunuz .
Adrian2895

1
evet haklısın, yanıtı düzeltmenle güncelleyeyim. Teşekkür ederim :)
Samuel Luís

2

İşte özeti onaltılı bir dizeye dönüştürmenin biraz daha performanslı bir yolu:

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

Java'da daha hızlı bir yol bilen var mı?


1

MessageDigest'i aşağıdaki şekilde kullanabilirsiniz:

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

Java 8'de

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

Java'da, MessageDigest sınıfı şifreleme karma değerini hesaplamak için kullanılır. Bu sınıf, metnin karma değerini bulmak için kriptografik sağlama işlevi ( MD5 , SHA-1 ve SHA-256 ) sağlar.

SHA-256 algoritmasını kullanmak için kod örneği.

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

Ben hashing için kullanılmıştır:

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

Çıktı: 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;
}

Yukarıdaki yöntemi, aşağıdaki gibi farklı algoritmalarla çağırabilirsiniz.

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

Tam başvuru için bu bağlantıya başvurabilirsiniz .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.