Bagaimana cara hash beberapa string dengan sha256 di Jawa?

Jawaban:

308

SHA-256 bukan "encoding" - ini adalah hash satu arah.

Anda pada dasarnya akan mengubah string menjadi byte (misalnya menggunakan text.getBytes(StandardCharsets.UTF_8)) dan kemudian hash byte. Perhatikan bahwa hasil hash juga akan menjadi data biner yang berubah-ubah, dan jika Anda ingin menyatakan bahwa dalam sebuah string, Anda harus menggunakan base64 atau hex ... jangan mencoba menggunakan String(byte[], String)konstruktor.

misalnya

MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hash = digest.digest(text.getBytes(StandardCharsets.UTF_8));
Jon Skeet
sumber
18
"SHA-256 bukan encoding" benar sekali, tetapi saya harus mengatakan saya lebih suka judul pertanyaan saat ini daripada "bagaimana cara mengenkripsi dengan sha" (banyak yang berpikir itu enkripsi). Mungkin kita harus memperlakukannya sebagai penyandian dan bukan sesuatu yang berkaitan dengan kriptografi karena dalam praktiknya itu lebih dekat dengan bagaimana itu digunakan.
Luc
5
@Luc: Yah itu hash kriptografi, jadi saya tidak berpikir itu masuk akal untuk mengatakan itu tidak ada hubungannya dengan kriptografi ... enkripsi dan kriptografi tidak dipertukarkan ...
Jon Skeet
8
Catatan: adalah ide yang baik untuk menggunakan StandardCharsets.UTF_8 alih-alih "UTF-8"literal di Java 7+: satu pengecualian yang diperiksa lebih sedikit untuk dikhawatirkan.
kryger
3
Mengapa Anda harus menghindari konstruktor String (byte [], String) ketika berhadapan dengan hasil hash?
Isaac van Bakel
5
@IsaacvanBakel: Karena hash bukan teks yang disandikan. Ini data biner sewenang-wenang.
Jon Skeet
172

Saya pikir solusi termudah adalah menggunakan Apache Common Codec :

String sha256hex = org.apache.commons.codec.digest.DigestUtils.sha256Hex(stringText);   
seba
sumber
1
Jawaban terbaik, mudah digunakan, bersih. Terima kasih!
fl0w
99

Alternatif lain adalah Guava yang memiliki rangkaian utilitas Hashing yang mudah digunakan . Sebagai contoh, untuk hash string menggunakan SHA256 sebagai hex-string, Anda cukup melakukan:

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

Contoh lengkap hash to string sebagai string lain.

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);
    }
}
pengguna1452273
sumber
7
Untuk menyandikan hasil Jon sebagai hex, pertimbangkan untuk menggunakan pustaka yang ada seperti apache commons daripada menggulir milik Anda.
Leigh
1
Mengapa StringBuffer? (bukan stringBuilder)? dan mungkin akan lebih baik untuk mengatur ukuran default dari stringbuilder?
Bogdan
36
@ Leigh: beberapa orang tidak ingin menambahkan ketergantungan lib keseluruhan hanya karena mereka membutuhkan fungsi tunggal sehingga menggulirkan Anda sendiri kadang-kadang merupakan ide yang bagus.
Chris
4
@ Chris - Benar. Itu sebabnya saya berkata "pertimbangkan" menggunakannya ;-) Libib yang ada dapat menambah massal. Di sisi lain mereka biasanya lebih tinggi diuji daripada kode pintal rumah dan tentu saja menghemat waktu. Tetapi tidak ada jawaban satu ukuran untuk semua orang.
Leigh
1
Anda juga dapat membaca kode sumber dari pustaka dan menyalin kodenya!
Olav Grønås Gjerde
47

Jika Anda menggunakan Java 8, Anda dapat menyandikan byte[]dengan melakukan

MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hash = digest.digest(text.getBytes(StandardCharsets.UTF_8));
String encoded = Base64.getEncoder().encodeToString(hash);
Eduardo Dennis
sumber
1
Cara ini nyaman bagi saya. Namun, Anda harus menggunakan Base64.encodeToString berikut (hash, Base64.DEFAULT);
Motassem Jalal
@MotassemJalal Base64.DEFAULT tidak tersedia di versi terbaru Java8, saya saat ini menggunakan jdk1.8.0_144, bisakah Anda memberi tahu saya bagaimana Anda membuatnya?
rajadilipkolli
2
@rajadilipkolli Saya pikir ini adalah implementasi 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
sumber
Apa gunanya bitwise & -ing nilai byte dengan 0xff? Tidak menghasilkan apa-apa, bukan?
yktoo
2
@yktoo: Ini mengkonversinya menjadi bilangan bulat positif (byte masuk di Jawa, sayangnya) stackoverflow.com/questions/11380062/…
leonbloy
StringBuffer dapat digantikan oleh 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
sumber
7

Saya menelusuri kode Apache DigestUtilsdan sha256tampaknya kembali ke java.security.MessageDigestperhitungan default . Apache tidak menerapkan sha256solusi independen . Saya mencari implementasi independen untuk dibandingkan dengan java.securityperpustakaan. Hanya FYI.

Garyn
sumber
3

Ini adalah pendekatan saya menggunakan 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
sumber
Hai, saya baru saja mencoba kode Anda karena saya perlu mengaitkan kata sandi di Android Studio dan kode Anda mengembalikan sesuatu seperti ini [B@188363e:, bukan kata sandi yang dienkripsi. Plus, tampaknya berbeda setiap kali fungsi ini dipanggil.
Adrian2895
1
Diperbaiki, Anda lupa return hash.fold("", { str, it -> str + "%02x".format(it)})yang mengembalikan kata sandi terenkripsi dan bukan objek itu sendiri.
Adrian2895
1
ya Anda benar, izinkan saya memperbarui jawabannya dengan perbaikan Anda. Terima kasih :)
Samuel Luís
2

Berikut adalah cara yang sedikit lebih berkinerja untuk mengubah intisari menjadi string hex:

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

Adakah yang tahu cara yang lebih cepat di Jawa?

dan saya
sumber
1

Anda dapat menggunakan MessageDigest dengan cara berikut:

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();
}
orang itu
sumber
1

Di Jawa 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
sumber
0

Di Jawa, kelas MessageDigest digunakan untuk menghitung nilai hashing kriptografis. Kelas ini menyediakan fungsi hash kriptografis ( MD5 , SHA-1 dan SHA-256 ) untuk menemukan nilai hash teks.

Contoh kode untuk menggunakan algoritma 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
sumber
0

Ini yang saya gunakan untuk hashing:

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

Output: 5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8

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

Anda dapat memanggil metode di atas dengan algoritma yang berbeda seperti di bawah ini.

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

Anda dapat merujuk tautan ini untuk aplikasi lengkap.

Hari Krishna
sumber