Türkiye'de ilk Mobil & PC Aynı Anda Metin2 Oyna. Triarchonline kalıcı ve uzun ömürlü yapısı ile 24 Temmuz'da açılıyor. | 1-99 Mobil Metin2 Triarch HEMEN TIKLA!
[NODE JS] Crypto ile SHA-256 Hash Üretme
Hash fonksiyonları, yazılım dünyasının her köşesinde karşımıza çıkar. Dosya bütünlüğü kontrolü, dijital imzalar, blockchain, veri yapıları ve daha birçok alanda kullanılırlar. SHA-256 (Secure Hash Algorithm 256-bit), günümüzde en yaygın kullanılan hash algoritmalarından biridir. Bitcoin blockchain'i bile SHA-256 üzerine kuruludur. Node.js'in crypto modülü ile SHA-256 hash'leri üretmek son derece basittir ama arka planda neler olduğunu anlamak önemlidir.
SHA-256, herhangi bir boyuttaki girdiyi alır ve sabit 256-bit (32 byte, 64 hex karakter) uzunluğunda bir çıktı üretir. Bu çıktı deterministiktir: aynı girdi her zaman aynı hash'i üretir. Ama girdide tek bir bit bile değişse, çıktı tamamen farklı olur. Bu özelliğe çığ etkisi (avalanche effect) denir ve hash fonksiyonlarının güvenliğinin temelidir.
Hash fonksiyonları tek yönlüdür. Hash'ten orijinal veriyi geri elde etmek matematiksel olarak imkânsızdır. Bu, bcrypt ile aynı prensiptir ama SHA-256 genel amaçlı bir hash fonksiyonudur, şifre hashleme için tasarlanmamıştır. Şifreler için bcrypt, scrypt veya Argon2 kullanın. SHA-256'yı dosya bütünlüğü, veri doğrulama, mesaj imzalama gibi amaçlarla kullanın.
Pratikte SHA-256'yı en sık şu senaryolarda kullanıyorum: API isteklerini imzalama, dosya hash'i hesaplama (indirilen dosyanın bozuk olup olmadığını kontrol etme), veritabanı kayıtlarının bütünlüğünü doğrulama, webhook doğrulama ve önbellek anahtarı oluşturma. Özellikle webhook doğrulaması önemlidir. Stripe, GitHub, Shopify gibi servisler webhook'larını HMAC-SHA256 ile imzalar ve siz bu imzayı doğrulayarak isteğin gerçekten o servisten geldiğini teyit edersiniz.
HMAC (Hash-based Message Authentication Code), SHA-256'nın gizli bir anahtar ile birlikte kullanılan versiyonudur. Sadece hash değil, aynı zamanda mesajın belirli bir anahtar sahibi tarafından üretildiğini de kanıtlar. HMAC, webhook doğrulama, API imzalama ve mesaj bütünlüğü kontrolü için standart yöntemdir.
Büyük dosyaların hash'ini hesaplarken dikkatli olmanız gerekir. Tüm dosyayı belleğe okuyup hashlemek, büyük dosyalarda bellek sorunlarına yol açar. Bunun yerine stream tabanlı yaklaşım kullanmalısınız. Node.js'in crypto.createHash() fonksiyonu bir Transform stream'dir, yani dosyayı parça parça okuyarak hash hesaplayabilirsiniz. Bu yaklaşım ile gigabyte'larca büyüklükteki dosyaların hash'ini birkaç megabyte bellek kullanarak hesaplayabilirsiniz.
Performans açısından SHA-256, modern işlemcilerde saniyede yüzlerce megabyte veriyi hashleyebilir. SHA-256 donanım hızlandırması sunan işlemcilerde (Intel SHA Extensions) bu rakam daha da yükselir. Node.js'in crypto modülü OpenSSL üzerinden çalıştığı için bu donanım optimizasyonlarından otomatik olarak yararlanır.
Bir diğer kullanım alanı da veri deduplikasyonu'dur. Depolama sistemlerinde aynı dosyanın birden fazla kopyasını saklamak israf olur. Her dosyanın SHA-256 hash'ini hesaplayarak, aynı hash'e sahip dosyaları tespit edebilir ve sadece bir kopyasını saklayabilirsiniz. Bu yöntem, bulut depolama ve yedekleme sistemlerinde yaygın olarak kullanılır.
JavaScript:
// ==============================
// SHA-256 Hash Üretme Temelleri
// ==============================
const crypto = require('crypto');
const fs = require('fs');
const path = require('path');
// ==============================
// Basit String Hash'leme
// ==============================
function sha256Hash(veri) {
return crypto
.createHash('sha256')
.update(veri, 'utf8')
.digest('hex');
}
// Örnekler
console.log('=== SHA-256 Hash Örnekleri ===
');
const metin1 = 'Merhaba Dünya!';
const metin2 = 'Merhaba dünya!'; // Sadece büyük D -> küçük d
const metin3 = 'Merhaba Dünya!'; // metin1 ile aynı
console.log(`"${metin1}" => ${sha256Hash(metin1)}`);
console.log(`"${metin2}" => ${sha256Hash(metin2)}`);
console.log(`"${metin3}" => ${sha256Hash(metin3)}`);
console.log(`
metin1 ve metin3 eşit mi: ${sha256Hash(metin1) === sha256Hash(metin3)}`);
console.log(`metin1 ve metin2 eşit mi: ${sha256Hash(metin1) === sha256Hash(metin2)}`);
// ==============================
// HMAC-SHA256 ile Mesaj İmzalama
// ==============================
function hmacOlustur(mesaj, gizliAnahtar) {
return crypto
.createHmac('sha256', gizliAnahtar)
.update(mesaj, 'utf8')
.digest('hex');
}
function hmacDogrula(mesaj, gizliAnahtar, beklenenImza) {
const hesaplananImza = hmacOlustur(mesaj, gizliAnahtar);
// Timing-safe karşılaştırma
const imza1 = Buffer.from(hesaplananImza, 'hex');
const imza2 = Buffer.from(beklenenImza, 'hex');
if (imza1.length !== imza2.length) return false;
return crypto.timingSafeEqual(imza1, imza2);
}
console.log('
=== HMAC-SHA256 İmzalama ===
');
const gizliAnahtar = 'benim-gizli-anahtarim-256-bit';
const mesaj = JSON.stringify({ kullanici: 'ahmet', islem: 'odeme', tutar: 150.00 });
const imza = hmacOlustur(mesaj, gizliAnahtar);
console.log('Mesaj:', mesaj);
console.log('İmza:', imza);
console.log('Doğrulama:', hmacDogrula(mesaj, gizliAnahtar, imza));
// ==============================
// Webhook Doğrulama Örneği
// ==============================
function webhookDogrula(payload, imzaHeader, webhookSecret) {
const beklenenImza = crypto
.createHmac('sha256', webhookSecret)
.update(payload, 'utf8')
.digest('hex');
const tamImza = 'sha256=' + beklenenImza;
// Timing-safe karşılaştırma
try {
return crypto.timingSafeEqual(
Buffer.from(tamImza),
Buffer.from(imzaHeader)
);
} catch (hata) {
return false;
}
}
// Express middleware olarak webhook doğrulama
function webhookMiddleware(webhookSecret) {
return (req, res, next) => {
const imza = req.headers['x-hub-signature-256'];
if (!imza) {
return res.status(401).json({ hata: 'İmza eksik.' });
}
const gecerli = webhookDogrula(JSON.stringify(req.body), imza, webhookSecret);
if (!gecerli) {
return res.status(403).json({ hata: 'Geçersiz imza.' });
}
next();
};
}
// ==============================
// Dosya Hash'i Hesaplama (Stream)
// ==============================
function dosyaHashHesapla(dosyaYolu) {
return new Promise((resolve, reject) => {
const hash = crypto.createHash('sha256');
const akis = fs.createReadStream(dosyaYolu);
akis.on('data', (parca) => {
hash.update(parca);
});
akis.on('end', () => {
const sonuc = hash.digest('hex');
console.log(`Dosya: ${path.basename(dosyaYolu)}`);
console.log(`SHA-256: ${sonuc}`);
resolve(sonuc);
});
akis.on('error', (hata) => {
reject(hata);
});
});
}
// ==============================
// Checksum ile Bütünlük Kontrolü
// ==============================
class ButunlukKontrolcusu {
constructor() {
this.checksumlar = new Map();
}
async dosyaKaydet(dosyaYolu) {
const hash = crypto.createHash('sha256');
const icerik = fs.readFileSync(dosyaYolu);
const checksum = hash.update(icerik).digest('hex');
this.checksumlar.set(dosyaYolu, checksum);
console.log(`Checksum kaydedildi: ${path.basename(dosyaYolu)} => ${checksum.substring(0, 16)}...`);
return checksum;
}
async dosyaKontrolEt(dosyaYolu) {
const kaydedilenChecksum = this.checksumlar.get(dosyaYolu);
if (!kaydedilenChecksum) {
console.log('Bu dosya için kayıtlı checksum yok.');
return false;
}
const hash = crypto.createHash('sha256');
const icerik = fs.readFileSync(dosyaYolu);
const mevcutChecksum = hash.update(icerik).digest('hex');
const butunMu = kaydedilenChecksum === mevcutChecksum;
console.log(`Bütünlük kontrolü: ${butunMu ? 'BAŞARILI' : 'BAŞARISIZ'}`);
return butunMu;
}
}
// ==============================
// Hash Tabanlı Önbellek Anahtarı
// ==============================
function onbellekAnahtariOlustur(sorgu, parametreler) {
const veri = JSON.stringify({ sorgu, parametreler });
return 'cache:' + sha256Hash(veri).substring(0, 16);
}
console.log('
=== Önbellek Anahtarı ===
');
const anahtar1 = onbellekAnahtariOlustur('SELECT * FROM kullanicilar', { limit: 10 });
const anahtar2 = onbellekAnahtariOlustur('SELECT * FROM kullanicilar', { limit: 20 });
console.log('Anahtar 1:', anahtar1);
console.log('Anahtar 2:', anahtar2);
SHA-256, veri bütünlüğü ve doğrulama için güvenilir bir araçtır. HMAC ile birlikte kullanıldığında mesaj kimlik doğrulaması sağlar. Dosya hash'leri için stream yaklaşımını kullanın, webhook'ları mutlaka doğrulayın ve timing-safe karşılaştırma yapın. Ancak şifreleme için SHA-256 tek başına yeterli değildir, şifre saklamak için bcrypt kullanın. Her aracın doğru kullanım alanı vardır ve bu ayrımı bilmek güvenli yazılım geliştirmenin temelidir.
