Kata sandi hash dan garam di C #

178

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?

ACP
sumber
di sini adalah perpustakaan yang melakukan hashing dengan salt encrypto.codeplex.com
Omu
6
Apa yang harus Anda berikan untuk ukuran dalam metode pertama untuk menghasilkan garam?
Shane LeBlanc
6
Tautan rusak.
osmanraifgunes
@ ShaneLeBlanc Anda harus memiliki bit setidaknya sebanyak fungsi yang dihasilkan. SHA1bukan crypto-grade, jadi Anda setidaknya harus menggunakan SHA256, 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.
VSO

Jawaban:

248

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

static byte[] GenerateSaltedHash(byte[] plainText, byte[] salt)
{
  HashAlgorithm algorithm = new SHA256Managed();

  byte[] plainTextWithSaltBytes = 
    new byte[plainText.Length + salt.Length];

  for (int i = 0; i < plainText.Length; i++)
  {
    plainTextWithSaltBytes[i] = plainText[i];
  }
  for (int i = 0; i < salt.Length; i++)
  {
    plainTextWithSaltBytes[plainText.Length + i] = salt[i];
  }

  return algorithm.ComputeHash(plainTextWithSaltBytes);            
}

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 menggunakan Convert.ToBase64StringdanConvert.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

public static bool CompareByteArrays(byte[] array1, byte[] array2)
{
  if (array1.Length != array2.Length)
  {
    return false;
  }

  for (int i = 0; i < array1.Length; i++)
  {
    if (array1[i] != array2[i])
    {
      return false;
    }
  }

  return true;
}

Selalu gunakan garam baru per kata sandi. Garam tidak harus dirahasiakan dan dapat disimpan di samping hash itu sendiri.

blowdart
sumber
3
Terima kasih atas saran ini - sangat membantu saya memulai. Saya juga menemukan tautan ini < dijksterhuis.org/creating-salted-hash-values-in-c > yang saya temukan adalah saran praktis yang bagus dan mencerminkan banyak hal yang dikatakan dalam pos ini
Alex P
18
refactor pernyataan LINQ bagus untuk CompareByteArrays return array1.Length == array2.Length && !array1.Where((t, i) => t != array2[i]).Any();
hunter
6
@Brettski Secara teknis, ya, tetapi memiliki garam yang unik untuk setiap pengguna menjadikan Rainbow Tables (secara umum diterima sebagai cara paling efisien untuk memecahkan kata sandi hash) praktis tidak berguna. Ini adalah oveview cepat yang memberikan gambaran mendalam tapi tidak berlebihan tentang cara menyimpan kata sandi dengan aman, dan mengapa / bagaimana semuanya bekerja.
Ranger
3
@ pemburu: Anda harus menambahkan .ToList () untuk menjadikannya waktu yang konstan. contoh: return array1.Length == array2.Length &&! array1.Where ((t, i) => t! = array2 [i]). ToList (). Any (); Lain, LINQ akan kembali segera setelah ia menemukan satu byte yang tidak sama.
Alex Rouillard
17
-1 untuk menggunakan fungsi hash cepat. Gunakan konstruksi yang lambat seperti PBKDF2, bcrypt atau scrypt.
CodesInChaos
48

Apa yang blowdart katakan, tetapi dengan kode sedikit kurang. Gunakan Linq atau CopyTountuk menggabungkan array.

public static byte[] Hash(string value, byte[] salt)
{
    return Hash(Encoding.UTF8.GetBytes(value), salt);
}

public static byte[] Hash(byte[] value, byte[] salt)
{
    byte[] saltedValue = value.Concat(salt).ToArray();
    // Alternatively use CopyTo.
    //var saltedValue = new byte[value.Length + salt.Length];
    //value.CopyTo(saltedValue, 0);
    //salt.CopyTo(saltedValue, value.Length);

    return new SHA256Managed().ComputeHash(saltedValue);
}

Linq juga memiliki cara mudah untuk membandingkan array byte Anda.

public bool ConfirmPassword(string password)
{
    byte[] passwordHash = Hash(password, _passwordSalt);

    return _passwordHash.SequenceEqual(passwordHash);
}

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 Rfc2898DeriveByteskelas 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 ).

Adam Boddington
sumber
6
@MushinNoShin SHA256 adalah hash cepat. Kata sandi membutuhkan hash yang lambat, seperti PBKDF2, bcrypt atau scrypt. Lihat Bagaimana cara mengamankan kata sandi hash? pada security.se untuk detailnya.
CodesInChaos
32

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:

