Saya baru saja membaca salah satu artikel DavidHayden tentang Hashing User Passwords .
Sungguh saya tidak bisa mendapatkan apa yang dia coba capai.
Ini kodenya:
private static string CreateSalt(int size)
{
//Generate a cryptographic random number.
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
byte[] buff = new byte[size];
rng.GetBytes(buff);
// Return a Base64 string representation of the random number.
return Convert.ToBase64String(buff);
}
private static string CreatePasswordHash(string pwd, string salt)
{
string saltAndPwd = String.Concat(pwd, salt);
string hashedPwd =
FormsAuthentication.HashPasswordForStoringInConfigFile(
saltAndPwd, "sha1");
return hashedPwd;
}
Apakah ada metode C # lainnya untuk mem-hashing kata sandi dan menambahkan garam ke dalamnya?
SHA1
bukan crypto-grade, jadi Anda setidaknya harus menggunakanSHA256
, yang menghasilkan 256 bit atau 32 byte. TETAPI, 256 bit TIDAK mudah dikonversi ke basis 64, karena masing-masing base64 char mengkodekan 6 bit, dan 256 tidak dapat dibagi seluruhnya oleh 6. Jadi Anda memerlukan penyebut umum 6 (untuk base64) dan 8 (untuk bit dalam byte) lebih dari 256 bit, yaitu 264 gigitan atau 33 byte. TLDR: Gunakan 33.Jawaban:
Sebenarnya ini agak aneh, dengan konversi string - yang dilakukan penyedia keanggotaan untuk memasukkannya ke file konfigurasi. Hash dan garam adalah gumpalan biner, Anda tidak perlu mengubahnya menjadi string kecuali jika Anda ingin memasukkannya ke dalam file teks.
Dalam buku saya, Beginning ASP.NET Security , (oh akhirnya, alasan untuk germo buku), saya melakukan hal berikut
Generasi garam adalah sebagai contoh dalam pertanyaan. Anda dapat mengonversi teks ke array byte menggunakan
Encoding.UTF8.GetBytes(string)
. Jika Anda harus mengonversi hash ke representasi stringnya, Anda dapat menggunakanConvert.ToBase64String
danConvert.FromBase64String
mengubahnya kembali.Anda harus mencatat bahwa Anda tidak dapat menggunakan operator kesetaraan pada array byte, itu memeriksa referensi dan jadi Anda harus loop melalui kedua array memeriksa setiap byte dengan demikian
Selalu gunakan garam baru per kata sandi. Garam tidak harus dirahasiakan dan dapat disimpan di samping hash itu sendiri.
sumber
return array1.Length == array2.Length && !array1.Where((t, i) => t != array2[i]).Any();
Apa yang blowdart katakan, tetapi dengan kode sedikit kurang. Gunakan Linq atau
CopyTo
untuk menggabungkan array.Linq juga memiliki cara mudah untuk membandingkan array byte Anda.
Namun sebelum menerapkan semua ini, periksa pos ini . Untuk hashing kata sandi, Anda mungkin menginginkan algoritma hash yang lambat, bukan yang cepat.
Untuk itu ada
Rfc2898DeriveBytes
kelas yang lambat (dan dapat dibuat lebih lambat), dan dapat menjawab bagian kedua dari pertanyaan awal karena dapat mengambil kata sandi dan garam dan mengembalikan hash. Lihat pertanyaan ini untuk informasi lebih lanjut. Catatan, Stack Exchange digunakanRfc2898DeriveBytes
untuk hashing kata sandi (kode sumber di sini ).sumber
Saya telah membaca bahwa fungsi hashing seperti SHA256 tidak benar-benar dimaksudkan untuk digunakan dengan menyimpan kata sandi: https://patrickmn.com/security/storing-passwords-securely/#notpasswordhash
Alih-alih fungsi derivasi kunci adaptif seperti PBKDF2, bcrypt atau scrypt. Berikut ini adalah PBKDF2 berbasis Microsoft yang menulis untuk PasswordHasher di perpustakaan Microsoft.AspNet.Identity mereka:
Catatan ini membutuhkan paket nuget Microsoft.AspNetCore.Cryptography.KeyDerivation diinstal yang memerlukan .NET Standard 2.0 (.NET 4.6.1 atau lebih tinggi). Untuk versi .NET yang lebih lama, lihat Crypto kelas dari perpustakaan System.Web.Helpers Microsoft.
Pembaruan Nov 2015
Jawaban yang diperbarui untuk menggunakan implementasi dari perpustakaan Microsoft yang berbeda yang menggunakan hashing PBKDF2-HMAC-SHA256 bukan PBKDF2-HMAC-SHA1 (catatan PBKDF2-HMAC-SHA1 masih aman jika iterCount cukup tinggi). Anda dapat memeriksa sumber dari kode sederhana yang disalin dari yang sebenarnya menangani validasi dan meningkatkan hash diimplementasikan dari jawaban sebelumnya, berguna jika Anda perlu meningkatkan iterCount di masa depan.
sumber
PBKDF2SubkeyLength
menjadi 20 byte. Itu adalah ukuran alami f SHA1 dan meningkatkannya melebihi yang memperlambat bek tanpa memperlambat penyerang. 2) Saya merekomendasikan untuk meningkatkan jumlah iterasi. Saya merekomendasikan 10k hingga 100k tergantung pada anggaran kinerja Anda. 3) Perbandingan waktu yang konstan juga tidak akan merugikan, tetapi tidak memiliki banyak dampak praktis.Garam digunakan untuk menambah tingkat kerumitan ekstra pada hash, untuk membuatnya lebih sulit retak dengan kasar.
Dari sebuah artikel di Sitepoint :
Tidak ada metode yang secara otomatis melakukan ini di .NET, jadi Anda harus pergi dengan solusi di atas.
sumber
Saya membuat kelas yang memiliki metode berikut:
Validasi input
`
sumber
Bah, ini lebih baik! http://sourceforge.net/projects/pwdtknet/ dan itu lebih baik karena ..... ia melakukan Peregangan Kunci DAN menggunakan HMACSHA512 :)
sumber
Saya telah membuat perpustakaan SimpleHashing.Net untuk mempermudah proses hashing dengan kelas dasar yang disediakan oleh Microsoft. SHA biasa sebenarnya tidak cukup untuk menyimpan kata sandi dengan aman lagi.
Perpustakaan menggunakan gagasan format hash dari Bcrypt, tetapi karena tidak ada implementasi MS resmi saya lebih suka menggunakan apa yang tersedia dalam kerangka kerja (yaitu PBKDF2), tetapi agak terlalu sulit di luar kotak.
Ini adalah contoh cepat cara menggunakan perpustakaan:
sumber
Ini adalah bagaimana saya melakukannya .. Saya membuat hash dan menyimpannya menggunakan
ProtectedData
api:sumber
Saya membaca semua jawaban dan saya pikir cukup mereka, khusus @ Michael artikel dengan hashing lambat dan @CodesInChaos komentar yang baik, tapi saya memutuskan untuk berbagi potongan kode saya untuk hashing / memvalidasi yang mungkin berguna dan tidak memerlukan [ Microsoft.AspNet.Cryptography .KeyDerivation ].
Mohon perhatikan fungsi SlowEquals yang sangat penting, Akhirnya, saya harap bantuan ini dan jangan ragu untuk memberi tahu saya tentang pendekatan yang lebih baik.
sumber
Gunakan
System.Web.Helpers.Crypto
paket NuGet dari Microsoft. Secara otomatis menambahkan garam ke hash.Kata sandi Anda seperti ini:
var hash = Crypto.HashPassword("foo");
Anda memverifikasi kata sandi seperti ini:
var verified = Crypto.VerifyHashedPassword(hash, "foo");
sumber
Jika Anda tidak menggunakan asp.net atau .net core ada juga cara mudah di> = .Net Standard 2.0 proyek.
Pertama, Anda dapat mengatur ukuran hash, garam dan nomor iterasi yang diinginkan yang terkait dengan durasi generasi hash:
Untuk membuat hash dan garam kata sandi, Anda dapat menggunakan sesuatu seperti ini:
Untuk memverifikasi apakah kata sandi yang dimasukkan pengguna valid, Anda dapat memeriksa dengan nilai-nilai di basis data Anda:
Tes unit berikut menunjukkan penggunaan:
Sumber Microsoft Rfc2898DeriveBytes
sumber
Dalam menjawab pertanyaan awal ini, "Apakah ada metode C # lain untuk mem-hashing password" Anda dapat mencapai ini menggunakan ASP.NET Identity v3.0 https://www.nuget.org/packages/Microsoft.AspNet.Identity. EntityFramework / 3.0.0-rc1-final
sumber
sumber
sumber