Question

I salted and hashed my logins according to this Code Project article

When I did this, my password and salt fields in the database were just varchar columns. The data was displayed in SQL Server Management Studio as question marks.

A friend then came and changed the columns to nvarchar data type and now the data appears to be a collection of Asian letters/words - I assume there's no sense behind it even to someone who does read whatever language it is.

The problem is that now, even when I created a new user, every login attempt fails.

User addition and login

    public User Login() // returns an instance of its own class
    {

        // get the salt value for the user
        var auser = ie.users.FirstOrDefault(u => String.Compare(u.emailaddress, emailaddress, false) == 0);
        if (auser == null)
        {
            throw new ValidationException("User not found");
        }

        // hash the login for comparison to stored password hash
        HashGenerator h = new HashGenerator(password, auser.usersalt);
        string hash = h.GetHash();

        var us = ie.users.FirstOrDefault(u => String.Compare(u.emailaddress, emailaddress, false) == 0 && String.Compare(u.password, password, false) == 0);

        if (us == null)
        {
            throw new Exception("Invalid email address and/or password."); // seems here's where it goes wrong
        }
        User user = new User();

        user.userid = us.userid;
        user.storeid = us.storeid;
        user.role = us.role;

        return user; // login succeeded, return the data to the calling method
    }

    public void Add()
    {
        user newuser = new user();
        newuser.storeid = storeid;
        newuser.emailaddress = emailaddress;

        // Generate password hash
        string usersalt = SaltGenerator.GetSaltString();
        HashGenerator hash = new HashGenerator(password, usersalt);
        newuser.password = hash.GetHash();

        newuser.role = role;
        newuser.usersalt = usersalt;

        ie.users.Add(newuser);
        ie.SaveChanges();
    }

Hash and Salt Generator

public class HashGenerator
{
    public string pass { get; protected set; }
    public string salt { get; protected set; }

    public HashGenerator(string Password, string Salt)
    {
        pass = Password;
        salt = Salt;
    }

    public string GetHash()
    {
        SHA512 sha = new SHA512CryptoServiceProvider();
        byte[] data = CryptUtility.GetBytes(String.Format("{0}{1}", pass, salt));
        byte[] hash = sha.ComputeHash(data);

        return CryptUtility.GetString(hash);
    }
}

public static class SaltGenerator
{
    private static RNGCryptoServiceProvider provider = null;
    private const int saltSize = 128;

    static SaltGenerator()
    {
        provider = new RNGCryptoServiceProvider();
    }

    public static string GetSaltString()
    {
        byte[] saltBytes = new byte[saltSize];

        provider.GetNonZeroBytes(saltBytes);

        return CryptUtility.GetString(saltBytes);
    }
}

Crypt utility for getting strings and bytes

class CryptUtility
{
    public static byte[] GetBytes(string Str)
    {
        byte[] bytes = new byte[Str.Length * sizeof(char)];
        System.Buffer.BlockCopy(Str.ToCharArray(), 0, bytes, 0, bytes.Length);
        return bytes;
    }

    public static string GetString(byte[] Bytes)
    {
        char[] chars = new char[Bytes.Length / sizeof(char)];
        System.Buffer.BlockCopy(Bytes, 0, chars, 0, Bytes.Length);
        return new string(chars);
    }
}

The login used to work and this code hasn't changed since then... The only thing that's changed is that the password and salt columns in the users table are now nvarchar instead of varchar.

That said, I figured I'd create a new user with the add method above, but logging in with that user fails as well.

I'm really at a loss as to how to fix this. I can't proceed to develop the rest of the system if I can't access it to test.

Any help will be greatly appreciated!

Was it helpful?

Solution

humm shouldn't you be using the variable

hash

for the comparison ?

    // hash the login for comparison to stored password hash
    HashGenerator h = new HashGenerator(password, auser.usersalt);
    string hash = h.GetHash();

    var us = ie.users.FirstOrDefault(u => String.Compare(u.emailaddress, emailaddress, false) == 0 && String.Compare(u.password, hash, false) == 0);

OTHER TIPS

Make a db backup and convert back to varchar. Or rollback to the backup before the conversion. It seems your friend did something wrong when converting the data type to nvarchar.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top