/* =======================
 * HASHED PASSWORD FORMATS
 * =======================
 * 
 * Version 3:
 * PBKDF2 with HMAC-SHA256, 128-bit salt, 256-bit subkey, 10000 iterations.
 * Format: { 0x01, prf (UInt32), iter count (UInt32), salt length (UInt32), salt, subkey }
 * (All UInt32s are stored big-endian.)
 */

public string HashPassword(string password)
{
    var prf = KeyDerivationPrf.HMACSHA256;
    var rng = RandomNumberGenerator.Create();
    const int iterCount = 10000;
    const int saltSize = 128 / 8;
    const int numBytesRequested = 256 / 8;

    // Produce a version 3 (see comment above) text hash.
    var salt = new byte[saltSize];
    rng.GetBytes(salt);
    var subkey = KeyDerivation.Pbkdf2(password, salt, prf, iterCount, numBytesRequested);

    var outputBytes = new byte[13 + salt.Length + subkey.Length];
    outputBytes[0] = 0x01; // format marker
    WriteNetworkByteOrder(outputBytes, 1, (uint)prf);
    WriteNetworkByteOrder(outputBytes, 5, iterCount);
    WriteNetworkByteOrder(outputBytes, 9, saltSize);
    Buffer.BlockCopy(salt, 0, outputBytes, 13, salt.Length);
    Buffer.BlockCopy(subkey, 0, outputBytes, 13 + saltSize, subkey.Length);
    return Convert.ToBase64String(outputBytes);
}

public bool VerifyHashedPassword(string hashedPassword, string providedPassword)
{
    var decodedHashedPassword = Convert.FromBase64String(hashedPassword);

    // Wrong version
    if (decodedHashedPassword[0] != 0x01)
        return false;

    // Read header information
    var prf = (KeyDerivationPrf)ReadNetworkByteOrder(decodedHashedPassword, 1);
    var iterCount = (int)ReadNetworkByteOrder(decodedHashedPassword, 5);
    var saltLength = (int)ReadNetworkByteOrder(decodedHashedPassword, 9);

    // Read the salt: must be >= 128 bits
    if (saltLength < 128 / 8)
    {
        return false;
    }
    var salt = new byte[saltLength];
    Buffer.BlockCopy(decodedHashedPassword, 13, salt, 0, salt.Length);

    // Read the subkey (the rest of the payload): must be >= 128 bits
    var subkeyLength = decodedHashedPassword.Length - 13 - salt.Length;
    if (subkeyLength < 128 / 8)
    {
        return false;
    }
    var expectedSubkey = new byte[subkeyLength];
    Buffer.BlockCopy(decodedHashedPassword, 13 + salt.Length, expectedSubkey, 0, expectedSubkey.Length);

    // Hash the incoming password and verify it
    var actualSubkey = KeyDerivation.Pbkdf2(providedPassword, salt, prf, iterCount, subkeyLength);
    return actualSubkey.SequenceEqual(expectedSubkey);
}

private static void WriteNetworkByteOrder(byte[] buffer, int offset, uint value)
{
    buffer[offset + 0] = (byte)(value >> 24);
    buffer[offset + 1] = (byte)(value >> 16);
    buffer[offset + 2] = (byte)(value >> 8);
    buffer[offset + 3] = (byte)(value >> 0);
}

private static uint ReadNetworkByteOrder(byte[] buffer, int offset)
{
    return ((uint)(buffer[offset + 0]) << 24)
        | ((uint)(buffer[offset + 1]) << 16)
        | ((uint)(buffer[offset + 2]) << 8)
        | ((uint)(buffer[offset + 3]));
}

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.

Michael
sumber
1
Perhatikan bahwa mungkin perlu meningkatkan PBKDF2IterCount ke nomor yang lebih tinggi, lihat security.stackexchange.com/q/3959 untuk lebih lanjut.
Michael
2
1) Kurangi PBKDF2SubkeyLengthmenjadi 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.
CodesInChaos
KeyDerivationPrf, KeyDerivation dan BlockCopy tidak terdefinisi, apa kelas mereka?
mrbengi
@mrbengi Sudahkah Anda menginstal paket nuget Microsoft.AspNet.Cryptography.KeyDerivation yang disebutkan? Jika itu tidak cocok di sini adalah versi yang tidak memerlukan paket nuget. Buffer.BlockCopy harus ada itu bagian dari Sistem.
Michael
1
Paket nuget sekarang adalah Microsoft.AspNetCore.Cryptography.KeyDerivation.
James Blake
25

