MD5’i SHA-256’ya dönüştürme? Neden imkânsız ve ne yapmalı
Bunu vaat eden bir sürü sayfa var ve bazıları gerçekten çalışan araçlara benziyor. Oysa reklamını yaptıkları işlem diye bir şey yok. Nedenini bilmek işinize yarar, çünkü bundan sonra ne yapacağınızı değiştirir.
Kısa cevap: MD5’i SHA-256’ya (ya da SHA-256’yı MD5’e) dönüştüremezsiniz
MD5 özeti, kendisini üreten girdiyi içermeyen 128 bitlik bir çıktıdır. SHA-256’nın herhangi bir şey hesaplayabilmesi içinse tam olarak o girdi gerekir. Orijinal veri olmadan aradaki adım kalıcı olarak eksik kalır; hiçbir araç ya da kütüphane bu boşluğu doldurmaz.
Aynı girdinin üç algoritma altındaki hâli:
| Algoritma | hello özeti | Hex karakter | Bit |
|---|---|---|---|
| MD5 | 5d41402abc4b2a76b9719d911017c592 | 32 | 128 |
| SHA-1 | aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d | 40 | 160 |
| SHA-256 | 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824 | 64 | 256 |
Üç özete birer karakter dizisi olarak bakın. Ne ortak bir önekleri var ne ortak bir alt dizileri; aralarında aritmetik bir bağıntı da yok. Onları birbirine bağlayan tek şey hello kelimesi ve hiçbiri o kelimeyi taşımıyor. Yazdıkça ikisinin de birbirinden bağımsız değiştiğini görmek isterseniz MD5 özet üretici ve SHA-256 özet üretici ile kendiniz hesaplayın.
Yön de bir şey değiştirmiyor. SHA-256’dan MD5’e gitmek tam olarak aynı nedenle başarısız olur: iki fonksiyon da bilgiyi bilerek yok eder, dolayısıyla hiçbir özet, diğerinin ihtiyaç duyacağı girdiye geri götürülemez.
Bu aramayı kimse özet teorisine duyduğu meraktan yapmaz. Peki siz gerçekte ne yapmaya çalışıyordunuz? Uygulamada bu, dört işten biri oluyor ve her birinin çalışan bir cevabı var:
- Bir indirmeyi doğrulamak veya sağlama toplamlarını karşılaştırmak
- Bir parola veritabanını MD5’ten taşımak
- Bir özetin arkasındaki orijinal girdiyi geri elde etmek
- Aynı veriyi farklı bir algoritmayla özetlemek
Dördünü de aşağıda ele alıyoruz. Yalnız, dönüşüm vaat eden sayfaların ne yaptığını bilmek de işe yarar: kalıbı bir kez tanıdıktan sonra böyle bir sayfanın çıktısına güvenmezsiniz.
Bir “MD5’ten SHA-256’ya dönüştürücü” sayfası gerçekte ne yapar
Yalnızca üç olasılık var ve hiçbiri dönüşüm değil.
Birincisi, sizden orijinal metni ister. Bir karakter dizisi yapıştırırsınız, sayfa iki özeti birden üretir, tanıtım metni de buna dönüşüm der. Bu aslında yanıltıcı etiketli bir özet üreticidir: hiçbir şey dönüşmemiştir, girdi iki kez özetlenmiştir.
İkinci ihtimalde sayfa, özeti bir tabloda arar. Kelime listelerinden ve sızdırılmış kimlik bilgisi dökümlerinden toplanmış girdi-özet çiftlerinden oluşan bir tablo tutar. Girdisi o tabloda bulunan bir MD5 yapıştırdığınızda sayfa girdiyi bulur, ardından onu SHA-256 ile özetleyip sonucu size gösterir. Bu yöntem password, 123456 ve benzeri kısa karakter dizilerinden oluşan uzun bir kuyruk için işe yarar. Geri kalan her şeyde sessizce başarısız olur; bu sayfalar çoğu zaman hiçbir açıklama yapmadan boş sonuç döndürür.
Bir de hiçbir şey yapmayanlar var. Şaşırtıcı sayıda sayfa girdinizi olduğu gibi yeniden gösterir ya da yapıştırdığınız hex karakter dizisinin SHA-256’sını üretip bunun orijinal verinizin SHA-256’sı olduğunu ima eder. Bu iki değer farklıdır; aşağıdaki çift özetleme bölümü ne kadar farklı olduklarını tam olarak gösteriyor.
Bunu sınamak kolay. Sayfaya 32 karakterlik bir hex karakter dizisi verin, başka hiçbir şey vermeyin ve kendinize sorun: girdiyi bilmesinin herhangi bir yolu var mı? Buna rağmen 64 karakterlik bir sonuç döndürüp buna dönüşüm diyorsa, ya bir arama tablosunu sorguluyordur ya da size yalan söylüyordur. Orijinal verinizi hiç sormayan bir özet dönüştürücünün rastlantı dışında doğru olma ihtimali yoktur.
Bu iddianın ayakta kalmasının nedeni, gerçekten işleyen komşu bir işleme benzemesi. Karışıklık da tam orada başlıyor.
Özetleme, kodlama ve şifreleme: üçünden yalnızca ikisi geri döndürülebilir
Geliştiriciler bu üçüyle aynı hafta içinde karşılaşır ve hepsini zihinlerinde aynı çekmeceye koyar. Oysa tamamen farklı davranırlar:
| İşlem | Örnek | Geri döndürülebilir mi? | Neye ihtiyacınız var |
|---|---|---|---|
| Kodlama | Base64, hex, URL kodlaması | Evet, her zaman | Hiçbir şeye |
| Şifreleme | AES, RSA | Evet | Anahtara |
| Özetleme | MD5, SHA-1, SHA-256 | Asla | Hiçbir şey işe yaramaz |
Yanlış sezgiyi öğreten şey Base64’tür. Herkes anahtar da izin de olmadan bir Base64 karakter dizisini çözüp baytlarına geri döndürebilir; Base64’ü hex’e çevirmek de meşru, gündelik bir işlemdir. İkisi de aynı baytların alternatif yazılışlarıdır. Bunun işlediğini gördüyseniz, “MD5’ten SHA-256’ya” da aynı türden bir yeniden yazım gibi geliyor.
Değil. Kodlama girdinin her bitini korur, şifreleme onu bir anahtarın arkasında saklar, özetleme ise neredeyse tamamını atar. İster bir parola verin ister 40 GB’lık bir disk imajı, MD5 özeti 16 bayttır. O 40 GB akıllıca bir yere gitmedi; yok oldu. Şifrelemeyle karşılaştırmayı daha ayrıntılı isterseniz MD5 aracının SSS bölümü bunu ele alıyor, ama burada tek cümlelik hâli yeterli: ortada anahtar yok, dolayısıyla çözülecek bir şey de yok.
”MD5 kırıldı” ile “MD5 geri döndürülebilir” aynı şey değil
Dürüst yazıların bile karıştırdığı nokta bu. İnsanlar “MD5 yıllar önce kırıldı” cümlesinden doğrudan “o hâlde birileri artık bunu geri alabiliyordur” sonucuna atlıyor.
Burada birbirinden farklı iki saldırı söz konusu:
- Çarpışma saldırısı, aynı özeti üreten iki farklı girdi bulur. Saldırgan iki girdiyi de kendi seçer ve ne olduklarını umursamaz.
- Öngörüntü saldırısı ise bir özetten yola çıkar ve onu üreten bir girdiyi geri elde eder. MD5’i SHA-256’ya dönüştürmenizi sağlayacak olan saldırı budur, çünkü size SHA-256’ya verebileceğiniz bir şeyi geri kazandırır.
MD5’in çarpışma direnci 2004’te düştü; bugün sıradan bir donanımda saniyeler içinde çarpışma üretilebiliyor. MD5’in imzalar, sertifikalar ve bir saldırganın etkileyebileceği her şey için uygunsuz olmasının nedeni bu.
MD5’in öngörüntü direnci ise düşmedi. Bilinen en iyi öngörüntü saldırısı hâlâ teorik ve karmaşıklığı 2^123.4 (Sasaki ve Aoki, 2009). Bu, kaba kuvvetten kıl payı daha hızlı ve önemli olan hiçbir ölçekte erişilebilir değil. Ne 2004’te ne bugün, keyfi MD5 özetlerini tersine çeviren kimse var.
Yani iki olgu birbiriyle çelişmeden yan yana durur: MD5 kırıktır ve MD5 hâlâ geri döndürülemez. Buradaki sonuç kırılmadan hiç etkilenmez. İki algoritma arasında dönüşüm yapmaya çalışmak yerine yeni bir sistem için aralarında seçim yapıyorsanız, MD5 vs SHA-256 karşılaştırması o kararı ayrıntısıyla ele alıyor.
Dört olası ihtiyaç ve her birinin gerçek cevabı
| Gerçekte ne yapıyorsunuz | Asıl cevap |
|---|---|
| Bir indirmeyi doğrulamak veya sağlama toplamlarını karşılaştırmak | İhtiyacınız olan algoritmayla dosyadan yeniden hesaplayın |
| MD5 parola özetlerini taşımak | Onları bcrypt ile sarın ve girişte yükseltin |
| Orijinal girdiyi geri elde etmek | Bu, dönüştürme değil kırma işidir ve entropiye bağlıdır |
| Aynı veriyi başka bir algoritmayla yeniden özetlemek | Kaynak baytlara geri dönün |
Görev 1: sağlama toplamlarını karşılaştırıyorsunuz veya bir indirmeyi doğruluyorsunuz
Dönüştürmeyin, yeniden hesaplayın. Dosya diskinizde duruyor; yani özetin kaybettiği tek şey elinizde. İhtiyacınız olan algoritmayı doğrudan dosya üzerinde çalıştırın:
# GNU coreutils
md5sum ubuntu-24.04-desktop-amd64.iso
sha256sum ubuntu-24.04-desktop-amd64.iso
# macOS
md5 ubuntu-24.04-desktop-amd64.iso
shasum -a 256 ubuntu-24.04-desktop-amd64.iso
İnsanların takıldığı uyuşmazlık şu: yayıncı yalnızca bir MD5 yayımlamışken güvenlik politikanız SHA-256 istiyor. Yayımlanan MD5’i dönüştürmek, mümkün olsaydı bile hiçbir şey kanıtlamazdı; çünkü başka bir özetten türettiğiniz bir özet, yayıncının dosya hakkındaki beyanı değildir. İhtiyacınız olan şey, yayıncının imzaladığı bir SHA-256’dır. Yayıncı böyle bir değer sunmuyorsa, SHA-256 özet üretici ile kendi SHA-256’nızı hesaplamak yine de dahili kullanım için kararlı bir parmak izi verir: bu değeri sabitleyip aynalar arasında karşılaştırabilir, sonraki değişiklikleri fark edebilirsiniz. Yalnızca yayıncının beyanının yerini tutmaz.
Görev 2: MD5 kullanan bir parola veritabanını taşıyorsunuz
Riskin en yüksek olduğu iş bu ve çok denenmiş bir çözümü var: eski özetleri sarın, ardından her hesabı girişte saydam biçimde yükseltin. Tek bir toplu işte, saklanan her MD5 özetini bcrypt’ten geçirirsiniz; o andan sonra giriş yolu, gönderilen parolanın önce MD5’ini alır ve bunu bcrypt kaydıyla karşılaştırır.
Önce bir uyarı, çünkü eski tavsiyelerin çoğu bunu ters anlıyor. MD5’i SHA-256’nın içine sarmak parola saklamayı güvenli hâle getirmez. SHA-256 hızlı bir özet fonksiyonudur, yani MD5 ile aynı sorun sınıfındadır ve GPU’lar ikisini de muazzam hızlarda öğütür. Çözüm diye sizi bir veritabanının yerleşik SHA2() fonksiyonuna yönlendiren tavsiyeler yanlış sorunu çözüyor. Hedef, kasıtlı olarak yavaş bir özet fonksiyonudur: bcrypt, scrypt veya Argon2. bcrypt(md5(password)) saklayın, asla sha256(md5(password)) değil. Üçü arasında nasıl seçim yapacağınızı bcrypt, Argon2 ve scrypt karşılaştırması anlatıyor; bcrypt oluşturucu ise birine karar vermeden önce iş faktörlerini denemenizi sağlıyor.
Taşımaları asıl bozan kısım burası. “Parolanın MD5’i” ifadesi belirsizdir; iki farklı okuması farklı sonuçlar üretir:
const { createHash } = require('node:crypto');
const md5Hex = createHash('md5').update('hello').digest('hex');
const md5Raw = createHash('md5').update('hello').digest(); // the same value as 16 bytes
createHash('sha256').update(md5Hex).digest('hex');
// 4914e23374bb211e3dca0df7636fefffc7fedd94f1340ae81c7d6c07b7113e9b
createHash('sha256').update(md5Raw).digest('hex');
// 88e20f0abb88153e3f0a9683668ccb5b84ed771817dc448a2b73254ed02c8d8c
createHash('sha256').update('hello').digest('hex');
// 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
Üç sonuç; hepsi doğru, hepsi farklı. 32 karakterlik hex karakter dizisini özetlersiniz, bir değer çıkar; onun temsil ettiği 16 ham baytı özetlersiniz, başka bir değer çıkar; orijinal parolayı özetlersiniz, üçüncü bir değer çıkar. Bir kural seçin, yazıya dökün ve aynısını hem taşıma betiğinde hem giriş yolunda kullanın. Bunu yanlış yapmak tüm kullanıcıları aynı anda dışarıda bırakır ve belirti, bir kodlama kararı gibi değil bcrypt hatası gibi görünür.
bcrypt sarmalayıcısı için hex daha güvenli kuraldır. Ham özet baytları sıfır bayt içerebilir ve bazı bcrypt uygulamaları girdilerini bir C karakter dizisi gibi ele alıp orada okumayı bırakır. Hex bunu tamamen ortadan kaldırır ve 32 karakteriyle bcrypt’in girdi uzunluğu sınırının epey altında kalır. Büyük-küçük harf durumunu da tektipleştirin: 5D41402A... ile 5d41402a... aynı özet olsalar bile bcrypt için farklı karakter dizileridir.
const bcrypt = require('bcrypt');
const { createHash } = require('node:crypto');
const legacyDigest = (password) =>
createHash('md5').update(password, 'utf8').digest('hex'); // lowercase hex
// Batch job, run once: wrap each stored MD5, then drop the old column.
async function wrapRow(row) {
return bcrypt.hash(row.md5_hash.toLowerCase(), 12);
}
// Login path
async function verify(password, row) {
if (row.scheme === 'bcrypt') {
return bcrypt.compare(password, row.hash);
}
const ok = await bcrypt.compare(legacyDigest(password), row.hash);
if (ok) {
const upgraded = await bcrypt.hash(password, 12);
await saveCredential(row.id, { scheme: 'bcrypt', hash: upgraded }); // your DB write
}
return ok;
}
Hesaplar, sahipleri giriş yaptıkça düz bcrypt’e geçer. Geride kalanlar için bir son tarih belirleyin ve o tarihten sonra sıfırlamayı zorunlu kılın.
Görev 3: orijinal girdiyi geri elde etmeye çalışıyorsunuz
Bunu en azından kendinize açıkça söyleyin, çünkü hem araç seçimini hem beklentileri değiştirir. Bir özetten girdiyi geri elde etmek dönüştürme değil kırma işidir ve işe yarayıp yaramaması, özeti hangi algoritmanın ürettiğiyle ilgisizdir. Girdiye bağlıdır.
İnsanların seçtiği kısa, yaygın karakter dizileri hızla düşer. Sözlük kelimeleri, sonuna rakam eklenmiş isimler ve herhangi bir sızıntı derlemesinde geçmiş her şey bir tablo aramasına ya da kısa bir kaba kuvvet denemesine yenilir. Uzun rastgele karakter dizileri ise hiç düşmez ve iki durum arasındaki fark, daha fazla donanım satın alarak kapatılacak türden değildir.
Bir rainbow table, girdiyi yalnızca o girdi salt olmadan özetlendiyse ve tabloda zaten varsa geri elde eder. İki koşul da gereklidir. Kullanıcı başına bir salt ekleyin, önceden hesaplanmış tablo değersizleşir: saldırganın artık her salt için ayrı bir tabloya ihtiyacı olur. Özet fonksiyonuna 128 bitlik rastgele bir token verin, dünyada onu içeren tek bir tablo bulunmaz. Sınırın tam olarak nerede durduğunu sayılarla parola entropy’si rehberi gösteriyor.
Girdi size ait bir parolaysa ve onu yeniden üretemiyorsanız, bunu bir kurtarma değil sıfırlama olarak ele alın. Başkasına aitse, işin adı yukarıda yazdığı gibidir.
Görev 4: aynı veriye farklı bir algoritmayla özet almanız gerekiyor (“md5 to sha1 converter”)
Birinci görevin genelleştirilmiş hâli. Talepteki algoritma çifti önemli değildir, çünkü cevap her zaman kaynak baytlara dönüp onları yeniden özetlemektir:
sha1sum payload.bin
sha256sum payload.bin
Bulacağınız her “md5 to sha1 converter”, yukarıda anlatılan aynı nedenlerle ya yeniden özetleyicidir ya da bir arama tablosudur. Orijinal veri elinizde yoksa bu işin çözümü yoktur ve bu, mevcut araçların bir kısıtı değildir. Hedef algoritmayı SHA ailesi karşılaştırması ile seçin; SHA-1 özet üretici ise hâlâ SHA-1 isteyen eski sistemler için orada duruyor, yeni hiçbir sistemin buna ihtiyacı olmamalı.
Özet arama işleminin gerçekten işe yaradığı tek durum
Bazı veri sınıfları merkezî olarak toplanır ve yaygın özetlerin hepsiyle aynı anda dizinlenir. Bunun en bilinen durumu zararlı yazılım örnekleri. VirusTotal gibi hizmetler dosyanın kendisini saklar; yani MD5’ini, SHA-1’ini ve SHA-256’sını aynı baytlardan hesaplamış ve üçünü tek bir kayda işlemiştir. Bir örneğin MD5’ini orada aratırsanız SHA-256’sını geri alırsınız.
Bu, dönüşüm değil bir veritabanı join işlemidir. İşe yaramasının nedeni, birinin orijinal dosyayı elinde tutup her algoritmayla özetlemiş olması; yani yukarıda anlatılan yeniden hesaplama adımı, yalnızca üçüncü bir tarafça önceden yapılmış hâli. Koşullar katı: nesnenin dizinde zaten bulunması ve dizini kuran tarafa güvenmeniz gerekir. Tehdit istihbaratı süreçleri her gün buna dayanıyor, ama bu durum keyfi MD5 özetleri hakkında hiçbir şey söylemez ve kendi verinizin özetinde size asla yardımcı olmaz.
Mekanizma, şaibeli dönüştürücü sayfalarının kullandığının aynısı. Fark şu: zararlı yazılım deposu size bunun bir arama olduğunu söyler ve kaydı gösterir.
Kendiniz deneyin
Aynı girdinin iki özetinin birbirinden ne kadar bağımsız çıktığını doğrudan görün:
$ printf 'hello' | md5sum
5d41402abc4b2a76b9719d911017c592 -
$ printf 'hello' | sha256sum
2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824 -
Tek bir karakteri değiştirin; iki çıktı da birbiriyle hiçbir ilgisi olmayan biçimlerde tamamen değişir. Bunu canlı görmek için aynı metni yan yana MD5 özet üretici ve SHA-256 özet üretici araçlarına yapıştırın; bir API isteğini imzalamak için anahtarlı bir özete ihtiyacınız varsa HMAC üretici aracına uzanın. Üçü de tamamen tarayıcınızda çalışır.
SSS
MD5’i SHA-256’ya dönüştürebilir misiniz?
Hayır. MD5 özeti orijinal girdiyi içermez ve SHA-256’nın herhangi bir şey üretebilmesi için o girdi gerekir. Dönüştürdüğünü iddia eden her sayfa, ya sizin verdiğiniz metni yeniden özetliyordur ya da değeri önceden hesaplanmış çiftlerden oluşan bir veritabanında arıyordur.
Neden bu kadar çok site “MD5’ten SHA-256’ya dönüştürücü” sunuyor?
İnsanların yazdığı bir aramada üst sıralara çıkıyorlar. Sayfaya vardığınızda ya sizden orijinal metniniz isteniyor (bu dönüşüm değil, yeniden özetlemedir) ya da işe yarar hiçbir şey dönmüyor. Yanlış anlama yaygın olduğu için de iddia ayakta kalıyor.
SHA-256’yı MD5’e geri dönüştürmek mümkün mü?
Hayır ve yön fark etmez. İkisi de tek yönlü fonksiyondur; dolayısıyla orijinal girdi olmadan hiçbir özet diğerine çevrilemez. Ters yolculuğu sunan bir araç, aynı arama ya da yeniden özetleme numarasını çeviriyordur.
MD5 kırıldı, o hâlde geri döndürülebilir olması gerekmez mi?
Hayır. MD5’in çarpışma direnci 2004’te düştü; yani iki girdinin aynı özeti paylaşması zorlanabiliyor. Bir özeti geri döndürmek ise öngörüntü saldırısıdır ve bilinen en iyisi hâlâ 2^123.4 işlem gerektirir. İmzalar için kırık, ama hâlâ tersine çevrilemez.
MD5 parola özetlerinden oluşan bir veritabanını daha güvenli bir şeye nasıl taşırım?
MySQL’de akla ilk gelen tek satırlık çözüm olan UPDATE users SET password = SHA2(password, 256) yanlıştır; hesapladığı özet parolanın değil, saklanan MD5 özetinindir. Bunun yerine bcrypt(md5(password)) saklayın ve doğrulamayı aynı sarmalayıcı üzerinden yapın; her kaydı bir sonraki başarılı girişte yükseltin. MD5’i SHA-256’nın içine sarmak işe yaramaz, çünkü ikisi de hızlı özet fonksiyonudur ve bir GPU her ikisini de aynı acımasız hızda işler.
Çift özetleme neden beklediğimden farklı bir sonuç verdi?
MD5’in hex karakter dizisini özetlemekle onun 16 ham baytını özetlemek farklı SHA-256 çıktıları üretir. İkisi de geçerlidir; yalnızca farklı girdilerdir. Bir kural seçin ve onu taşıma betiğinde de giriş yolunda da birebir aynı şekilde uygulayın.
Bir rainbow table, MD5 özetinin arkasındaki girdiyi geri elde edebilir mi?
Yalnızca girdi salt’sız özetlendiyse ve tabloda zaten varsa; pratikte bu, kısa ya da yaygın karakter dizileri demektir. Uzun rastgele girdiler bu yolla geri elde edilemez ve kullanıcı başına salt eklemek önceden hesaplanmış tabloları tamamen etkisiz kılar.
MD5 SHA-1 dönüştürücü diye bir araç var mı?
Hayır. Her “MD5 SHA-1 dönüştürücü”, yukarıda anlatılan nedenlerle ya yeniden özetleyicidir ya da bir arama tablosudur; aynı tek yönlülük MD5’ten SHA-1’e giden yolu da SHA-256’ya giden yol kadar kapatır. Orijinal girdi elinizdeyse SHA-1 özet üretici ile yeniden hesaplayabilirsiniz; girdi yoksa hiçbir şey bunu yapamaz.