简体   繁体   中英

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

Depending in what kind of password I use to store in the database my program crashes on "Consulta" method when its trying to do Reader.close() inside the first "if".

For example if I set as password "1234" I have no problems, with "prueba" instead the crash happens and it doesnt even go to "catch".

This is the method to save a new user, which is in a button event.

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

This is the database class with some methods.

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

This is your problem:

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

There is absolutely no guarantee that the bytes you get back from a hash algorithm forms a legal unicode string, in fact I would say that it is a very slim chance that this will produce usable strings at all. Seems you have found a few odd cases that do. This is just by chance.

You should not pipe those bytes through Encoding.Default.GetString , instead you should use something like Base 64 encoding:

String encryptedPassword = Convert.ToBase64String(bytes);

This will produce a string that doesn't have oddball characters that won't survive a roundtrip through the database.

To get the hash bytes back you decode using the same class:

byte[] hash = Convert.FromBase64String(encryptedPassword);

Now, is this the only problem with your code?

No, it isn't.

The second problem, that coupled with the above one, will throw a spanner into your SQL execution is this:

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

You should never form a SQL through string concatenation, you should instead use parameters.

Since you've made a method, Consulta that does this querying, actually modifying your code to use parameters is quite a bit of changes but to execute the above SQL, with parameters , you would do something like this:

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

Exactly how you go about changing your Consultas method to handle this is up to you, but this is the way you must do it!

So to fix the problem I was having I used another encrypting method

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

And fixed the first "try/catch" adding another try/catch to call the con.Consulta() method and to catch the invalid characters.

Thanks you very much https://stackoverflow.com/users/267/lasse-v-karlsen

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM