Cara terbaik untuk menyimpan kata sandi dalam basis data [tertutup]

476

Saya sedang mengerjakan proyek yang harus memiliki otentikasi (nama pengguna dan kata sandi)

Ini juga terhubung ke database, jadi saya pikir saya akan menyimpan nama pengguna dan kata sandi di sana. Namun, sepertinya bukan ide yang baik untuk memiliki kata sandi hanya sebagai bidang teks dalam tabel yang berada di database.

Saya menggunakan C # dan menghubungkan ke server ekspres 2008. Adakah yang bisa menyarankan (dengan sebanyak mungkin contoh) apa cara terbaik untuk menyimpan data jenis ini?

PS Saya terbuka pada gagasan bahwa info ini tidak disimpan dalam database jika alasan yang baik dapat diberikan

Crash893
sumber
1
Apa pun yang Anda lakukan, jika Anda menggunakan enkripsi, jangan menyimpan kunci dalam kode seperti poster sebelumnya yang disebutkan. Itu hanya praktik yang buruk.
Woody
12
'Bagaimana melakukan kata sandi dengan benar?' adalah pertanyaan vital. Ini adalah masalah yang sulit dan kesalahan memiliki konsekuensi serius (ingat apa yang terjadi pada Tesco dan LinkedIn). Saya pikir pertanyaan ini harus dibuka kembali di programmers.stackexchange.com
Kolonel Panic
2
Lebih baik tetap berpegang pada standar - lihat en.wikipedia.org/wiki/PBKDF2 Anda hanya perlu menemukan implementasi dalam bahasa Anda
Boris Treukhov
5
Pertanyaan ini dijawab secara luas di forum keamanan
gioele

Jawaban:

406

Anda benar bahwa menyimpan kata sandi di bidang teks biasa adalah ide yang mengerikan . Namun, sejauh lokasi berjalan , untuk sebagian besar kasus yang akan Anda temui (dan saya benar-benar tidak bisa memikirkan contoh tandingan) menyimpan representasi kata sandi dalam database adalah hal yang tepat untuk dilakukan. Dengan representasi saya berarti bahwa Anda ingin hash password menggunakan garam (yang harus berbeda untuk setiap pengguna) dan algoritma 1-cara yang aman dan toko yang , membuang password asli. Kemudian, ketika Anda ingin memverifikasi kata sandi, Anda hash nilainya (menggunakan algoritma hashing dan garam yang sama) dan membandingkannya dengan nilai hash dalam database.

Jadi, walaupun Anda memikirkan hal ini adalah hal yang baik dan ini adalah pertanyaan yang bagus, sebenarnya ini adalah duplikat dari pertanyaan-pertanyaan ini (setidaknya):

Untuk mengklarifikasi sedikit lebih jauh pada bit penggaraman, bahayanya dengan hanya membuat password dan menyimpannya adalah bahwa jika seorang pelanggar menguasai database Anda, mereka masih dapat menggunakan apa yang dikenal sebagai tabel pelangi untuk dapat "mendekripsi" kata sandi (setidaknya yang muncul di tabel pelangi). Untuk menyiasatinya, pengembang menambahkan garam ke kata sandi yang, jika dilakukan dengan benar, membuat serangan pelangi tidak mungkin dilakukan. Perhatikan bahwa kesalahpahaman yang umum adalah dengan menambahkan string unik dan panjang yang sama ke semua kata sandi; Meskipun ini tidak mengerikan , yang terbaik adalah menambahkan garam unik ke setiap kata sandi. Baca ini untuk lebih lanjut.

Paolo Bergantino
sumber
40
Maksud saya menyimpan kata sandi di basis data dan bukannya menyimpannya di tempat lain. Mengambil kalimat itu di luar konteks membuatnya tampak seperti saya mendukung menyimpan kata sandi polos, jika Anda membaca sisanya saya jelas tidak.
Paolo Bergantino
14
Bukan hanya itu yang saya katakan, saya mengarahkannya ke sejumlah besar pos yang membahas garam dan lebih lanjut ...
Paolo Bergantino
1
@ Paolo Bergantino: Anda yakin tidak ada kesalahan ketik pada posting Anda? Ia mengatakan, "Untuk sebagian besar kasus yang akan Anda temui (dan saya sejujurnya tidak bisa memikirkan contoh tandingan) menyimpan kata sandi dalam database adalah hal yang tepat untuk dilakukan." ??? Tampaknya bertentangan dengan komentar Anda
Mitch Wheat
3
Apa yang dikatakan Paolo secara langsung bertentangan dengan dirinya sendiri. Kata sandi yang asin bukanlah kata sandi. Menyimpan hash asin dari kata sandi dalam basis data tidak menyimpan kata sandi dalam basis data. Tubuh jawaban sangat tepat, tetapi kalimat pertamanya sangat menyesatkan.
Robert Rossney
40
@ Robert: Itu semakin dekat dengan permainan semantik kecil, tetapi saya akan memperbaikinya ...
Paolo Bergantino
54

