2
\$\begingroup\$

In a WinForms application I'm doing the password validation as follows:

When the user presses the OK button after entering username and password, an event will be fired and the listener in the presenter will then do the validation with the help of the Encryption class. It will basically compare the two hash values.

User Model

class User
{
    string UserID { get; set; }
    string Name { get; set; }
    string NIC {get;set;}
    string Designation { get; set; }
    string PassWord { get; set; }
    List<string> Permission = new List<string>();
    bool status { get; set; }
    DateTime EnteredDate { get; set; }

}

Login form

public partial class frmLogin : Form , IView
{
    public event EventHandler OnValidatePassword;

    public string UserName
    {
        get { return txtUser.Text; }
    }

    public string Password
    {
        get { return txtPassword.Text; }
    }

    public bool Valid { get; set; }


    private void btnOK_Click(object sender, EventArgs e)
    {

        OnValidatePassword(sender, e);
        if (Valid)
        {
            frmMain Main = new frmMain();
            Main.ShowDialog();
        }
    }
}

Presenter

class LoginPresenter
{
    IView _View;
    User _Model;
    DataService _DataService;

    public LoginPresenter( IView view, User model, DataService dataService )
    {
        _View = view;
        _Model = model;
        _DataService = dataService;
        SetModelPropertiesFromView();
        WireUpEvents();
    }

    private void SetModelPropertiesFromView()
    {
        _Model.UserName = _View.UserName;
        _Model.Password = _View.Password;
    }

    private void WireUpEvents()
    {
        _View.OnValidatePassword += new EventHandler(_View_OnValidatePassword);
    }

    void _View_OnValidatePassword(object sender, EventArgs e)
    {
        ValidatePassword();
    }

    private void ValidatePassword()
    {
        var hash = Encryption.GetHash(_Model.UserName, _Model.Password);
        var hashInDB = _DataService.GetUserCredentials( _Model.UserName); //returns a hash value

        if (hash != hashInDB)
        {
            MessageBox.Show("Invalid username or password");
            _View.Valid = false;
        }
        else
        {
            _View.Valid = true;
        }
    }
}

Encryption

class Encryption
{
    public static string GetHash(string salt, string password)
    {
        MD5CryptoServiceProvider hash = new MD5CryptoServiceProvider();            
        byte[] plainTextBytes = Encoding.UTF8.GetBytes(salt + password);
        byte[] hashBytes = hash.ComputeHash(plainTextBytes);

        string hashValue = Convert.ToBase64String(hashBytes);
        return hashValue;

    }
}

I'm unsure of the way I'm calling main form's ShowDialog() method in the login form. In that case I'm not using a presenter for the main form as it is just a MDI form which is only holding links to other forms.

Would MD5 encryption would be enough in this level?

Could you please review this code and provide your feedback?

\$\endgroup\$
2
\$\begingroup\$

For the GetHash() function you could go with PBKDF2. It was specifically created to address password hashing. It requires at least 8 bytes of salt, so the code below builds a SHA1 hash to "stretch" your salt to that minimum length. The better approach would be to generate a cryptographically-strong random salt and store that along with the resulting hash. (c.f. RNGCryptoServiceProvider)

public static string GetHash(string salt, string password)
{
    if (string.IsNullOrEmpty(salt))
    {
        throw new ArgumentNullException("salt");
    }

    if (string.IsNullOrEmpty(password))
    {
        throw new ArgumentNullException("password");
    }

    byte[] passwordSaltBytes = System.Text.Encoding.UTF8.GetBytes(salt);

    if (passwordSaltBytes.Length < 8)
    {
        using (var saltStretcher = System.Security.Cryptography.SHA1.Create())
        {
            passwordSaltBytes = saltStretcher.ComputeHash(passwordSaltBytes);
        }
    }

    using (var pbkdf2 = new System.Security.Cryptography.Rfc2898DeriveBytes(password, passwordSaltBytes, 10000))
    {
        return Convert.ToBase64String(pbkdf2.GetBytes(20));
    }
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.