为什么我在使用 MD5 哈希的 C# 中遇到某种密码的连接问题?

Why I am having connection Issues with some kind of passwords in C# using MD5 hash?

根据我在数据库中存储的密码类型,我的程序在尝试在第一个 "if" 中执行 Reader.close() 时在 "Consulta" 方法上崩溃。

例如,如果我将密码设置为“1234”,我没有任何问题,而使用 "prueba" 则会发生崩溃,甚至不会进入 "catch"。

这是保存新用户的方法,在按钮事件中。

private void bbtnGuardar_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
    {
        DB con = new DB(path);

        MD5 md5 = MD5.Create();

        byte[] hash = md5.ComputeHash(Encoding.Default.GetBytes(tbPassword.Text));
        String encryptedPassword = Encoding.Default.GetString(hash);

        string query = "INSERT INTO IEM182_LOGIN (USUARIO, PASSWORD) VALUES " +
            "('" + tbUsuario.Text + "', '" + encryptedPassword + "');";

        try
        {
            con.Consulta(query);
            MessageBox.Show("Nuevo usuario dado de alta correctamente");
            limpiar_usuario();
        }
        catch
        {
            try
            {
                con.Cerrar();
                query = "SELECT * FROM IEM182_LOGIN WHERE USUARIO = '" + tbUsuario.Text + "'";
                con.Consulta(query);
                if (con.Reader.Read())
                {
                    MessageBox.Show("El nombre de usuario ya existe");
                }
            }
            catch
            {
                MessageBox.Show("El usuario contiene caracteres no validos");
            }
            con.Cerrar();
    }

这是包含一些方法的数据库class。

class DB
{
    private SqlDataReader rdr;
    private string path;
    private SqlConnection con;
    private SqlCommand cmd;

    public DB(string cadenaConexion)
    {
        path = cadenaConexion;
        con = new SqlConnection(path);
    }

    public void Consulta(string query)
    {
        if (Conexion.State == System.Data.ConnectionState.Open)
        {
            cmd = new SqlCommand(query, con);
            Reader.Close();
            Reader = cmd.ExecuteReader();
        }
        else
        {
            con.Open();
            cmd = new SqlCommand(query, con);
            Reader = cmd.ExecuteReader();
        }
    }

    public SqlDataReader Reader
    {
        get { return rdr; }
        set { rdr = value; }
    }

    public void Cerrar()
    {
        con.Close();
    }

    public SqlConnection Conexion
    {
        get { return con; }
        set { con = value; }
    }

这是你的问题:

byte[] hash = md5.ComputeHash(Encoding.Default.GetBytes(tbPassword.Text));
String encryptedPassword = Encoding.Default.GetString(hash);

绝对没有保证你从哈希算法得到的字节形成合法的unicode字符串,事实上我会说这是一个非常小的机会将产生可用的字符串。似乎您发现了一些奇怪的情况。这只是偶然。

您应该通过Encoding.Default.GetString管道传输这些字节,而您应该使用像 Base 64 编码这样的东西:

String encryptedPassword = Convert.ToBase64String(bytes);

这将生成一个没有古怪字符的字符串,这些字符不会在数据库往返中存活下来。

要取回哈希字节,您使用相同的 class:

进行解码
byte[] hash = Convert.FromBase64String(encryptedPassword);

现在,这是您的代码的唯一问题吗?

不,不是。

第二个问题,加上上面的问题,会给你的 SQL 执行带来麻烦:

string query = "INSERT INTO IEM182_LOGIN (USUARIO, PASSWORD) VALUES " +
        "('" + tbUsuario.Text + "', '" + encryptedPassword + "');";

你应该永远不要通过字符串连接形成SQL,你应该使用参数。

由于您创建了一个方法,Consulta 执行此查询,实际上修改您的代码以使用参数是相当多的更改,但要执行上述 SQL、使用参数,你会做这样的事情:

string query = "INSERT INTO IEM182_LOGIN (USUARIO, PASSWORD) VALUES " +
        "(@username, @password);";
var cmd = new SqlCommand();
cmd.CommandText = query;
cmd.Parameters.AddWithValue("@username", tbUsuario.Text);
cmd.Parameters.AddWithValue("@password", encryptedPassword);
cmd.ExecuteNonQuery();

具体如何更改 Consultas 方法来处理此问题取决于您,但 这是您必须采用的方式!

所以为了解决我遇到的问题,我使用了另一种加密方法

// byte array representation of that string
        byte[] encodedPassword = new UTF8Encoding().GetBytes(password);

        // need MD5 to calculate the hash
        byte[] hash = ((HashAlgorithm)CryptoConfig.CreateFromName("MD5")).ComputeHash(encodedPassword);

        // string representation (similar to UNIX format)
        string encoded = BitConverter.ToString(hash)
            // without dashes
           .Replace("-", string.Empty)
            // make lowercase
           .ToLower();

并修复了第一个 "try/catch" 添加另一个 try/catch 以调用 con.Consulta() 方法并捕获无效字符。

非常感谢https://whosebug.com/users/267/lasse-v-karlsen