Garam digunakan untuk menambah tingkat kerumitan ekstra pada hash, untuk membuatnya lebih sulit retak dengan kasar.

Dari sebuah artikel di Sitepoint :

Seorang hacker masih dapat melakukan apa yang disebut serangan kamus. Pihak jahat dapat membuat serangan kamus dengan mengambil, misalnya, 100.000 kata sandi yang mereka tahu sering digunakan orang (misalnya nama kota, tim olahraga, dll.), Hash mereka, dan kemudian membandingkan setiap entri dalam kamus dengan setiap baris dalam database meja. Jika para peretas menemukan kecocokan, bingo! Mereka memiliki kata sandi Anda. Untuk mengatasi masalah ini, kita hanya perlu garam hash.

Untuk menambahkan hash, kami cukup membuat string teks yang tampak acak, menggabungkannya dengan kata sandi yang disediakan oleh pengguna, lalu mengaitkan string dan kata sandi yang dihasilkan secara acak bersama sebagai satu nilai. Kami kemudian menyimpan hash dan garam sebagai bidang terpisah dalam tabel Pengguna.

Dalam skenario ini, tidak hanya seorang hacker perlu menebak kata sandinya, mereka juga harus menebak garamnya. Menambahkan garam ke teks yang jelas meningkatkan keamanan: sekarang, jika seorang hacker mencoba serangan kamus, ia harus hash 100.000 entri dengan garam dari setiap baris pengguna. Meskipun masih mungkin, peluang keberhasilan peretasan berkurang secara radikal.

Tidak ada metode yang secara otomatis melakukan ini di .NET, jadi Anda harus pergi dengan solusi di atas.

Seb Nilsson
sumber
Garam digunakan untuk bertahan melawan hal-hal seperti meja pelangi. Untuk mempertahankan diri dari serangan kamus diperlukan faktor kerja (juga dikenal sebagai peregangan kunci) seperti KDF yang bagus: en.wikipedia.org/wiki/Key_stretching
Erwan Legrand
11

