C# WPF Inicie sesión y regístrese con hashing y base de datos

 C Programming >> Programación C >  >> Tags >> WPF
C# WPF Inicie sesión y regístrese con hashing y base de datos

La solución para el inicio de sesión y el registro de C# WPF con hash y base de datos
se proporciona a continuación:

lo que quiero lograr:

Quiero hacer un sistema de cuenta con inicio de sesión y registro. Ya tengo el sistema de inicio de sesión y registro, este también está conectado a la base de datos. Sin embargo, las contraseñas no tienen hash.
No puedo encontrar ninguna ayuda sobre cómo hacer hash en relación con la base de datos.
Además, todavía me pregunto cómo agrego un poco de sal, ya que esto sería más seguro.

Problema:
Ver arriba

código de inicio de sesión:

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();
            }
        }

Cosas hash que quiero implementar

obtener SHA:

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

coincidir con 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;
    }

prueba:

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!");
        }
    }

Ya está familiarizado con cómo almacenar una cadena en la base de datos aquí:

Ya que sabe cómo almacenar la contraseña como un string en la base de datos, y también sabe cómo codificar la contraseña con GetSHA1() – todo lo que tenemos que hacer es convertir la contraseña codificada en un string .

GetSHA1 actualmente devuelve un byte[] que es la contraseña cifrada y el nombre de usuario.

Para convertir el byte[] en un string deberíamos Codificar (formatear los bytes en texto legible por humanos) de bytes a un string . Vamos a usar el System.Convert.ToBase64String() método que toma cualquier byte[] y lo convierte en una cadena.

Una vez que hemos codificado los bytes hash en un string no tenemos que usar MatchSHA1 más y puede eliminar ese método. Esto se debe a que podemos comparar string s con el == operador o utilizando otros métodos integrados.

Si podemos convertir el hash en una cadena en lugar de

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

en cambio, podríamos usar una mucho más simple

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

Podemos fortalecer aún más la forma en que hacemos hash actualizando a SHA384 desde SHA1 ya no se recomienda su uso debido a su alta tasa de colisión.

Seguí adelante y modifiqué tu GetSHA1 siguiente método con los cambios recomendados

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);
}

Para almacenar la contraseña simplemente reemplace

con lo siguiente

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

Si este es un proyecto apasionante

SHA no incluye una implementación de salazón, para ello tendrías que hacerlo tú mismo. Dejaré esto como un ejercicio para el lector u otros desarrolladores útiles.

Si se trata de un proyecto de producción

Recomendaría usar una implementación lista para usar como BCrypt o algo similar. Dado que la implementación de una función salt and hash segura puede dar lugar a vulnerabilidades de seguridad no recomiendo que las implemente usted mismo .