Jenis data apa yang digunakan untuk bidang kata sandi hash dan berapa panjang?

269

Saya tidak yakin bagaimana hashing kata sandi berfungsi (akan mengimplementasikannya nanti), tetapi perlu membuat skema basis data sekarang.

Saya berpikir untuk membatasi kata sandi hingga 4-20 karakter, tetapi seperti yang saya mengerti setelah mengenkripsi string hash akan memiliki panjang yang berbeda.

Jadi, bagaimana cara menyimpan kata sandi ini di basis data?

bos-z
sumber
Juga lihat kerangka hashing kata sandi PHP (PHPass) Openwall. Ini portabel dan mengeras terhadap sejumlah serangan umum pada kata sandi pengguna. Orang yang menulis kerangka kerja (SolarDesigner) adalah orang yang sama yang menulis John The Ripper dan duduk sebagai juri di Kompetisi Sandi Hashing . Jadi dia tahu satu atau dua hal tentang serangan pada kata sandi.
jww
2
Tolong jangan berikan batas atas kata sandi Anda. Anda mem-hashing mereka, tidak ada alasan penyimpanan untuk batas atas. Jika Anda khawatir tentang serangan DoS menggunakan hash kata sandi, 1000 atau 1024 adalah batas atas yang wajar.
Iiridayn
mengapa membatasi panjang kata sandi? Setidaknya biarkan pengguna membuat kata sandi 100 karakter :)
Andrew
4 karakter adalah batas bawah kata sandi yang cukup berbahaya karena mudah untuk dipecahkan. Paling tidak gunakan 8 tetapi 14 atau 16 jauh lebih baik.
quikchange
Ini adalah pertanyaan yang sangat lama dengan jawaban yang sudah ketinggalan zaman. Lihat jawaban Gilles untuk yang terbaru.
kelalaka

Jawaban:

448

Pembaruan: Cukup menggunakan fungsi hash tidak cukup kuat untuk menyimpan kata sandi. Anda harus membaca jawaban dari Gilles di utas ini untuk penjelasan yang lebih terperinci.

Untuk kata sandi, gunakan algoritma hash penguatan kunci seperti Bcrypt atau Argon2i. Misalnya, dalam PHP, gunakan fungsi password_hash () , yang menggunakan Bcrypt secara default.

$hash = password_hash("rasmuslerdorf", PASSWORD_DEFAULT);

Hasilnya adalah string 60 karakter yang mirip dengan yang berikut (tetapi digit akan bervariasi, karena menghasilkan garam yang unik).

$2y$10$.vGA1O9wmRjrwAVXD98HNOgsNpDczlqm3Jq7KnEd1rVAGv3Fykk1a

Gunakan tipe data SQL CHAR(60)untuk menyimpan pengodean Bcrypt hash ini. Perhatikan bahwa fungsi ini tidak disandikan sebagai untaian digit heksadesimal, jadi kita tidak dapat dengan mudah menghapusnya untuk disimpan dalam biner.

Fungsi hash lainnya masih memiliki kegunaan, tetapi tidak untuk menyimpan kata sandi, jadi saya akan menyimpan jawaban asli di bawah ini, yang ditulis pada tahun 2008.


Itu tergantung pada algoritma hashing yang Anda gunakan. Hashing selalu menghasilkan hasil dengan panjang yang sama, terlepas dari inputnya. Merupakan ciri khas untuk merepresentasikan hasil hash biner dalam teks, sebagai rangkaian digit heksadesimal. Atau Anda dapat menggunakan UNHEX()fungsi ini untuk mengurangi string angka heks menjadi setengahnya.

  • MD5 menghasilkan nilai hash 128-bit. Anda dapat menggunakan CHAR (32) atau BINARY (16)
  • SHA-1 menghasilkan nilai hash 160-bit. Anda dapat menggunakan CHAR (40) atau BINARY (20)
  • SHA-224 menghasilkan nilai hash 224-bit. Anda dapat menggunakan CHAR (56) atau BINARY (28)
  • SHA-256 menghasilkan nilai hash 256-bit. Anda dapat menggunakan CHAR (64) atau BINARY (32)
  • SHA-384 menghasilkan nilai hash 384-bit. Anda dapat menggunakan CHAR (96) atau BINARY (48)
  • SHA-512 menghasilkan nilai hash 512-bit. Anda dapat menggunakan CHAR (128) atau BINARY (64)
  • BCrypt menghasilkan nilai hash yang tergantung pada implementasi 448-bit. Anda mungkin perlu CHAR (56), CHAR (60), CHAR (76), BINARY (56) atau BINARY (60)

