Anda bisa mencarinya di Wikipedia ... Tapi karena Anda ingin penjelasan, saya akan melakukan yang terbaik di sini:
Fungsi Hash
Mereka menyediakan pemetaan antara input panjang arbitrer, dan output (biasanya) panjang tetap (atau lebih kecil). Ini bisa berupa apa saja, dari crc32 sederhana, hingga fungsi hash kriptografis yang penuh sesak nafas seperti MD5 atau SHA1 / 2/256/512. Intinya adalah bahwa ada pemetaan satu arah yang terjadi. Selalu ada banyak: 1 pemetaan (berarti akan selalu ada tabrakan) karena setiap fungsi menghasilkan output yang lebih kecil daripada yang bisa dimasukkan (Jika Anda memasukkan setiap file 1mb ke MD5, Anda akan mendapatkan banyak tabrakan).
Alasan mereka sulit (atau tidak mungkin secara praktis) untuk dibalik adalah karena cara mereka bekerja secara internal. Sebagian besar fungsi hash kriptografis beralih pada input yang ditetapkan berkali-kali untuk menghasilkan output. Jadi jika kita melihat pada setiap panjang input yang tetap (yang bergantung pada algoritma), fungsi hash akan memanggil keadaan saat ini. Ini kemudian akan beralih ke negara dan mengubahnya ke yang baru dan menggunakannya sebagai umpan balik ke dirinya sendiri (MD5 melakukan ini 64 kali untuk setiap sepotong data 512bit). Itu kemudian entah bagaimana menggabungkan status yang dihasilkan dari semua iterasi ini kembali bersama untuk membentuk hash yang dihasilkan.
Sekarang, jika Anda ingin men-decode hash, pertama-tama Anda harus mencari cara untuk membagi hash yang diberikan menjadi status iterasi (1 kemungkinan input lebih kecil dari ukuran sepotong data, banyak untuk input lebih besar). Maka Anda harus membalikkan iterasi untuk setiap negara. Sekarang, untuk menjelaskan mengapa ini adalah sangat sulit, bayangkan mencoba untuk menyimpulkan a
dan b
dari rumus berikut: 10 = a + b
. Ada 10 kombinasi positif a
dan b
yang dapat bekerja. Sekarang lewati beberapa kali:tmp = a + b; a = b; b = tmp
. Untuk 64 iterasi, Anda akan memiliki lebih dari 10 ^ 64 kemungkinan untuk dicoba. Dan itu hanya tambahan sederhana di mana beberapa negara dipertahankan dari iterasi ke iterasi. Fungsi hash nyata melakukan lebih dari 1 operasi (MD5 melakukan sekitar 15 operasi pada 4 variabel keadaan). Dan karena iterasi berikutnya tergantung pada keadaan sebelumnya dan sebelumnya dihancurkan dalam menciptakan kondisi saat ini, itu semua tidak mungkin untuk menentukan keadaan input yang mengarah ke status output yang diberikan (untuk setiap iterasi tidak kurang). Gabungkan bahwa, dengan sejumlah besar kemungkinan yang terlibat, dan memecahkan kode bahkan MD5 akan mengambil jumlah sumber daya yang hampir tak terbatas (tetapi bukan tak terbatas). Begitu banyak sumber daya sehingga
Fungsi Enkripsi
Mereka menyediakan pemetaan 1: 1 antara input dan output panjang yang sewenang-wenang. Dan mereka selalu bisa dibalik. Yang penting untuk dicatat adalah itu dapat dibalik menggunakan beberapa metode. Dan selalu 1: 1 untuk kunci yang diberikan. Sekarang, ada beberapa input: pasangan kunci yang mungkin menghasilkan output yang sama (sebenarnya biasanya ada, tergantung pada fungsi enkripsi). Data terenkripsi yang baik tidak bisa dibedakan dari kebisingan acak. Ini berbeda dari output hash yang baik yang selalu dari format yang konsisten.
Gunakan Kasing
Gunakan fungsi hash ketika Anda ingin membandingkan nilai tetapi tidak dapat menyimpan representasi polos (karena sejumlah alasan). Kata sandi harus sesuai dengan kasus penggunaan ini dengan sangat baik karena Anda tidak ingin menyimpannya teks biasa untuk alasan keamanan (dan tidak seharusnya). Tetapi bagaimana jika Anda ingin memeriksa filesystem untuk file musik bajakan? Tidak praktis menyimpan 3 mb per file musik. Jadi alih-alih, ambil hash file tersebut, dan simpan itu (md5 akan menyimpan 16 byte, bukan 3mb). Dengan begitu, Anda hanya meng-hash setiap file dan membandingkannya dengan database hash yang tersimpan (Ini tidak berfungsi dengan baik dalam praktik karena pengodean ulang, pengubahan header file, dll, tetapi ini merupakan contoh kasus penggunaan).
Gunakan fungsi hash saat Anda memeriksa validitas data input. Untuk itulah mereka dirancang. Jika Anda memiliki 2 buah input, dan ingin memeriksa apakah keduanya sama, jalankan keduanya melalui fungsi hash. Probabilitas tabrakan secara astronomis rendah untuk ukuran input kecil (dengan asumsi fungsi hash yang baik). Karena itu disarankan untuk kata sandi. Untuk kata sandi hingga 32 karakter, md5 memiliki ruang keluaran 4 kali lipat. SHA1 memiliki 6 kali ruang output (kurang-lebih). SHA512 memiliki sekitar 16 kali ruang output. Anda tidak terlalu peduli apa kata sandi itu , Anda peduli apakah itu sama yang disimpan. Itu sebabnya Anda harus menggunakan hash untuk kata sandi.
Gunakan enkripsi kapan pun Anda perlu mendapatkan kembali data input. Perhatikan kata kebutuhan . Jika Anda menyimpan nomor kartu kredit, Anda harus mengembalikannya di beberapa titik, tetapi tidak ingin menyimpannya dalam bentuk teks. Jadi alih-alih, simpan versi terenkripsi dan simpan kunci seaman mungkin.
Fungsi hash juga bagus untuk menandatangani data. Misalnya, jika Anda menggunakan HMAC, Anda menandatangani sepotong data dengan mengambil hash data yang digabungkan dengan nilai yang diketahui tetapi tidak ditransmisikan (nilai rahasia). Jadi, Anda mengirim teks biasa dan hash HMAC. Kemudian, penerima hanya hash data yang dikirimkan dengan nilai yang diketahui dan memeriksa untuk melihat apakah cocok dengan HMAC yang dikirimkan. Jika itu sama, Anda tahu itu tidak dirusak oleh pesta tanpa nilai rahasia. Ini biasanya digunakan dalam sistem cookie aman oleh kerangka kerja HTTP, serta dalam pengiriman pesan data melalui HTTP di mana Anda menginginkan jaminan integritas dalam data.
Catatan tentang hash untuk kata sandi:
Fitur utama dari fungsi hash kriptografi adalah bahwa mereka harus sangat cepat untuk dibuat, dan sangat sulit / lambat untuk dibalik (begitu banyak sehingga secara praktis tidak mungkin). Ini menimbulkan masalah dengan kata sandi. Jika Anda menyimpan sha512(password)
, Anda tidak melakukan apa pun untuk menjaga dari meja pelangi atau serangan brute force. Ingat, fungsi hash dirancang untuk kecepatan. Jadi sepele bagi penyerang untuk hanya menjalankan kamus melalui fungsi hash dan menguji setiap hasil.
Menambahkan garam membantu masalah karena menambahkan sedikit data yang tidak diketahui ke hash. Jadi, alih-alih menemukan apa pun yang cocok md5(foo)
, mereka perlu menemukan sesuatu yang ketika ditambahkan ke garam yang dikenal menghasilkan md5(foo.salt)
(yang sangat sulit dilakukan). Tapi itu masih tidak menyelesaikan masalah kecepatan karena jika mereka tahu garam itu hanya masalah menjalankan kamus.
Jadi, ada cara untuk mengatasi ini. Salah satu metode populer disebut penguatan kunci (atau peregangan kunci). Pada dasarnya, Anda mengulangi hash berkali-kali (biasanya ribuan). Ini melakukan dua hal. Pertama, memperlambat runtime dari algoritma hashing secara signifikan. Kedua, jika diimplementasikan dengan benar (mengirimkan input dan garam kembali pada setiap iterasi) sebenarnya meningkatkan entropi (ruang yang tersedia) untuk output, mengurangi kemungkinan tabrakan. Implementasi sepele adalah:
var hash = password + salt;
for (var i = 0; i < 5000; i++) {
hash = sha512(hash + password + salt);
}
Ada implementasi lain yang lebih standar seperti PBKDF2 , BCrypt . Tetapi teknik ini digunakan oleh beberapa sistem terkait keamanan (seperti PGP, WPA, Apache dan OpenSSL).
Intinya, hash(password)
tidak cukup baik. hash(password + salt)
lebih baik, tetapi masih belum cukup baik ... Gunakan mekanisme hash yang diregangkan untuk menghasilkan hash kata sandi Anda ...
Catatan lain tentang peregangan sepele
Jangan dalam keadaan apa pun memberi makan output dari satu hash langsung kembali ke fungsi hash :
hash = sha512(password + salt);
for (i = 0; i < 1000; i++) {
hash = sha512(hash); // <-- Do NOT do this!
}
Alasannya ada hubungannya dengan tabrakan. Ingat bahwa semua fungsi hash memiliki tabrakan karena ruang output yang mungkin (jumlah kemungkinan output) lebih kecil daripada ruang input. Untuk melihat alasannya, mari kita lihat apa yang terjadi. Untuk mengawali ini, mari kita asumsikan ada kemungkinan 0,001% tabrakan sha1()
(ini jauh lebih rendah pada kenyataannya, tetapi untuk tujuan demonstrasi).
hash1 = sha1(password + salt);
Sekarang, hash1
memiliki kemungkinan tabrakan 0,001%. Tetapi ketika kita melakukan selanjutnya hash2 = sha1(hash1);
, semua tabrakan hash1
secara otomatis menjadi tabrakanhash2
. Jadi sekarang, kami memiliki tingkat hash1 di 0,001%, dan sha1()
panggilan ke-2 menambah itu. Jadi sekarang, hash2
memiliki kemungkinan tabrakan 0,002%. Peluang itu dua kali lipat! Setiap iterasi akan menambah 0.001%
kemungkinan tabrakan dengan hasilnya. Jadi, dengan 1000 iterasi, peluang tabrakan melonjak dari sepele 0,001% menjadi 1%. Sekarang, degradasi adalah linear, dan probabilitas sebenarnya jauh lebih kecil, tetapi efeknya sama (perkiraan kemungkinan tabrakan tunggal md5
adalah sekitar 1 / (2 128 ) atau 1 / (3x10 38). Meskipun itu tampak kecil, berkat serangan ulang tahun itu tidak benar-benar sekecil kelihatannya).
Alih-alih, dengan menambahkan kembali garam dan kata sandi setiap kali, Anda memasukkan kembali data ke fungsi hash. Jadi setiap tabrakan dari babak tertentu tidak lagi tabrakan dari babak berikutnya. Begitu:
hash = sha512(password + salt);
for (i = 0; i < 1000; i++) {
hash = sha512(hash + password + salt);
}
Memiliki kemungkinan tabrakan yang sama dengan sha512
fungsi asli . Yang kamu inginkan. Gunakan itu sebagai gantinya.