3

so I have some models being displayed in a default view. I am trying to figure out if I want to hash the password with Crypto.HashPassword() method. Do I do this in the controller or the model or where? I did research on how to do it, but I am just finding different method and not where the action takes place. Beginner to MVC and asp.net, so any point in the right direction would be major help. Thank you in advance.

1
  • 1
    I'd use Rfc2898DeriveBytes to implement an API similar to the Crypto class, but with a higher iteration count. Commented Feb 13, 2014 at 11:15

3 Answers 3

3

You generally will want to perform the hash operation in the controller, and store the hash result value in the model.

Taking for example a simple user login to your website:

  • When the user account is first created, you'll call Crypto.HashPassword(pwd) to calculate the hash value of the password the user has set. You can do this in the controller, inside the action where the user registers a new account.
  • The resulting hash value needs to be stored in the Model (e.g. in the DB) so that you can retrieve it later.
  • When the same user tries to login next time, you'll need to call Crypto.VerifyHashedPassword(storedHash, submittedPwd). Crypto class hashes the submitted pwd with the same IV and Salt, and returns True if they match (pwd is correct), or False if they don't (pwd is wrong).

If you are new to MVC and ASP.Net, you may want to look at ASP.Net Forms Authentication (such as this page on MSDN), which you can use for authenticating users without having to roll your own custom solution.

Sign up to request clarification or add additional context in comments.

2 Comments

"When the same user tries to login next time, you'll need to again call Crypto.HashPassword(pwd) on the submitted password. Then compare the resulting hash value to the value stored in the Model" That doesn't work because HashPassword is not deterministic. You need to use Crypto.VerifyHashedPassword.
Thanks @CodesInChaos, you are right. I edited my response to reflect this. I also agree with your other answer, that using Rfc2898DeriveBytes is better, and I use it myself (so in my own app I actually do have to call the same hashing method w/ stored salt and compare new results to stored hash).
2

I'd define the user class like this:

public class User
{
    private string PasswordHash {get; set;} //assuming your db supports serializing private properties. If not increase visibility as necessary.

    public void SetPassword(string newPassword)
    {
        PasswordHash = PasswordHasher.CreateHash(newPassword);
    }

    public bool VerifyPassword(string passwordCandidate)
    {
        return PasswordHasher.Verify(PasswordHash, passwordCandidate);
    }
}

I would not have a User.Password property, since you never store it, and there is no simple mapping between passwords and hashes.

The PasswordHash property should only be accessed by the database serializer and through these two functions. The controller should fetch the user and then call these methods to verify/change the password.


I also recommend using a custom hasher with similar API to the Crypto class. Crypto has a hardcoded iteration count with a rather small value.

Comments

0

There could be many ways of doing it..

I ideally I would mark the password property with a custom attribute name [Encrypt(true)]. So then when the property is saving to the database, you got to track the models property that marked by Encrypt attribute separately (inside DbContext Saving event). Then you could encrypt that and save it to the database inside the said saving event.

A custom attribute and a generic solution like this could come handy when you want to encrypt any other sensitive data that you want to save in to your database later too.

5 Comments

So I would add the [Encrypt(true)] above the public String Password { get; set; } in my User model. And then I would make another class for Encrypt and write the hashing method there?
Yes that is what I would do.. But please don't misunderstand.. inside the custom attribute you cannot write the encryption but it has to be separately done inside the context saving event. so that you have a one generic solution to encrypt data in your application..
I think I am doing something wrong. I put [Encrypt] above the public string password. Next I made the excrypt class, and filled it with class EncryptAttribute : Attribute { public string hashPassword(string Password) { string Passhash = Crypto.Hash(Password); return Passhash; } } } and it does not effect it when it gets stored in the database?
But there is no Decrypt operation. So how would you verify the a password with such a class? Password hashing APIs have two distinct operations to create and verify a hash. Creating a hash isn't deterministic, since it needs to generate a new salt.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.