İçeriğe geç
Programlama

Java ile MD5 ve SHA-256 Hash Hesaplama (MessageDigest)

Güncellendi: Son kontrol: Eylül 2026 6 dk okuma

Kısaca cevap

Java MD5 hash için MessageDigest.getInstance("MD5").digest(metin.getBytes(StandardCharsets.UTF_8)) yeterlidir; SHA-256 için algoritma adını "SHA-256" yapın. Sonucu Java 17+ HexFormat.of().formatHex(...) ile hex metne çevirin. MD5 ve SHA-256 veri doğrulama içindir, şifre saklamak için uygun değildir; şifreler için PBKDF2 kullanın. Kodlar Java 21 ile derlenip çalıştırıldı.

Bu sayfada

Java MD5 hash of string: MD5 ve SHA-256 değeri

Hash (özet) fonksiyonu, herhangi uzunluktaki veriden sabit uzunlukta bir değer üretir; aynı girdi her zaman aynı özeti verir ve özetten orijinal veri hesaplanamaz. Java'da bunun için java.security.MessageDigest sınıfı kullanılır:

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HexFormat;

public class HashOrnek {
    static String ozet(String algoritma, String metin) throws NoSuchAlgorithmException {
        MessageDigest md = MessageDigest.getInstance(algoritma);
        byte[] sonuc = md.digest(metin.getBytes(StandardCharsets.UTF_8));
        return HexFormat.of().formatHex(sonuc);
    }

    public static void main(String[] args) throws NoSuchAlgorithmException {
        System.out.println("MD5    : " + ozet("MD5", "merhaba"));
        System.out.println("SHA-256: " + ozet("SHA-256", "merhaba"));
    }
}
MD5    : c39436ee452e641cde2eb992ab397911
SHA-256: 4c6bcdd55f3153e1939669ab1ec039e4059174dc25abdfcb2f58868849b4d61b

Aynı metni Python ve C# ile özetlediğimizde de bu değerleri aldık. Sonucu sitedeki MD5 ve SHA-256 hash hesaplama aracıyla da karşılaştırabilirsiniz. HexFormat.of() küçük harf üretir; büyük harf gerekiyorsa HexFormat.of().withUpperCase() kullanın.

Neden StandardCharsets.UTF_8?

Eski örneklerde (bu sayfanın önceki sürümü dahil) metin.getBytes() parametresiz çağrılır. Bu çağrı sistemin varsayılan karakter kümesini kullanır. JEP 400 ile Java 18'den beri varsayılan UTF-8'dir, ama daha eski Java sürümlerinde Windows'ta farklı bir kod sayfası kullanılabilir. Türkçe karakterli metinler bu yüzden farklı makinelerde farklı özet verebilir. Karakter kümesini her zaman açıkça yazın.

Java MessageDigest SHA-256: bilmeniz gerekenler

  • Algoritma adları: Java'nın standart adları "MD5", "SHA-1", "SHA-256" ve "SHA-512" biçimindedir; tire önemlidir.
  • Zorunlu algoritmalar: Belgelere göre her Java platformu SHA-1 ve SHA-256'yı desteklemek zorundadır. MD5 bu listede yoktur; yaygın JDK'larda bulunur ama NoSuchAlgorithmException ihtimalini yakalamanız gerekir.
  • Parça parça besleme: update() birden fazla kez çağrılabilir; digest() sonucu verir ve nesneyi başlangıç durumuna döndürür.
  • İş parçacığı: Belgeler MessageDigest için eşzamanlı kullanım güvencesi vermez. Her iş parçacığında ayrı nesne alın.

Sık hata: baştaki sıfırın kaybolması

İnternette çok yaygın olan bir kısa yol, özeti BigInteger ile sayıya çevirip 16 tabanında yazmaktır. Özet 0 ile başlıyorsa bu sıfır kaybolur ve 32 yerine 31 karakterlik, yanlış bir değer elde edilir:

import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.HexFormat;

public class SifirHatasi {
    public static void main(String[] args) throws Exception {
        byte[] ozet = MessageDigest.getInstance("MD5")
            .digest("test".getBytes(StandardCharsets.UTF_8));

        System.out.println(new BigInteger(1, ozet).toString(16)); // hatalı
        System.out.println(HexFormat.of().formatHex(ozet));       // doğru
    }
}
98f6bcd4621d373cade4e832627b4f6
098f6bcd4621d373cade4e832627b4f6

İlk satır 31 karakterdir ve başka bir sistemin ürettiği özetle eşleşmez. HexFormat her baytı iki karakterle yazdığı için bu sorunu yaşamaz.

Java 8 ve 11 için hex dönüşümü

HexFormat Java 17 ile geldi. Daha eski bir sürüm kullanıyorsanız her baytı %02x biçimiyle, yani başına gerekirse sıfır ekleyerek iki karakter olarak yazın:

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;

