C# WPF Accedi e registrati con hash e database

 C Programming >> Programmazione C >  >> Tags >> WPF
C# WPF Accedi e registrati con hash e database

La soluzione per C# WPF Login e Register con hash e database
è indicata di seguito:

cosa voglio ottenere:

Voglio creare un sistema di account con login e registrazione. Ho già il sistema di login e registrazione, anche questo è collegato al database. Tuttavia, le password non vengono sottoposte a hash.
Non riesco a trovare alcun aiuto su come eseguire l'hashing in connessione con il database.
Inoltre, mi chiedo ancora come aggiungo un po' di sale, poiché questo sarebbe più sicuro.

Problema:
Vedi sopra

codice per l'accesso:

private void btn_login_Click(object sender, RoutedEventArgs e)
        {
            SqlConnection sqlCon = new SqlConnection("Server=xxxxx;Database=x;User Id=xxx;Password=xx;");
            try
            {
                if (sqlCon.State == System.Data.ConnectionState.Closed)
                    sqlCon.Open();
                String query = "SELECT COUNT(1) FROM tblUser WHERE [email protected] AND [email protected]";
                SqlCommand sqlCmd = new SqlCommand(query, sqlCon);
                sqlCmd.CommandType = System.Data.CommandType.Text;
                sqlCmd.Parameters.AddWithValue("@Username", txtUsername.Text);
                sqlCmd.Parameters.AddWithValue("@Password", txtPassword.Text);
                int count = Convert.ToInt32(sqlCmd.ExecuteScalar());
                if (count == 1)
                {
                    MessageBox.Show("Success!");
                }
                else
                {
                    MessageBox.Show("Wrong!");
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            finally
            {
                sqlCon.Close();
            }
        }

Cose hash che voglio implementare

ottieni SHA:

private static byte[] GetSHA1(string userID, string password)
    {
    SHA1CryptoServiceProvider sha = new SHA1CryptoServiceProvider();
    return sha.ComputeHash(System.Text.Encoding.ASCII.GetBytes(userID + password));
    }

corrisponde a SHA:

private static bool MatchSHA1(byte[] p1, byte[] p2)
    {
    bool result = false;
    if (p1 != null && p2 != null)
        {
        if (p1.Length == p2.Length)
            {
            result = true;
            for (int i = 0; i < p1.Length; i++)
                {
                if (p1[i] != p2[i])
                    {
                    result = false;
                    break;
                    }
                }
            }
        }
    return result;
    }

prova:

private static void RunTest()
    {
    string userId = "OriginalGriff";
    string password = "NotMyPassword";
    string enteredPassword = "NotMyPassword";
    string notPassword = "notMyPassword";
    byte[] hashedPassword = GetSHA1(userId, password);
    if (MatchSHA1(hashedPassword, GetSHA1(userId, enteredPassword)))
        {
        Console.WriteLine("Log him in!");
        }
    else
        {
        Console.WriteLine("Don't log him in!");
        }
    if (MatchSHA1(hashedPassword, GetSHA1(userId, notPassword)))
        {
        Console.WriteLine("Will not happen!");
        }
    else
        {
        Console.WriteLine("Don't log him in!");
        }
    }

Hai già familiarità con come archiviare una stringa nel database qui:

Dal momento che sai come memorizzare la password come string nel database e sai anche come eseguire l'hashing della password con GetSHA1() – tutto ciò che dobbiamo fare è trasformare la password con hash in un string .

GetSHA1 attualmente restituisce un byte[] che è la password e il nome utente con hash.

Per trasformare il byte[] in un string dovremmo Codificare (formatta i byte in testo leggibile dall'uomo) dai byte in un string . Utilizzeremo System.Convert.ToBase64String() metodo che accetta qualsiasi byte[] e lo trasforma in una stringa.

Dopo aver codificato i byte con hash in un string non dobbiamo usare MatchSHA1 più e può eliminare quel metodo. Questo perché possiamo confrontare string s con il == operatore o utilizzando altri metodi integrati.

Se riusciamo a trasformare l'hash in una stringa invece di

if (MatchSHA1(hashedPassword, GetSHA1(userId, enteredPassword)))
{
    Console.WriteLine("Log him in!");
}

potremmo invece usare un molto più semplice

if (hashedPassword == SHA384(userId, enteredPassword))
{
    Console.WriteLine("Log him in!");
}

Possiamo rafforzare ulteriormente il modo in cui eseguiamo l'hash aggiornando a SHA384 dal SHA1 non è più consigliato per l'uso a causa del suo alto tasso di collisione.

Sono andato avanti e ho modificato il tuo GetSHA1 metodo seguente con le modifiche consigliate

private static string GetSHA384(string userID, string password)
{
    // SHA classes are disposable, use using to ensure any managed resources are properly disposed of by the runtime
    using SHA384 sha = new SHA384CryptoServiceProvider();

    // convert the username and password into bytes
    byte[] preHash = Encoding.ASCII.GetBytes(userID + password);

    // hash the bytes
    byte[] hash = sha.ComputeHash(preHash);

    // convert the raw bytes into a string that we can save to a database
    return Convert.ToBase64String(hash);
}

Per memorizzare la password è sufficiente sostituirla

con quanto segue

sqlCmd.Parameters.AddWithValue("@Password", GetSHA384(txtUsername.Text, txtPassword.Text));

Se questo è un progetto di passione

SHA non include un'implementazione della salatura, per questo dovresti farlo da solo. Lascerò questo come esercizio per il lettore o altri sviluppatori utili.

Se questo è un progetto di produzione

Consiglierei di utilizzare un'implementazione standard come BCrypt o qualcosa di simile. Poiché l'implementazione autonoma di una funzione salt e hash sicura può portare a vulnerabilità di sicurezza Non consiglio di implementarle automaticamente .