Pada 2015, NIST merekomendasikan penggunaan SHA-256 atau lebih tinggi untuk aplikasi fungsi hash yang memerlukan interoperabilitas. Tetapi NIST tidak merekomendasikan penggunaan fungsi hash sederhana ini untuk menyimpan kata sandi dengan aman.

Algoritma hashing yang lebih kecil memiliki kegunaannya (seperti internal untuk suatu aplikasi, bukan untuk pertukaran), tetapi mereka dikenal dapat crackable .

Bill Karwin
sumber
47
@ Kuda Nil: Tolong, jangan gunakan nama pengguna sebagai garam. Hasilkan garam acak per pengguna.
Bill Karwin
11
Ya, tidak ada alasan untuk tidak menyimpannya di baris yang sama. Bahkan jika penyerang mendapatkan akses ke basis data Anda, mereka harus membuat tabel pelangi berdasarkan garam itu. Dan itu sama banyaknya pekerjaan dengan hanya menebak kata sandi.
Bill Karwin
5
@ SgtPooki: Anda perlu kolom lain untuk menyimpan garam di plaintext. Kemudian Anda dapat meng-hash kata sandi pengguna dengan garam yang sama ketika mereka mengetiknya, dan membandingkan hasilnya dengan intisari digest yang disimpan dalam tabel.
Bill Karwin
12
Jika Anda menyimpan garam di tabel yang sama (atau lokasi lain dengan izin akses yang sama), tidak ada alasan untuk tidak menggunakan nama pengguna sebagai garam, karena itu akan unik untuk setiap pengguna. Namun, setiap garam yang diketahui membuat hash lebih lemah dari pada jika tidak ada garam yang dikenal. Garam hanya menambah nilai jika juga tidak diketahui.
fijiaaron
9
Saya tidak mengerti kesepakatan dengan garam yang diketahui vs. tidak dikenal. Jika Anda menerapkan situs - garam harus diketahui ke halaman login / script / sevice yang menguji kata sandi. Jadi - Anda pendukung garam "tidak dikenal" - apakah Anda mengasumsikan bahwa kode untuk proses login tidak diketahui oleh penyerang? Jika tidak - tidak akan penyerang selalu tahu garam, apakah itu acak, unik, disimpan bersama dengan kata sandi hash atau terpisah?
mattstuehler
13

Anda benar-benar dapat menggunakan CHAR(panjang hash) untuk menentukan tipe data Anda untuk MySQL karena setiap algoritma hashing akan selalu mengevaluasi ke jumlah karakter yang sama. Misalnya, SHA1selalu mengembalikan angka heksadesimal 40 karakter.

Noah Goodrich
sumber
1
SHA-1 tidak cocok untuk hashing passwords.
Gilles 'SO- stop being evil'
10

Selalu gunakan algoritma hashing kata sandi: Argon2 , scrypt , bcrypt atau PBKDF2 .

Argon2 memenangkan kompetisi hashing password 2015. Scrypt , bcrypt dan PBKDF2 adalah algoritma yang lebih tua yang dianggap kurang disukai sekarang, tetapi masih bagus secara fundamental, jadi jika platform Anda belum mendukung Argon2, boleh saja menggunakan algoritma lain untuk saat ini.

Jangan pernah menyimpan kata sandi secara langsung dalam database. Jangan mengenkripsi itu juga: jika tidak, jika situs Anda dilanggar, penyerang mendapatkan kunci dekripsi dan dengan demikian dapat memperoleh semua kata sandi. Kata sandi HARUS di- hash .

