0

I got this register form where i get the user email and password and hash the password using SHA512

 public Boolean IsRegistered(String email, String pass)
    {
        SHA512 shaM = new SHA512Managed();
        if (pass.Length > 0 && email.Length > 0)
        {
            byte[] data = Encoding.UTF8.GetBytes(pass);
            String encryptedpass = Encoding.UTF8.GetString(shaM.ComputeHash(data));
            using (ModelContainer db = new ModelContainer())
            {
                //User usr = db.UserSet.Where(u => u.PasswordDigest == encryptedpass && u.Email == email).First();

                  int matches = (from u in bd.UserSet
                                 where u.PasswordDigest == encryptedpass&& u.Email == email
                                 select new
                                 {
                                     Id = u.Id
                                 }
                             ).Count();
                if (matches > 0)
                {
                    return true;
                }
            }
        }
        return false;
    }

I use this method each time the user logs in and it works like a charm (i guess), thing is when i prompt the user to change his/her password i cannot seem to be able to validate the old one here is what i try

I do the following to retrive the user data on the MyAccount form's constructor

    User user;.

    public MyAccount()
    {
        InitializeComponent();

        try
        {
            using (ModelContainer db = new ModelContainer())
            {
                user = (from u in db.UserSet where u.Id == 2 select u).First();

                txtName.Text = user.Name;
                txtEmail.Text = user.Email;
            }
        }
        catch (Exception x)
        {
            ErrorAlert error = new ErrorAlert("Error: " + x.Message);
            error.Owner = getParentWindow();
            error.ShowDialog();
        }
    }

then I validate it on the forms button_click

using (ModelContainer db = new ModelContainer())
            {
                SHA512 shaM = new SHA512Managed();
                string oldpass = Encoding.UTF8.GetString(shaM.ComputeHash(Encoding.UTF8.GetBytes(ptxtOldPassword.Password)));
                shaM.Dispose();

                db.UserSet.Attach(user);

                Regex rgx = new Regex(@"\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z");

                if (rgx.IsMatch(txtEmail.Text))
                {
                    if (oldpass == user.PasswordDigest)
                    {
                        if (ptxtNewPassword.Password.Equals(ptxtNewPassword2.Password))
                        {
                            string newpass = Encoding.UTF8.GetString(shaM.ComputeHash(Encoding.UTF8.GetBytes(ptxtNewPassword.Password)));
                            user.Name = txtName.Text;
                            user.Email = txtEmail.Text;
                            user.PasswordDigest = newpass;

                            db.SaveChanges();
                        }
                        else
                        {
                            ErrorAlert error = new ErrorAlert("Passwords do not match");
                            error.Owner = getParentWindow();
                            error.ShowDialog();
                        }

When I comapare the old password in the database with the one the user enter they do not match since they are strings I've tried using equals with no luck I thought == would work but I was wrong, i looked into other answers and found this Sha512 not returning equal in c# hash validation sadly it didn't work for me, I need to understand why my first validation work and the second doesnt so any help is apreciated Have a nice day

SoulBlack
  • 41
  • 8
  • Uh... trying to decode SHA512 byte data as a UTF-8 string is just asking for trouble... How are the SHA512 hashes stored in the DB? –  Jun 20 '17 at 23:26
  • @elgonzo they are stored as strings, not as utf-8 string though, you might be right – SoulBlack Jun 20 '17 at 23:36
  • It seems to me you do not seem to understand the problem i was pointing at. The problem was not UTF-8 string vs. non-UTF-8 string. You cannot always successfully decode any arbitrary byte data as a string, since arbitrary byte data could contain bytes (or byte sequences) that would be invalid for a given text encoding, or represent certain non-printable characters which could potentially mess up further string processing. (1/2) –  Jun 21 '17 at 07:32
  • (2/2) If you want to store the hashes in the db as a string field (and not as something like a *binary* field), i would suggest to [base64-encode](https://msdn.microsoft.com/en-us/library/dhx0d524(v=vs.110).aspx) the sha byte data. Base64's purpose is precisely to encode arbitrary byte data as (ASCII) strings. But personally, i would prefer storing the byte data of the sha512 hashes (possibly additionally encrypted) in *binary(64)* fields... –  Jun 21 '17 at 07:32
  • @elgonzo ok I guess I can encode the bytes to base 64, or just store the passwords in binary as you suggest, but that still doesn't explain why my login validation works and my change password does not, also when I debug I can clearly see that the hashes are equal – SoulBlack Jun 21 '17 at 19:07
  • From your question i believe you take issue with the the string equality operator `==` apparently failing (note that you are comparing strings here). However, `==` doesn't fail -- otherwise almost every single .NET program would be horribly broken. So, your assumption that the two compared strings are equal is incorrect. What exactly is going on there in your program and db i can't tell, since i can't debug it and see what really is going on there. And since you should fix this issue with the unreliable UTF-8 conversion of the SHA512 hash anyway, this problem will perhaps go away anyway... –  Jun 21 '17 at 19:17
  • @elgonzo Of course == operator isn't broken, by your logic my first valdation should not work etiher, i could post a screen shot where i debug and show you the value i see. but it might not make any difference, anyways, is UTF-8 truly the problem here? what i'm trying to say is, will using another type of encoding fix my problem? thanks by the way – SoulBlack Jun 22 '17 at 14:47

1 Answers1

0

You don't really need to compare the final strings, test at the bytes-level. Check this previous question.

Also, if you already validated the existence of the user (by email or any other mechanism), why don't just change / update with the new password? You could validate with the email and re-use the working function for login / signin.

Jose Cordero
  • 526
  • 5
  • 15