Latar Belakang Anda tidak pernah ... benar-benar ... perlu mengetahui kata sandi pengguna. Anda hanya ingin memverifikasi pengguna yang masuk mengetahui kata sandi untuk suatu akun.

Hash It: Menyimpan kata sandi pengguna hash (enkripsi satu arah) melalui fungsi hash yang kuat. Pencarian untuk "c # mengenkripsi kata sandi" memberikan banyak contoh.

Lihat pembuat hash SHA1 online untuk gagasan tentang apa yang dihasilkan fungsi hash (Tapi jangan gunakan SHA1 sebagai fungsi hash, gunakan sesuatu yang lebih kuat seperti SHA256).

Sekarang, kata sandi hash berarti Anda (dan pencuri basis data) tidak dapat membalikkan hash itu kembali ke kata sandi semula.

Bagaimana cara menggunakannya: Tapi, Anda berkata, bagaimana saya menggunakan kata sandi yang dihaluskan yang disimpan dalam database?

Ketika pengguna masuk, mereka akan memberi Anda nama pengguna dan kata sandi (dalam teks aslinya). Anda hanya menggunakan kode hash yang sama untuk hash kata sandi yang diketik untuk mendapatkan versi yang disimpan.

Jadi, bandingkan dua kata sandi hash (hash basis data untuk nama pengguna dan kata sandi yang diketik & hash). Anda dapat mengetahui apakah "apa yang mereka ketikkan" cocok dengan "apa yang dimasukkan oleh pengguna asli untuk kata sandi mereka" dengan membandingkan hash mereka.

Kredit tambahan:

Pertanyaan: Jika saya memiliki basis data Anda, maka bisakah saya mengambil cracker seperti John the Ripper dan mulai membuat hash sampai saya menemukan kecocokan dengan kata sandi hash yang tersimpan? (karena pengguna memilih kata-kata kamus yang pendek ... seharusnya mudah)

Jawab: Ya ... ya mereka bisa.

Jadi, Anda harus 'garam' kata sandi Anda. Lihat artikel Wikipedia tentang garam

Lihat "Cara hash data dengan garam" contoh C #

joej
sumber
14
Posting yang bagus, kecuali untuk satu hal: md5 dan sha1 keduanya telah rusak. Anda mungkin harus menggunakan algoritma yang lebih kuat, seperti mungkin keluarga SHA2.
Paolo Bergantino
3
Terima kasih Paolo - Anda benar. Karena penggunaan SHA2 semudah menggunakan MD5 & SHA1, silakan gunakan algoritma hash yang lebih kuat.
joej
5
SHA-1 belum rusak. Tetapi untuk memparafrasekan Bruce Schneier: Berjalan, jangan lari, ke SHA-2.
Ian Boyd
3
"Jadi, Anda harus 'garam' kata sandi Anda" ... Tapi garam itu biasanya disimpan dalam database bersama dengan kata sandi, jadi bagaimana itu membantu? Penyerang hanya perlu menambahkan garam ke frasa serangan kamus yang sedang dia uji. Bagaimana itu lebih aman selain tidak akan mengungkapkan kata sandi rangkap?
trusktr
4
@ Joej "Kamu tidak pernah ... benar-benar ... perlu tahu kata sandi pengguna" - itu adalah asumsi yang terlihat sangat pendek. Ada banyak jenis aplikasi di mana memiliki kata sandi yang disimpan dengan cara yang dapat diambil benar-benar diperlukan. Misalnya, aplikasi yang perlu sering masuk ke sistem lain dengan kredensial tersimpan, disediakan dan diperbarui oleh pengguna.
Francisco Zarabozo
29

Sebagai hash yang dikeraskan dengan kunci, menggunakan algoritma aman seperti sha-512.

nilamo
sumber
6
Menurut pendapat saya, Anda harus selalu menggunakan algoritma lambat (seperti Blowfish, misalnya) untuk menyimpan kata sandi. Langgan ini adalah jawaban yang jauh lebih baik: security.stackexchange.com/questions/211/… . Cukup letakkan di sini, karena halaman ini masih muncul tinggi di hasil pencarian.
Dynom
2
Mengikuti saran ini untuk penyimpanan kata sandi akan sangat salah.
mlissner
27

Praktik keamanan terbaik adalah tidak menyimpan kata sandi sama sekali (bahkan tidak dienkripsi), tetapi untuk menyimpan hash asin (dengan garam unik per kata sandi) dari kata sandi terenkripsi.

Dengan cara itu (secara praktis) tidak mungkin untuk mengambil kata sandi plaintext.

Mitch Wheat
sumber
11
Wayne, dengan pengasinan sebelum menghitung hash, tabel pelangi dikalahkan secara efektif, asalkan garamnya berukuran cukup.
Mike Rosenblum
12
@Wayne Hartman: Tidak. Jika nilai garam terpapar, maka Anda harus membuat tabel pelangi baru untuk nilai garam tertentu. Tujuan dari tabel pelangi adalah untuk memiliki nilai hash yang dihitung sebelumnya. Dan tidak ada yang akan memiliki meja pelangi untuk garam spesifiknya.
Ian Boyd
6

Saya mungkin sedikit di luar topik ketika Anda menyebutkan perlunya nama pengguna dan kata sandi, dan pemahaman saya tentang masalah ini memang bukan yang terbaik tetapi apakah OpenID sesuatu yang patut dipertimbangkan?

Jika Anda menggunakan OpenID maka Anda tidak akan menyimpan kredensial sama sekali jika saya memahami teknologi dengan benar dan pengguna dapat menggunakan kredensial yang sudah mereka miliki, menghindari kebutuhan untuk membuat identitas baru yang khusus untuk aplikasi Anda.

Ini mungkin tidak cocok jika aplikasi tersebut murni untuk penggunaan internal

RPX menyediakan cara mudah yang bagus untuk mengintegrasikan dukungan OpenID ke dalam suatu aplikasi.

Crippledsmurf
sumber
Saya setuju bahwa orang-orang openID batu menghadapi tetapi untuk aplikasi ini itu adalah in-house database untuk sebuah perusahaan saya ragu mereka ingin orang tua yang datang untuk masuk. juga akses web tidak diperlukan untuk aplikasi ini untuk bekerja dengan benar sehingga saya akan benci untuk membutuhkannya.
Crash893
3

Dalam skenario Anda, Anda dapat melihat keanggotaan asp.net, merupakan praktik yang baik untuk menyimpan kata sandi pengguna sebagai string hash dalam database. Anda dapat mengotentikasi pengguna dengan membandingkan kata sandi masuk yang hash dengan yang disimpan dalam database.

Semuanya telah dibangun untuk tujuan ini, periksa keanggotaan asp.net

Ray Lu
sumber
1

Saya akan MD5 / SHA1 kata sandi jika Anda tidak perlu dapat membalikkan hash. Saat pengguna masuk, Anda bisa mengenkripsi kata sandi yang diberikan dan membandingkannya dengan hash. Tabrakan hash hampir tidak mungkin dalam kasus ini, kecuali seseorang mendapatkan akses ke database dan melihat hash yang sudah mereka tabrakan.

waiwai933
sumber
2
Saya tidak akan menggunakan MD5 untuk hashing - itu pada dasarnya mscs.dal.ca/~selinger/md5collision
zebrabox
3
Sebenarnya, bukan itu yang rusak. Apa yang bisa mereka lakukan adalah menemukan nilai hash yang sama untuk dua file berbeda. Yang tidak bisa mereka lakukan adalah membalikkan MD5 dan mendapatkan kata sandi yang berfungsi.
waiwai933
2
Nah, bukankah itu akan rusak juga? Anda cukup memasukkan kata sandi lain yang menghasilkan hash yang sama, dan Anda masuk. Anda tidak perlu tahu kata sandi asli. Cara untuk memperbaikinya adalah jika Anda memberi garam kata sandi sebelum hashing.
mjuarez
2
@mjuarez jika Anda menambahkan garam ke kata sandi sebelum Anda menggunakan MD5 tabrakan tidak masalah karena Anda tidak dapat menggunakan kata sandi lainnya
WiiMaxx