3-bo‘lim
Xesh funksiyalari
Bir tomonlama funksiyalar, ko'chki effekti, to'qnashuvlar va nima uchun SHA-256 parol uchun yaramaydi.
Ushbu bo‘lim mundarijasi
Xesh funksiyasi - istalgan uzunlikdagi ma'lumotni qat'iy uzunlikdagi qiymatga aylantiruvchi funksiya.
U shifrlash emas: natijani qaytarib bo'lmaydi.
Asosiy xususiyatlar #
function xeshKorsat(string $nom, string $qiymat, string $algo = 'sha256'): void
{
printf("%-22s %s%s", $nom, hash($algo, $qiymat), PHP_EOL);
}
// 1. Aniqlik: bir xil kirish - har doim bir xil chiqish
xeshKorsat('birinchi marta', 'Salom');
xeshKorsat('ikkinchi marta', 'Salom');
// 2. Qat'iy uzunlik: kirish hajmi ahamiyatsiz
$qisqa = hash('sha256', 'a');
$uzun = hash('sha256', str_repeat('a', 1000000));
echo 'bir belgi: ', strlen($qisqa), ' hex belgi', PHP_EOL;
echo 'million belgi:', strlen($uzun), ' hex belgi', PHP_EOL;
birinchi marta 441f71d48aacacdc18293201da2bfda40a421c4f93d8e509fcd2d0440b007b46
ikkinchi marta 441f71d48aacacdc18293201da2bfda40a421c4f93d8e509fcd2d0440b007b46
bir belgi: 64 hex belgi
million belgi:64 hex belgi
Ko'chki effekti #
Kirishning bitta biti o'zgarsa, natijaning taxminan yarmi o'zgaradi:
$a = hash('sha256', 'Salom', true);
$b = hash('sha256', 'Talom', true); // S -> T, bitta harf
echo 'a: ', bin2hex($a), PHP_EOL;
echo 'b: ', bin2hex($b), PHP_EOL;
// nechta bit farq qilgan?
$farq = 0;
for ($i = 0; $i < strlen($a); $i++) {
$xor = ord($a[$i]) ^ ord($b[$i]);
$farq += substr_count(decbin($xor), '1');
}
printf('jami bit: %d%s', strlen($a) * 8, PHP_EOL);
printf('farq qilgan: %d bit%s', $farq, PHP_EOL);
printf('foiz: %.1f%%%s', $farq / (strlen($a) * 8) * 100, PHP_EOL);
a: 441f71d48aacacdc18293201da2bfda40a421c4f93d8e509fcd2d0440b007b46
b: 40ca9baef6ce07202257706cb661c5bcfb3d3df89591d130bff0edb97a6c58d5
jami bit: 256
farq qilgan: 128 bit
foiz: 50.0%
Bitta harf o'zgarishi natijani butunlay o'zgartirdi. Bu ko'chki effekti (avalanche effect).
Agar u bo'lmasa, o'xshash kirishlar o'xshash xesh berardi. Shunda hujumchi xeshga qarab kirish haqida taxmin qila olardi.
Yaxshi xesh funksiyada:
| Talab | Ma'nosi |
|---|---|
| Aniqlik | Bir xil kirish - bir xil chiqish |
| Tez hisoblanish | Katta fayl uchun ham amaliy |
| Bir tomonlama | Xeshdan kirishni tiklash imkonsiz |
| Ikkinchi asl nusxaga chidamlilik | Berilgan x uchun hash(y) = hash(x) bo'ladigan y topilmasin |
| To'qnashuvga chidamlilik | Umuman hash(a) = hash(b) bo'ladigan juftlik topilmasin |
Uchinchi qatorga e'tibor bering - "tez hisoblanish" yaxshi xususiyat. Lekin parol saqlashda u kamchilikka aylanadi (4-bo'lim).
To'qnashuv nima #
Xesh chiqishi cheklangan, kirish esa cheksiz. Demak to'qnashuvlar matematik jihatdan muqarrar.
Savol faqat ularni topish qanchalik qiyin ekanida.
Buni qisqartirilgan xesh bilan ko'rsatamiz:
// Xesh natijasining faqat birinchi 3 baytini olamiz - 24 bit
function qisqaXesh(string $matn): string
{
return substr(hash('sha256', $matn), 0, 6);
}
$korilgan = [];
$urinish = 0;
while (true) {
$matn = 'xabar-' . $urinish;
$x = qisqaXesh($matn);
if (isset($korilgan[$x])) {
echo "TO'QNASHUV topildi!", PHP_EOL;
echo ' 1-matn: ', $korilgan[$x], PHP_EOL;
echo ' 2-matn: ', $matn, PHP_EOL;
echo ' xesh: ', $x, PHP_EOL;
echo ' urinish: ', $urinish, PHP_EOL;
break;
}
$korilgan[$x] = $matn;
$urinish++;
}
// to'liq xeshlar esa butunlay boshqacha
echo PHP_EOL, 'toliq xeshlar:', PHP_EOL;
echo ' ', substr(hash('sha256', $korilgan[$x]), 0, 32), '...', PHP_EOL;
echo ' ', substr(hash('sha256', $matn), 0, 32), '...', PHP_EOL;
TO'QNASHUV topildi!
1-matn: xabar-1795
2-matn: xabar-8758
xesh: dad2ab
urinish: 8758
toliq xeshlar:
dad2ab8ddb998119462a7e89a3ea4d56...
dad2ab14f3627e7d67e9c9cc24665101...
24 bitlik xeshda 2²⁴ ≈ 16.7 million variant bor. Lekin to'qnashuv 16 million urinishdan ancha oldin topildi.
Sabab - tug'ilgan kun paradoksi: n variant orasidan
to'qnashuv topish uchun taxminan √n urinish yetarli.
| Xesh uzunligi | Variantlar | To'qnashuv uchun taxminan |
|---|---|---|
| 24 bit | 2²⁴ | 2¹² ≈ 4 000 |
| 64 bit | 2⁶⁴ | 2³² ≈ 4 milliard |
| 128 bit (MD5) | 2¹²⁸ | 2⁶⁴ - nazariy |
| 256 bit (SHA-256) | 2²⁵⁶ | 2¹²⁸ - imkonsiz |
Shuning uchun xesh uzunligi ikki barobar olinadi: 128 bitlik xavfsizlik uchun 256 bitlik xesh kerak.
Buzilgan algoritmlar #
$algolar = ['md5', 'sha1', 'sha256', 'sha512', 'sha3-256'];
printf("%-10s %-6s %s%s", 'algoritm', 'bit', 'holati', PHP_EOL);
echo str_repeat('-', 46), PHP_EOL;
$holat = [
'md5' => 'BUZILGAN - toqnashuv topiladi',
'sha1' => 'BUZILGAN - toqnashuv topiladi',
'sha256' => 'ishonchli',
'sha512' => 'ishonchli',
'sha3-256' => 'ishonchli',
];
foreach ($algolar as $a) {
printf("%-10s %-6d %s%s", $a,
strlen(hash($a, '')) * 4, $holat[$a], PHP_EOL);
}
algoritm bit holati
----------------------------------------------
md5 128 BUZILGAN - toqnashuv topiladi
sha1 160 BUZILGAN - toqnashuv topiladi
sha256 256 ishonchli
sha512 512 ishonchli
sha3-256 256 ishonchli
| Algoritm | Birinchi to'qnashuv | Holati |
|---|---|---|
| MD5 | 2004 | Butunlay buzilgan, oddiy noutbukda topiladi |
| SHA-1 | 2017 (SHAttered) | Buzilgan, amaliy hujum mavjud |
| SHA-256 | Yo'q | Ishonchli |
| SHA-3 | Yo'q | Ishonchli, boshqa tuzilishga asoslangan |
To'qnashuv nimani anglatadi: hujumchi ikkita turli hujjat yasay oladi - biri zararsiz, ikkinchisi zararli - va ikkalasining xeshi bir xil bo'ladi. Siz birinchisini imzolaysiz, hujumchi imzoni ikkinchisiga qo'yadi.
md5 va sha1 hali ham foydali bo'lgan yagona joy -
kriptografiya bilan bog'liq bo'lmagan vazifalar:
| Ruxsat etiladi | Taqiqlanadi |
|---|---|
| Kesh kaliti | Parol xeshi |
| Fayl nomini qisqartirish | Raqamli imzo |
| Tasodifiy bo'lmagan taqsimlash | Butunlik tekshiruvi |
| Nusxalarni topish (tez filtr) | Sertifikat |
Shubha bo'lsa - SHA-256 ishlating.
Fayl butunligini tekshirish #
$fayl = tempnam(sys_get_temp_dir(), 'kr');
file_put_contents($fayl, "hisobot\nsatr 1\nsatr 2\n");
$asl = hash_file('sha256', $fayl);
echo 'asl xesh: ', substr($asl, 0, 24), '...', PHP_EOL;
// nusxa ko'chirdik
$nusxa = $fayl . '.nusxa';
copy($fayl, $nusxa);
echo 'nusxa mos: ', hash_equals($asl, hash_file('sha256', $nusxa))
? 'ha' : 'yoq', PHP_EOL;
// bitta bayt o'zgardi
file_put_contents($nusxa, "hisobot\nsatr 1\nsatr 3\n");
echo 'ozgargach: ', hash_equals($asl, hash_file('sha256', $nusxa))
? 'ha' : 'yoq', PHP_EOL;
unlink($fayl);
unlink($nusxa);
asl xesh: 490893ebba0dbf3421bfc535...
nusxa mos: ha
ozgargach: yoq
Tez hisoblanish - qachon muammo #
$soni = 200000;
$boshlanish = hrtime(true);
for ($i = 0; $i < $soni; $i++) {
hash('sha256', 'parol' . $i);
}
$sekund = (hrtime(true) - $boshlanish) / 1e9;
$tezlik = $soni / $sekund;
// Aniq raqam mashinaga bog'liq, shuning uchun chegara bilan tekshiramiz
printf('%d ta SHA-256 hisoblandi%s', $soni, PHP_EOL);
printf('bir soniyadan kam vaqtda: %s%s',
$sekund < 1.0 ? 'ha' : 'yoq', PHP_EOL);
printf('soniyasiga 500 000 dan kop: %s%s',
$tezlik > 500000 ? 'ha' : 'yoq', PHP_EOL);
echo 'va bu - oddiy noutbuk, PHP da, bitta yadroda', PHP_EOL;
200000 ta SHA-256 hisoblandi
bir soniyadan kam vaqtda: ha
soniyasiga 500 000 dan kop: ha
va bu - oddiy noutbuk, PHP da, bitta yadroda
Aniq raqam mashinaga bog'liq, lekin tartib doim bir xil: oddiy noutbukda PHP soniyasiga million atrofida SHA-256 hisoblaydi.
Yuqoridagi raqamga qarang - va u faqat PHP da, bitta yadroda.
Maxsus uskunada (GPU, ASIC) SHA-256 tezligi butunlay boshqa darajada bo'ladi. Bitcoin tarmog'i soniyasiga kvintillionlab SHA-256 hisoblaydi.
Demak parol xeshlari o'g'irlansa va ular oddiy SHA-256 bilan saqlangan bo'lsa, hujumchi lug'atdagi barcha parollarni juda tez sinab chiqadi.
Yechim - ataylab sekin funksiyalar: bcrypt, Argon2id. Bu keyingi bo'limning mavzusi.
Yana bir tuzoq: uzunlikni kengaytirish #
// XATO: sirni oldiga qo'yib xeshlash
$sir = 'maxfiy-kalit';
$malumot = 'foydalanuvchi=oddiy&admin=0';
$notogriImzo = hash('sha256', $sir . $malumot);
echo 'notogri usul: ', substr($notogriImzo, 0, 32), '...', PHP_EOL;
// TO'G'RI: HMAC
$togriImzo = hash_hmac('sha256', $malumot, $sir);
echo 'togri usul: ', substr($togriImzo, 0, 32), '...', PHP_EOL;
notogri usul: 0ae2a56f7deccd85553830c9bfd53e08...
togri usul: 7fac401a5c4dd50079322dc1097d4c62...
hash($sir . $malumot) - klassik xatoSHA-256 Merkle-Damgard tuzilishiga asoslangan: u ma'lumotni bloklarga bo'lib, holatni ketma-ket yangilab boradi.
Bu shunday xususiyat beradi: hash($sir . $malumot) ni
bilgan hujumchi, $sir ning o'zini bilmasa ham,
hash($sir . $malumot . $qoshimcha) ni hisoblay oladi.
Ya'ni u imzoni buzmasdan ma'lumotga qo'shimcha qo'sha oladi -
masalan &admin=1.
Bu uzunlikni kengaytirish hujumi (length extension).
| Qurilish | Xavfsizmi |
|---|---|
hash($sir . $malumot) | Yo'q |
hash($malumot . $sir) | Zaifroq, lekin baribir tavsiya etilmaydi |
hash_hmac($malumot, $sir) | Ha |
SHA-3 bilan hash($sir . $malumot) | Ha (boshqa tuzilish), lekin baribir HMAC afzal |
Qoida: xesh bilan autentiklik kerak bo'lsa - har doim HMAC. Buni keyingi bo'limlardan birida ko'ramiz.
Qaysi algoritmni tanlash #
| Vazifa | Tavsiya |
|---|---|
| Umumiy xeshlash, butunlik | SHA-256 |
| Uzun xesh kerak | SHA-512 |
| Boshqa tuzilish kerak | SHA3-256 |
| Parol | Argon2id / bcrypt (hash() emas!) |
| Xabar autentikligi | hash_hmac |
| Kesh kaliti, nusxa filtri | MD5 ham mumkin (kriptografik emas) |
- Bir xil matnni ikki marta xeshlang va natijalar bir xilligini tekshiring.
- Bir belgi va million belgi uchun xesh uzunligini solishtiring.
- Bitta harf o'zgartirib, nechta bit farq qilganini hisoblang.
- 3 baytga qisqartirilgan xesh uchun to'qnashuv toping.
- Qisqartirishni 4 baytga oshiring - urinishlar soni qanday o'zgardi?
- Tug'ilgan kun paradoksini o'z so'zlaringiz bilan tushuntiring.
hash_filebilan fayl butunligini tekshiring.- Faylning bitta baytini o'zgartirib, xesh o'zgarishini ko'ring.
- O'z mashinangizda soniyasiga nechta SHA-256 hisoblanishini o'lchang.
hash($sir . $malumot)nima uchun xato ekanini yozing.
Xulosa #
- Xesh funksiyasi istalgan hajmdagi ma'lumotni qat'iy uzunlikdagi qiymatga aylantiradi.
- U bir tomonlama: natijadan kirishni tiklab bo'lmaydi.
- Ko'chki effekti: bitta bit o'zgarsa, natijaning taxminan yarmi o'zgaradi.
- To'qnashuvlar matematik jihatdan muqarrar - savol ularni topish qiyinligida.
- Tug'ilgan kun paradoksi:
nvariant uchun√nurinish yetarli. - Shuning uchun 128 bitlik xavfsizlikka 256 bitlik xesh kerak.
- MD5 va SHA-1 buzilgan - kriptografik maqsadda ishlatilmaydi.
- Xesh tez hisoblanadi - bu butunlik uchun yaxshi, parol uchun halokatli.
hash($sir . $malumot)uzunlikni kengaytirish hujumiga ochiq.- Xabar autentikligi kerak bo'lsa -
hash_hmac.
Keyingi bo'limda parollarni to'g'ri saqlash bilan tanishamiz.
O‘qish tarixini saqlamoqchimisiz?
Tizimga kirsangiz, tugatgan bo‘limlaringiz saqlanadi va qoldirgan joyingizdan davom etasiz.
Xatolik topdingizmi?
Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.