3

I am trying to prevent the user from using any of their last 5 passwords. I am using the exact template from Visual Studio 2015 that gives you a basic Identity user system with it.

I have went ahead to add the following columns to my user database, passwordLastChanged(Date) and 5 columns named previousPassword1 (through 5) respectively.

I need to retreive the current user password from the database using something along the lines of User.Identity.GetUserPassword and I also need something along the lines of model.NewPassword.Encrypt (those don't exist!). Are there methods that do these actions that I am just not seeing in the api?

And I also have to encrypt my new data to see if it matches, how can I encrypt a string the same way that my user password is encrypted?

//
// POST: /Manage/ChangePassword
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> ChangePassword(ChangePasswordViewModel model)
{
    if (!ModelState.IsValid)
    {
        return View(model);
    }
    var result = await UserManager.ChangePasswordAsync(User.Identity.GetUserId(), model.OldPassword, model.NewPassword);
    if (result.Succeeded)
    {
        var user = await UserManager.FindByIdAsync(User.Identity.GetUserId());
        if (user != null)
        {
            await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);
        }
        return RedirectToAction("Index", new { Message = ManageMessageId.ChangePasswordSuccess });
    }
    AddErrors(result);
    return View(model);
}
Travis
  • 45
  • 1
  • 7
  • 1
    Passwords stored using the standard ASP.Net authentication model are Hashed, not encrypted. Hashing is one way so you cannot get the password back – Liam Oct 24 '16 at 12:36
  • Have a read though [How do one-way hash functions work?](http://stackoverflow.com/questions/2112685/how-do-one-way-hash-functions-work). You could hash all your passwords and then test against the hash to see if the password has already been used. Which hashing method depends on how you've configured your system – Liam Oct 24 '16 at 12:38
  • Yes I have, Thats what I was thinking. But is there an already built hash method built that I can simply call? I didn't actually set up any hashing, it is the built in that ChangePasswordAsync is calling – Travis Oct 24 '16 at 12:39
  • Yes there will be, but which one depends on which alogorithm the standard auth uses. [There are several possibilities](http://stackoverflow.com/questions/800685/which-cryptographic-hash-function-should-i-choose) not to [mention salts](http://security.stackexchange.com/questions/51959/why-are-salted-hashes-more-secure-for-password-storage) – Liam Oct 24 '16 at 12:41
  • I wonder If I can just call a function or if I will have to implement the actual hashing algorithm that uses the same salt and what not? – Travis Oct 24 '16 at 12:42

1 Answers1

1

Ok going to turn my comments into some kind of answer. So as mentioned passwords are stored in the table Hashed not encrypted. So by definition they can't be retrived (easily).

There's nothing to stop you putting the hashed passwords into the table though to keep a records of previous passwords. Then when a user enters a password you hash it and check if it's already been used, exactly the same as if it wasn't hashed but using the hash not the raw password (this keeps everything nice and secure too).

I wonder If I can just call a function or if I will have to implement the actual hashing algorithm that uses the same salt and what not?

UserManager implements a PasswordHasher. So to get a password hashed in the same fashion as the default hash should be as simple as:

PasswordVerificationResult passwordMatch = UserManager.PasswordHasher.VerifyHashedPassword(previousPassword1, rawPassword);

I don't use this auth method so the above is untested and based on the MSDN docs only. Should be fine but let me know if it doesn't work.

If the passwords match then passwordMatch == PasswordVerificationResult.Success. You may also need to allow for PasswordVerificationResult.SuccessRehashNeeded

Community
  • 1
  • 1
Liam
  • 27,717
  • 28
  • 128
  • 190
  • 3
    You'll need `VerifyHashedPassword` rather than `HashPassword` to compare the raw (new) password with an old hash. `HashPassword` can create a new salt ensuring the new hash would never match the old hash. – Chris Chilvers Oct 24 '16 at 14:47
  • cheers @ChrisChilvers. I haven't used these methods for a very long time, so I'm a little rusty – Liam Oct 24 '16 at 14:51