Asp.net MVC - How to hash password

2019-02-10 19:42发布

How do I hash an users input(password) to database and then later read the hashed password during login?

I believe the solution is to hash the password upon register, where the password is saved as hashed inside db. Later upon Login, it should un-hash and compare its password with users password-input. But I don't know how to do it.

I allowed password to have nvarchar(MAX)in db since hashed password are usually long.

        [Required]
        [StringLength(MAX, MinimumLength = 3, ErrorMessage = "min 3, max 50 letters")]
        public string Password { get; set; }

Register:

        [HttpPost]
        public ActionResult Register(User user) {
            if (ModelState.IsValid) {

                        var u = new User {
                            UserName = user.UserName,                               
                            Password = user.Password
                        };

                        db.Users.Add(u);
                        db.SaveChanges();

                    return RedirectToAction("Login");
                }
            }return View();    
        }

Login:

  public ActionResult Login() {
        return View();
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Login(User u) {
        if (ModelState.IsValid) 
        {
            using (UserEntities db = new UserEntities()) {

                //un-hash password?

                var v = db.Users.Where(a => a.UserName.Equals(u.UserName) && a.Password.Equals(u.Password)).FirstOrDefault();
                if (v != null) {

                    return RedirectToAction("Index", "Home"); //after login
                }
            }
        }return View(u);
    }

I'm using database first.

2条回答
做自己的国王
2楼-- · 2019-02-10 20:08

You should never need to unhash a password. A cryptographic hash function is supposed to be a one-way operation.

(And that's precisely why it is called hashing and not encrypting. If unhashing passwords was to be a normal procedure in your flow of operations, then it would not be hashing and unhashing, it would be encrypting and decrypting. So, hashing is a different thing from encryption, precisely because unhashing is not supposed to ever happen.)

Hashing provides security, because nobody can steal your user's passwords even if they manage to view the contents of your database.

  • When the user registers, compute the hash of their password, store the hash in the database, and forget the password forever.

  • When the user logs in, compute the hash of the password they entered, (forget that password too,) and see if the hash matches the hash stored in the database.

This is the mechanism used by most websites out there, and that's precisely why if you successfully go through the "I forgot my password" procedure, they will still not show you your password: they don't have it; they cannot retrieve it even if they wanted to. Instead, they send you a password reset link.

As for how to compute a hash from a string, the interwebz abound with answers to that question, for example: MD5 (MSDN); SHA-256 (MSDN); SHA-512 (MSDN)

查看更多
地球回转人心会变
3楼-- · 2019-02-10 20:16

When it comes to security don't try to reinvent the wheel. Use Claims based authentication.

If you still must manage usernames and passwords use Hash-based message authentication code (HMAC)

I would also recommend investing sometime and reading Enterprise Security Best Practices. There are already smarter people who solved this problems why reinvent the wheel. And .NET has all the goodies there.

Example below:

using System.Security.Cryptography;
using System.Text;

//--------------------MyHmac.cs-------------------
public static class MyHmac
{
    private const int SaltSize = 32;

    public static byte[] GenerateSalt()
    {
        using (var rng = new RNGCryptoServiceProvider())
        {
            var randomNumber = new byte[SaltSize];

            rng.GetBytes(randomNumber);

            return randomNumber;

        }
    }

    public static byte[] ComputeHMAC_SHA256(byte[] data, byte[] salt)
    {
        using (var hmac = new HMACSHA256(salt))
        {
            return hmac.ComputeHash(data);
        }
    }
}



//-------------------Program.cs---------------------------
string orgMsg = "Original Message";
        string otherMsg = "Other Message";


        Console.WriteLine("HMAC SHA256 Demo in .NET");

        Console.WriteLine("----------------------");
        Console.WriteLine();

        var salt = MyHmac.GenerateSalt();

        var hmac1 = MyHmac.ComputeHMAC_SHA256(Encoding.UTF8.GetBytes(orgMsg), salt);
        var hmac2 = MyHmac.ComputeHMAC_SHA256(Encoding.UTF8.GetBytes(otherMsg), salt);


        Console.WriteLine("Original Message Hash:{0}", Convert.ToBase64String(hmac1));
        Console.WriteLine("Other Message Hash:{0}", Convert.ToBase64String(hmac2));

NOTE: Salts do not have to be kept secret and can be stored alongside the hash itself. It's to increase security from rainbow table attack. Please don't post same question twice. Duplicate from here.

查看更多
登录 后发表回答