public class EskiHex {
    public static void main(String[] args) throws Exception {
        byte[] ozet = MessageDigest.getInstance("MD5")
            .digest("test".getBytes(StandardCharsets.UTF_8));

        StringBuilder sb = new StringBuilder(ozet.length * 2);
        for (byte b : ozet) {
            sb.append(String.format("%02x", b));
        }
        System.out.println(sb);
    }
}
098f6bcd4621d373cade4e832627b4f6

Bu kodu Java 8 hedefiyle (javac --release 8) de derleyerek denedik; sonuç HexFormat ile aynı, 32 karakterdir.

Java MD5 file: dosyanın MD5 ve SHA-256 checksum değeri

İndirilen bir dosyanın bozulmadığını veya değiştirilmediğini kontrol etmek için dosyayı DigestInputStream ile okuyun. Dosya parça parça okunur, belleğe tamamen yüklenmez:

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HexFormat;

public class DosyaHash {
    static String dosyaOzeti(Path yol, String algoritma)
            throws IOException, NoSuchAlgorithmException {
        MessageDigest md = MessageDigest.getInstance(algoritma);
        try (InputStream in = new DigestInputStream(Files.newInputStream(yol), md)) {
            in.transferTo(OutputStream.nullOutputStream()); // okunan her bayt özete eklenir
        }
        return HexFormat.of().formatHex(md.digest());
    }

    public static void main(String[] args) throws Exception {
        Path dosya = Path.of("ornek.txt");
        System.out.println(dosyaOzeti(dosya, "MD5"));
        System.out.println(dosyaOzeti(dosya, "SHA-256"));
    }
}
ee71517ae5ffad6dfd4ddcc19af016a8
de208334b2d386b0f38c8f3123c149ace9cba507cbe33a89dd28958efb98ee4f

Örnekteki ornek.txt "merhaba" kelimesi ve bir satır sonu içerir; bu yüzden sonuç yukarıdaki metin özetinden farklıdır. Görünmeyen bir satır sonu bile özeti değiştirir.

Java MD5 checksum: sonucu komut satırıyla karşılaştırmak

Aynı dosyayı Windows'ta certutil -hashfile ornek.txt SHA256 ve PowerShell'de Get-FileHash ornek.txt -Algorithm MD5 komutlarıyla da özetledik; değerler Java çıktısıyla aynıydı. PowerShell sonucu büyük harfle yazar; karşılaştırmada equalsIgnoreCase kullanın. Linux ve macOS'ta sha256sum veya shasum -a 256 gibi komutlar da aynı işi görür. Kendi uygulamanızda bir güncelleme dosyasını doğruluyorsanız beklenen değeri dosyayla aynı sunucudan değil, ayrı ve güvenilir bir kanaldan alın; aksi hâlde dosyayı değiştirebilen biri özeti de değiştirebilir. Güvenlik açısından önemli bir dosyayı doğruluyorsanız yayıncı SHA-256 veriyorsa MD5 yerine onu kontrol edin: RFC 6151'e göre MD5, çakışma direnci gereken yerlerde artık kabul edilemez.

HmacSHA256: anahtarlı özet ile mesaj doğrulama

Düz bir özet verinin bozulmadığını gösterir ama kimin ürettiğini kanıtlamaz; veriyi değiştiren biri yeni özeti de hesaplayabilir. Webhook veya API isteklerinde mesajın gerçekten anahtarı bilen taraftan geldiğini doğrulamak için HMAC kullanılır. Java belgelerine göre her Java platformu HmacSHA1 ve HmacSHA256 algoritmalarını desteklemek zorundadır:

import java.nio.charset.StandardCharsets;
import java.util.HexFormat;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

public class HmacOrnek {
    public static void main(String[] args) throws Exception {
        byte[] anahtar = "gizli-anahtar".getBytes(StandardCharsets.UTF_8);
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(new SecretKeySpec(anahtar, "HmacSHA256"));

        byte[] imza = mac.doFinal("merhaba".getBytes(StandardCharsets.UTF_8));
        System.out.println(HexFormat.of().formatHex(imza));
    }
}
0aa2ac0fc13599bb2a993f0a26f83365bdf6b2c0004412bb8b0593664e03501b

Aynı anahtar ve mesajla Python ve C# da bu değeri verdi. Gelen imzayı kendi hesapladığınızla MessageDigest.isEqual ile karşılaştırın ve anahtarı kaynak koda değil, yapılandırmaya veya gizli anahtar deposuna koyun.

Şifre saklamak için MD5 değil PBKDF2

Eski yazılarda MD5 ile "şifreleme" yapılıp şifrelerin böyle saklanabileceği anlatılırdı. Hash şifreleme değildir ve MD5, SHA-256 gibi hızlı algoritmalar şifre saklamaya uygun değildir: sızan bir veritabanındaki özetler saniyede milyarlarca tahminle denenebilir. Java'da ek kütüphane gerektirmeyen seçenek, SecretKeyFactory ile PBKDF2'dir. OWASP Password Storage Cheat Sheet, PBKDF2-HMAC-SHA256 için 600.000 iterasyon önerir:

import java.security.MessageDigest;
import java.security.SecureRandom;
import java.security.spec.KeySpec;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;

public class Pbkdf2Ornek {
    static final int ITERASYON = 600_000; // OWASP: PBKDF2-HMAC-SHA256
    static final int ANAHTAR_BIT = 256;

    static byte[] turet(char[] sifre, byte[] tuz, int iterasyon) throws Exception {
        KeySpec spec = new PBEKeySpec(sifre, tuz, iterasyon, ANAHTAR_BIT);
        SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
        return f.generateSecret(spec).getEncoded();
    }

    public static void main(String[] args) throws Exception {
        byte[] tuz = new byte[16];
        new SecureRandom().nextBytes(tuz);

        byte[] kayitli = turet("Gizli-Parola-2026".toCharArray(), tuz, ITERASYON);

        byte[] deneme1 = turet("Gizli-Parola-2026".toCharArray(), tuz, ITERASYON);
        byte[] deneme2 = turet("yanlis-parola".toCharArray(), tuz, ITERASYON);
        System.out.println(MessageDigest.isEqual(kayitli, deneme1));
        System.out.println(MessageDigest.isEqual(kayitli, deneme2));
    }
}
true
false

Tuz her kullanıcı için SecureRandom ile ayrı üretilir ve özetle birlikte saklanır; gizli değildir. İterasyon sayısını da kayda yazarsanız ileride değeri artırdığınızda eski kayıtları doğrulamaya devam edebilirsiniz. MessageDigest.isEqual, belgelere göre süresi içeriğe değil yalnızca uzunluğa bağlı olan bir karşılaştırma yapar. Şifrenin String yerine char[] olarak verilmesi, işiniz bitince diziyi temizleyebilmenizi sağlar.

OWASP, mümkünse Argon2id'yi, o yoksa scrypt'i önerir; bunlar ve bcrypt için ayrı kütüphaneler bulunur. Algoritmaların karşılaştırması şifre saklama yazısında.

Dikkat edilmesi gerekenler

  • Karakter kümesini açıkça yazın: getBytes(StandardCharsets.UTF_8).
  • Hex dönüşümünü doğru yapın: BigInteger kısa yolunu kullanmayın.
  • Yeni işlerde SHA-256: MD5'i yalnızca eski sistemlerle uyumluluk gereken, güvenlik dışı sağlama işlerinde kullanın.

Aynı işlemlerin diğer dillerdeki karşılıkları: Python ile MD5 ve SHA-256 ve C# ile MD5 ve SHA-256. Hash kavramının kendisi için hash nedir, güvenli rastgele tuz ve şifre üretmek için Java ile güvenli şifre üretme yazısına bakabilirsiniz.

Sık sorulan sorular

Java'da bir string'in MD5 hash değeri nasıl alınır?

MessageDigest.getInstance("MD5") ile bir nesne alın, metni getBytes(StandardCharsets.UTF_8) ile bayta çevirip digest metoduna verin ve sonucu HexFormat.of().formatHex ile onaltılık metne dönüştürün. HexFormat Java 17 ile geldi; daha eski sürümlerde her baytı String.format("%02x", b) ile yazabilirsiniz.

Java MD5 çıktısı neden 31 karakter çıkıyor?

Özet new BigInteger(1, ozet).toString(16) ile metne çevrildiyse, baştaki sıfırlar sayı gösteriminde düşer. Örneğin "test" kelimesinin MD5 değeri 0 ile başlar ve bu yöntemle 31 karakter çıkar. HexFormat veya %02x biçimi her baytı iki karakterle yazdığı için bu sorun oluşmaz.

MessageDigest SHA-256 her Java sürümünde var mı?

Evet. Java belgelerine göre her Java platformu uygulaması SHA-1 ve SHA-256 algoritmalarını desteklemek zorundadır. MD5 bu zorunlu listede yer almaz; yaygın JDK'larda bulunsa da getInstance("MD5") çağrısının NoSuchAlgorithmException fırlatabileceğini hesaba katın.

Java ile bir dosyanın MD5 checksum değeri nasıl kontrol edilir?

Dosyayı DigestInputStream ile okuyup özetini hesaplayın ve yayıncının verdiği değerle büyük-küçük harf farkını gözetmeden karşılaştırın. Windows'ta certutil -hashfile dosya MD5 veya PowerShell Get-FileHash komutları da aynı değeri verir.

Şifreleri MD5 veya SHA-256 ile saklamak güvenli mi?

Hayır. Bu algoritmalar çok hızlıdır ve sızan özetler kısa sürede denenebilir. Java'da yerleşik seçenek SecretKeyFactory ile PBKDF2WithHmacSHA256'dır; her şifre için rastgele bir tuz ve yüksek bir iterasyon sayısı kullanın. OWASP, PBKDF2-HMAC-SHA256 için 600.000 iterasyon önerir.