3

I managed to get hash working, but the salt-part is still an issue.. I've been searching and testing examples without success. This is my code with hash:

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

Hash password function(without salt):

 public string HashPass(string password) { 

       byte[] encodedPassword = new UTF8Encoding().GetBytes(password);
       byte[] hash = ((HashAlgorithm) CryptoConfig.CreateFromName("MD5")).ComputeHash(encodedPassword);
       string encoded = BitConverter.ToString(hash).Replace("-", string.Empty).ToLower();

          return encoded;//returns hashed version of password
      }

Register:

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

                        var u = new User {
                            UserName = user.UserName,                               
                            Password = HashPass(user.Password)//calling hash-method
                        };

                        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()) {

                    string readHash = HashPass(u.Password);

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

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

So far hash work.. But how do I make salt work here?

I would prefer a demonstrate on my code as I find it very hard to understand by words.

I'm using database first.

Ezony
  • 141
  • 1
  • 3
  • 9
  • There is a good example available [HERE](http://www.obviex.com/samples/hash.aspx) – mmushtaq Oct 01 '16 at 04:05
  • [Salted Password Hashing - Doing it Right](https://crackstation.net/hashing-security.htm) –  Oct 01 '16 at 04:18
  • This message has been already answered [here.](http://stackoverflow.com/questions/2138429/hash-and-salt-passwords-in-c-sharp) – Farukh Oct 01 '16 at 04:50
  • Just using a hash function is not sufficient and just adding a salt does little to improve the security. Instead iIterate over an HMAC with a random salt for about a 100ms duration and save the salt with the hash. Use functions such as `PBKDF2`, `password_hash`, `Bcrypt` and similar functions. The point is to make the attacker spend a lot of time finding passwords by brute force with a popular password list. – zaph Oct 01 '16 at 12:05

2 Answers2

4

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:

//--------------------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(hmac1));

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.

Farukh
  • 2,173
  • 2
  • 23
  • 38
  • Are you saying that using salt isn't significantly meaningful when using claims based security? The thing you mentioned about not reinventing the wheel sounds like that. Please elaborate? – Konrad Viltersten Dec 10 '19 at 01:57
  • I am saying use existing libraries like Identity Server or other .NET solutions. Don't implement your own. – Farukh Dec 11 '19 at 03:40
1

Use the System.Web.Helpers.Crypto NuGet package from Microsoft. It takes care of the salt for you.

You hash a password like this: var hash = Crypto.HashPassword("foo");

You verify a password like this: var verified = Crypto.VerifyHashedPassword(hash, "foo");

Kai Hartmann
  • 3,106
  • 1
  • 31
  • 45
  • Are you saying that salting doesn't need to be handled manually at all in any way when using the helpers mentioned in your answer? – Konrad Viltersten Dec 10 '19 at 02:02
  • That should be correct. See the discussion here: https://stackoverflow.com/questions/17693918/system-web-helpers-crypto-wheres-the-salt – Kai Hartmann Dec 10 '19 at 07:50
  • It's been a few years since that question's been asked and I wonder which of the helpers that are supposedly the best choice for modern .NET Core environments (i.e. 2.x at least, preferably 3.x). I've found [this thing](https://www.nuget.org/packages/System-Web-Helpers.dll/) and [that thing](https://www.nuget.org/packages/Microsoft.AspNet.WebHelpers/). Both seem not to be maintained anymore, though. Which version and what NuGet are you using currently? – Konrad Viltersten Dec 29 '19 at 17:10
  • I see that [MSDN](https://learn.microsoft.com/en-us/aspnet/core/security/data-protection/consumer-apis/password-hashing?view=aspnetcore-3.1) provides a how-to on hashing a password but that's nowhere near the *Crypto* class, most seems to be manually managed, in contrary to your statement. It makes me fear that I'm barking up the wrong tree. Please advise. – Konrad Viltersten Dec 29 '19 at 17:14
  • We're using the latter (Version 3.2.7), but we're not using .NET Core. – Kai Hartmann Jan 06 '20 at 07:27
  • @KonradViltersten There seems to be a .NET Core compatible alternative now. But I haven't used it, yet. https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.identity.passwordhasher-1?view=aspnetcore-6.0 – Kai Hartmann Aug 12 '22 at 14:16