Saya membuat kelas yang memiliki metode berikut:

  1. Buat Garam
  2. Input Hash
  3. Validasi input

    public class CryptographyProcessor
    {
        public string CreateSalt(int size)
        {
            //Generate a cryptographic random number.
              RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
             byte[] buff = new byte[size];
             rng.GetBytes(buff);
             return Convert.ToBase64String(buff);
        }
    
    
          public string GenerateHash(string input, string salt)
          { 
             byte[] bytes = Encoding.UTF8.GetBytes(input + salt);
             SHA256Managed sHA256ManagedString = new SHA256Managed();
             byte[] hash = sHA256ManagedString.ComputeHash(bytes);
             return Convert.ToBase64String(hash);
          }
    
          public bool AreEqual(string plainTextInput, string hashedInput, string salt)
          {
               string newHashedPin = GenerateHash(plainTextInput, salt);
               return newHashedPin.Equals(hashedInput); 
          }
     }

    `

Bamidele Alegbe
sumber
3

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:

ISimpleHash simpleHash = new SimpleHash();

// Creating a user hash, hashedPassword can be stored in a database
// hashedPassword contains the number of iterations and salt inside it similar to bcrypt format
string hashedPassword = simpleHash.Compute("Password123");

// Validating user's password by first loading it from database by username
string storedHash = _repository.GetUserPasswordHash(username);
isPasswordValid = simpleHash.Verify("Password123", storedHash);
Ilya Chernomordik
sumber
2

Ini adalah bagaimana saya melakukannya .. Saya membuat hash dan menyimpannya menggunakan ProtectedDataapi:

    public static string GenerateKeyHash(string Password)
    {
        if (string.IsNullOrEmpty(Password)) return null;
        if (Password.Length < 1) return null;

        byte[] salt = new byte[20];
        byte[] key = new byte[20];
        byte[] ret = new byte[40];

        try
        {
            using (RNGCryptoServiceProvider randomBytes = new RNGCryptoServiceProvider())
            {
                randomBytes.GetBytes(salt);

                using (var hashBytes = new Rfc2898DeriveBytes(Password, salt, 10000))
                {
                    key = hashBytes.GetBytes(20);
                    Buffer.BlockCopy(salt, 0, ret, 0, 20);
                    Buffer.BlockCopy(key, 0, ret, 20, 20);
                }
            }
            // returns salt/key pair
            return Convert.ToBase64String(ret);
        }
        finally
        {
            if (salt != null)
                Array.Clear(salt, 0, salt.Length);
            if (key != null)
                Array.Clear(key, 0, key.Length);
            if (ret != null)
                Array.Clear(ret, 0, ret.Length);
        } 
    }

    public static bool ComparePasswords(string PasswordHash, string Password)
    {
        if (string.IsNullOrEmpty(PasswordHash) || string.IsNullOrEmpty(Password)) return false;
        if (PasswordHash.Length < 40 || Password.Length < 1) return false;

        byte[] salt = new byte[20];
        byte[] key = new byte[20];
        byte[] hash = Convert.FromBase64String(PasswordHash);

        try
        {
            Buffer.BlockCopy(hash, 0, salt, 0, 20);
            Buffer.BlockCopy(hash, 20, key, 0, 20);

            using (var hashBytes = new Rfc2898DeriveBytes(Password, salt, 10000))
            {
                byte[] newKey = hashBytes.GetBytes(20);

                if (newKey != null)
                    if (newKey.SequenceEqual(key))
                        return true;
            }
            return false;
        }
        finally
        {
            if (salt != null)
                Array.Clear(salt, 0, salt.Length);
            if (key != null)
                Array.Clear(key, 0, key.Length);
            if (hash != null)
                Array.Clear(hash, 0, hash.Length);
        }
    }

    public static byte[] DecryptData(string Data, byte[] Salt)
    {
        if (string.IsNullOrEmpty(Data)) return null;

        byte[] btData = Convert.FromBase64String(Data);

        try
        {
            return ProtectedData.Unprotect(btData, Salt, DataProtectionScope.CurrentUser);
        }
        finally
        {
            if (btData != null)
                Array.Clear(btData, 0, btData.Length);
        }
    }

    public static string EncryptData(byte[] Data, byte[] Salt)
    {
        if (Data == null) return null;
        if (Data.Length < 1) return null;

        byte[] buffer = new byte[Data.Length];

        try
        {
            Buffer.BlockCopy(Data, 0, buffer, 0, Data.Length);
            return System.Convert.ToBase64String(ProtectedData.Protect(buffer, Salt, DataProtectionScope.CurrentUser));
        }
        finally
        {
            if (buffer != null)
                Array.Clear(buffer, 0, buffer.Length);
        }
    }
JGU
sumber
Bagaimana cara saya menyebutnya sambil menyimpan dan ketika membandingkan nanti?
SearchForKnowledge
2

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 ].

    private static bool SlowEquals(byte[] a, byte[] b)
            {
                uint diff = (uint)a.Length ^ (uint)b.Length;
                for (int i = 0; i < a.Length && i < b.Length; i++)
                    diff |= (uint)(a[i] ^ b[i]);
                return diff == 0;
            }

    private static byte[] PBKDF2(string password, byte[] salt, int iterations, int outputBytes)
            {
                Rfc2898DeriveBytes pbkdf2 = new Rfc2898DeriveBytes(password, salt);
                pbkdf2.IterationCount = iterations;
                return pbkdf2.GetBytes(outputBytes);
            }

    private static string CreateHash(string value, int salt_bytes, int hash_bytes, int pbkdf2_iterations)
            {
                // Generate a random salt
                RNGCryptoServiceProvider csprng = new RNGCryptoServiceProvider();
                byte[] salt = new byte[salt_bytes];
                csprng.GetBytes(salt);

                // Hash the value and encode the parameters
                byte[] hash = PBKDF2(value, salt, pbkdf2_iterations, hash_bytes);

                //You need to return the salt value too for the validation process
                return Convert.ToBase64String(hash) + ":" + 
                       Convert.ToBase64String(hash);
            }

    private static bool ValidateHash(string pureVal, string saltVal, string hashVal, int pbkdf2_iterations)
            {
                try
                {
                    byte[] salt = Convert.FromBase64String(saltVal);
                    byte[] hash = Convert.FromBase64String(hashVal);

                    byte[] testHash = PBKDF2(pureVal, salt, pbkdf2_iterations, hash.Length);
                    return SlowEquals(hash, testHash);
                }
                catch (Exception ex)
                {
                    return false;
                }
            }

Mohon perhatikan fungsi SlowEquals yang sangat penting, Akhirnya, saya harap bantuan ini dan jangan ragu untuk memberi tahu saya tentang pendekatan yang lebih baik.

QMaster
sumber
Daripada membuat loop sibuk, mengapa tidak membuat penundaan non-sibuk buatan. mis. menggunakan Task.Delay. Ini akan menunda upaya kekerasan tetapi tidak memblokir utas aktif.
gburton
@ gburton Terima kasih atas saran Anda. Saya akan memeriksanya.
QMaster
Ada salah ketik di CreateHash: Anda concaneting Convert.ToBase64String (hash) untuk dirinya sendiri, bukan garam. Selain itu, ini adalah jawaban yang bagus yang membahas hampir semua masalah yang diangkat dalam komentar tentang jawaban lain.
ZeRemz
2

Gunakan System.Web.Helpers.Cryptopaket 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");

Kai Hartmann
sumber
1

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:

private const int SaltSize = 32;
private const int HashSize = 32;
private const int IterationCount = 10000;

Untuk membuat hash dan garam kata sandi, Anda dapat menggunakan sesuatu seperti ini:

public static string GeneratePasswordHash(string password, out string salt)
{
    using (Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, SaltSize))
    {
        rfc2898DeriveBytes.IterationCount = IterationCount;
        byte[] hashData = rfc2898DeriveBytes.GetBytes(HashSize);
        byte[] saltData = rfc2898DeriveBytes.Salt;
        salt = Convert.ToBase64String(saltData);
        return Convert.ToBase64String(hashData);
    }
}

Untuk memverifikasi apakah kata sandi yang dimasukkan pengguna valid, Anda dapat memeriksa dengan nilai-nilai di basis data Anda:

public static bool VerifyPassword(string password, string passwordHash, string salt)
{
    using (Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, SaltSize))
    {
        rfc2898DeriveBytes.IterationCount = IterationCount;
        rfc2898DeriveBytes.Salt = Convert.FromBase64String(salt);
        byte[] hashData = rfc2898DeriveBytes.GetBytes(HashSize);
        return Convert.ToBase64String(hashData) == passwordHash;
    }
}

Tes unit berikut menunjukkan penggunaan:

string password = "MySecret";

string passwordHash = PasswordHasher.GeneratePasswordHash(password, out string salt);

Assert.True(PasswordHasher.VerifyPassword(password, passwordHash, salt));
Assert.False(PasswordHasher.VerifyPassword(password.ToUpper(), passwordHash, salt));

Sumber Microsoft Rfc2898DeriveBytes

eugstman
sumber
-1

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

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNet.Identity;
using System.Security.Principal;

namespace HashTest{


    class Program
    {
        static void Main(string[] args)
        {

            WindowsIdentity wi = WindowsIdentity.GetCurrent();

            var ph = new PasswordHasher<WindowsIdentity>();

            Console.WriteLine(ph.HashPassword(wi,"test"));

            Console.WriteLine(ph.VerifyHashedPassword(wi,"AQAAAAEAACcQAAAAEA5S5X7dmbx/NzTk6ixCX+bi8zbKqBUjBhID3Dg1teh+TRZMkAy3CZC5yIfbLqwk2A==","test"));

        }
    }


}
Dave Cornall
sumber
-1
 protected void m_GenerateSHA256_Button1_Click(objectSender, EventArgs e)
{
string salt =createSalt(10);
string hashedPassword=GenerateSHA256Hash(m_UserInput_TextBox.Text,Salt);
m_SaltHash_TextBox.Text=Salt;
 m_SaltSHA256Hash_TextBox.Text=hashedPassword;

}
 public string createSalt(int size)
{
 var rng= new System.Security.Cyptography.RNGCyptoServiceProvider();
 var buff= new byte[size];
rng.GetBytes(buff);
 return Convert.ToBase64String(buff);
}


 public string GenerateSHA256Hash(string input,string salt)
{
 byte[]bytes=System.Text.Encoding.UTF8.GetBytes(input+salt);
 new System.Security.Cyptography.SHA256Managed();
 byte[]hash=sha256hashString.ComputedHash(bytes);
 return bytesArrayToHexString(hash);
  }
ankush shukla
sumber
metode lain adalah string password = HashPasswordForStoringInConfigFile (TextBox1.Text, SHA1)
ankush shukla
-6
create proc [dbo].[hash_pass] @family nvarchar(50), @username nvarchar(50), @pass nvarchar(Max),``` @semat nvarchar(50), @tell nvarchar(50)

as insert into tbl_karbar values (@family,@username,(select HASHBYTES('SHA1' ,@pass)),@semat,@tell)
ehsan
sumber