Sebuah hash password yang memiliki sifat yang berbeda dari hash table hash atau hash kriptografi. Jangan pernah menggunakan hash kriptografi biasa seperti MD5, SHA-256 atau SHA-512 pada kata sandi. Algoritma hashing kata sandi menggunakan garam , yang unik (tidak digunakan untuk pengguna lain atau dalam basis data orang lain). Garam diperlukan agar penyerang tidak bisa hanya menghitung pra-hash kata sandi yang umum: dengan garam, mereka harus memulai kembali perhitungan untuk setiap akun. Algoritma hashing kata sandi secara intrinsik lambat - selambat yang Anda mampu. Keterlambatan menyakiti penyerang jauh lebih banyak daripada Anda karena penyerang harus mencoba banyak kata sandi yang berbeda. Untuk informasi lebih lanjut, lihat Cara mengamankan kata sandi hash .

Kata sandi hash mengkodekan empat informasi:

  • Indikator algoritma yang digunakan. Ini diperlukan untuk kelincahan : rekomendasi kriptografi berubah seiring waktu. Anda harus dapat beralih ke algoritma baru.
  • Indikator kesulitan atau kekerasan. Semakin tinggi nilai ini, semakin banyak perhitungan yang dibutuhkan untuk menghitung hash. Ini harus berupa nilai konfigurasi konstan atau global dalam fungsi perubahan kata sandi, tetapi harus meningkat seiring waktu ketika komputer semakin cepat, jadi Anda perlu mengingat nilai untuk setiap akun. Beberapa algoritma memiliki nilai numerik tunggal, yang lain memiliki lebih banyak parameter di sana (misalnya untuk menyetel penggunaan CPU dan penggunaan RAM secara terpisah).
  • Garam. Karena garam harus unik secara global, garam harus disimpan untuk setiap akun. Garam harus dibuat secara acak pada setiap perubahan kata sandi.
  • Hash yang tepat, yaitu keluaran dari perhitungan matematis dalam algoritma hashing.

Banyak perpustakaan menyertakan fungsi pasangan yang dengan mudah mengemas informasi ini sebagai string tunggal: yang menggunakan indikator algoritma, indikator kekerasan dan kata sandi, menghasilkan garam acak dan mengembalikan string hash penuh; dan yang mengambil kata sandi dan string hash lengkap sebagai input dan mengembalikan boolean yang menunjukkan apakah kata sandi itu benar. Tidak ada standar universal, tetapi penyandian umum adalah

$ algoritma $ parameter $ garam $ output

di mana algorithmnomor atau string alfanumerik pendek yang mengkodekan pilihan algoritma, parametersadalah string yang dapat dicetak, dan saltdan outputdikodekan dalam Base64 tanpa berakhir =.

16 byte cukup untuk garam dan output. (Lihat misalnya rekomendasi untuk Argon2 .) Disandikan dalam Base64, masing-masing 21 karakter. Dua bagian lainnya bergantung pada algoritma dan parameter, tetapi 20–40 karakter adalah tipikal. Itu total sekitar 82 karakter ASCII ( CHAR(82), dan tidak perlu untuk Unicode), yang harus Anda tambahkan margin keamanan jika Anda pikir akan sulit untuk memperbesar bidang nanti.

Jika Anda menyandikan hash dalam format biner, Anda bisa mendapatkannya hingga 1 byte untuk algoritme, 1-4 byte untuk kekerasan (jika Anda meng-hard-code beberapa parameter), dan masing-masing 16 byte untuk garam dan output , dengan total 37 byte. Katakan 40 byte ( BINARY(40)) untuk memiliki setidaknya beberapa byte cadangan. Perhatikan bahwa ini adalah byte 8-bit, bukan karakter yang dapat dicetak, khususnya bidang dapat menyertakan byte nol.

Perhatikan bahwa panjang hash sama sekali tidak terkait dengan panjang kata sandi.

Gilles 'SANGAT berhenti menjadi jahat'
sumber
9

Anda mungkin menemukan artikel Wikipedia ini tentang pengasinan yang bermanfaat . Idenya adalah menambahkan sedikit data untuk mengacak nilai hash Anda; ini akan melindungi kata sandi Anda dari serangan kamus jika seseorang mendapat akses tanpa izin ke hash kata sandi.

Dana si Sane
sumber
2
Itu memang sangat berharga (+1), tetapi tidak menjawab pertanyaan! (-1)
Bill Karwin
3
Ya, tapi jelas relevan dalam konteks ini (+1)
Treb
7

Sebagai string panjang tetap (VARCHAR (n) atau bagaimanapun MySQL menyebutnya). Hash selalu memiliki panjang tetap misalnya 12 karakter (tergantung pada algoritma hash yang Anda gunakan). Jadi kata sandi 20 char akan dikurangi menjadi hash 12 char, dan password 4 char juga akan menghasilkan hash 12 char.

Treb
sumber
3
'atau bagaimanapun MySQL menyebutnya' - MYSQL menyebutnya CHAR. Tipe ini untuk nilai panjang tetap. Jadi saya pikir CHAR adalah tipe yang lebih baik daripada VARCHAR.
t298712383
4

Anda harus menggunakan TEXT(menyimpan karakter dalam jumlah tidak terbatas) demi kompatibilitas ke depan. Algoritma Hashing (perlu) menjadi lebih kuat dari waktu ke waktu dan dengan demikian bidang basis data ini perlu mendukung lebih banyak karakter dari waktu ke waktu. Selain itu tergantung pada strategi migrasi Anda, Anda mungkin perlu menyimpan hash baru dan lama di bidang yang sama, jadi tidak disarankan untuk memperbaiki panjang ke satu jenis hash.

Bart
sumber
3

Ini sangat tergantung pada algoritma hashing yang Anda gunakan. Panjang kata sandi tidak ada hubungannya dengan panjang hash, jika saya ingat dengan benar. Cari spesifikasi pada algoritma hashing yang Anda gunakan, jalankan beberapa tes, dan potong tepat di atas itu.

willasaywhat
sumber
3

Hash adalah urutan bit (128 bit, 160 bit, 256 bit, dll., Tergantung pada algoritma). Kolom Anda harus bertipe biner, bukan tipe teks / karakter, jika MySQL mengizinkannya (tipe data SQL Server adalah binary(n)atau varbinary(n)). Anda juga harus menggarami hash. Garam bisa berupa teks atau biner, dan Anda akan membutuhkan kolom yang sesuai.

yfeldblum
sumber
Keadilan sepenuhnya benar di sini - MySQL akan menyimpan ini sebagai nilai numerik dan akan membuat pencarian pada kolom ini jauh lebih efisien daripada melakukan pencocokan string, namun garam tidak boleh disimpan dalam database di samping data asin - yang menghilangkan keamanan yang diberikan garam .
Tony Maro
6
Garam bukan rahasia. Satu- satunya rahasia adalah kata sandi. Pastikan setiap kata sandi baru mendapat garam baru. Setiap kali pengguna mengubah kata sandi, sistem harus menghasilkan garam baru untuk kata sandi itu. Garam harus panjang dan acak, seperti 16 byte yang dihasilkan dari PRNG yang aman secara kriptografis.
yfeldblum
1
@TonyMaro Tidak yakin apakah string kata sandi cocok pada tingkat SQL adalah strategi yang baik. Dengan kata lain, Anda tidak harus mencari kata sandi di database Anda, alih-alih mengambil pengguna berdasarkan nama pengguna dan membandingkan kata sandi dalam kode, bukan SQL.
Bart
1

Saya selalu diuji untuk menemukan panjang string MAX dari string terenkripsi dan menetapkan itu sebagai panjang karakter dari tipe VARCHAR. Bergantung pada berapa banyak catatan yang akan Anda miliki, ini bisa sangat membantu ukuran database.

Stephen Walcher
sumber
0

untuk md5 vARCHAR (32) sesuai. Bagi yang menggunakan AES lebih baik menggunakan varbinary.

Hare Srinivasa
sumber
1
Baik MD5 bukan AES tidak cocok untuk membuat kata sandi.
Gilles 'SO- stop being evil'