Password hashing using HMACSHA512 in asp.net application


👤 Diwas Poudel    🕒 Jul 8 2019    📁 Fix    📜 0 comment

Storing password in plain text in a database is very dangerous because anyone who looked through the database would be able to just read the passwords and if your password may be compromised so your application can be at risk. So, it is better to hash the password and store hashed form password in a database so that if your hashed password is compromised, then they don't expose your password. So, a password is a critical part of any web application.

Prevention is better than cure, so the correct precautions are better before your data become exposed. So, we the developer is responsible to take the right precautions!

So, without wasting time, lets the use of the best approach for storing password :

Hashing

Hashing a password is the best approach of storing password. Hashing is the practice of using an algorithm to map data of any size to a fixed length. There are many hashing functions like Hash functions like SHA256, SHA512, RipeMD, and whirlpool, HMAC256, HMAC512 etc.

Implementation

Let’s take a common hashing algorithm SHA-512 and apply HMAC in C#.

1)Create Model as :  UserForRegisterDTO.cs


  public class UserForRegisterDTO
	{
		[Required]
		public string Username { get; set; }
		public string Password { get; set; }
		public int id { get; set; }
		public byte[] PasswordHash { get; set; }
		public byte[] PasswordSalt { get; set; }
	}
  

2) Creating Register Action inside AccountController


  [AllowAnonymous]
  public ActionResult Register()
  {
    return View();
  }

  [HttpPost]
  [AllowAnonymous]
  [ValidateAntiForgeryToken]
  public ActionResult Register(UserForRegisterDTO model)
  {
      User user = new User();
      byte[] passwordHash, passwordSalt;
      CreatePasswordHash(model.Password,out passwordHash,out passwordSalt);
      user.passwordsalt = passwordSalt;
      user.passwordhash = passwordHash;
      user.username = model.Username;
      db.SaveChanges();
      return View(model);
  }

  [NonAction]
  private void CreatePasswordHash(string password, out byte[] passwordHash, out byte[] passwordSalt)
  {
      using (var hmac = new System.Security.Cryptography.HMACSHA512())
      {
        passwordSalt = hmac.Key;
        passwordHash = hmac.ComputeHash(System.Text.Encoding.UTF8.GetBytes(password));
      }
  }

3)View of Register Action : register.cshtml

  @{
    ViewBag.Title = "Register";
  }
  <div class="row">
  <div class="col-lg-4" >
    <h3>Register</h3>
      <form role="form" action="/account/register" method="post">
        @Html.AntiForgeryToken()
          <div class="form-group">
           <input type="text" class="form-control" placeholder="Username" name="Username" required="">
          </div>
  
        <div class="form-group">
          <input type="password" class="form-control" placeholder="Password" name="Password" required="">
        </div>
      <button type="submit" class="btn btn-primary block full-width m-b">Register</button>
    </form>
  </div> 
</div>

register image

Here , I have register user "Diwas Poudel"

User "Diwas Poudel registered successfully. Let's look at postgresql. 

user created at postgresql database

Lets login same user

4) In AccountController :Creating Login Action Method 

  public ActionResult Login(UserForLoginDTO user)
 {
    var data = db.User.FirstOrDefault(x =>x.username == user.UserName);
    if(data == null)
    {
      return View(user);
    }

    if (!VerifyPasswordHash(user.Password, data.passwordhash, data.passwordsalt))
      return View(user);
    else {
      return Redirect("/home")
      }
  }


 [NonAction]
 private bool VerifyPasswordHash(string password, byte[] passwordHash, byte[] passwordSalt)
 {
   using(var hmac = new System.Security.Cryptography.HMACSHA512(passwordSalt))
   {
      var computedHash = hmac.ComputeHash(System.Text.Encoding.UTF8.GetBytes(password));

      for (int i = 0; i < computedHash.Length; i++)
      {
        if (computedHash[i] != passwordHash[i]) return false;
      }
        return true;
    }
  }

5) View of Login as Login.cshtml

  @{
    ViewBag.Title = "Login";
  }


	<div>

  <div><h2>Simple Login Form</h2></div>

    <form  method="post" action="/Account/Login">
			@Html.AntiForgeryToken()
    <div style="padding-left:8px;padding-right:8px">
      <div class="form-group">
        <input type="text" class="form-control" placeholder="Username" name="UserName" required="">
      </div>
		<div class="form-group">
      <input type="password" class="form-control" placeholder="Password" name="Password" required="">
		</div>
      <button type="submit" class="btn btn-primary">Login</button>
    </div>
	</form>
</div>  

login image

 

Lets just visualize it :

Hash  of "a" using HMAC SHA 512 produces:

239254CD9E54392DDE39BC8F975F2498

CF709CAA598CE3762BE282D860DBEA5D

8034EEE86F19BBDF3EFDAB22C6BE610A

8908FAF2800AF46243364135E9BB206E

==================================================================

Hash of "www.ourtechroom.com" using HMAC SHA 512 produces:

3F1E17B76F871F6DDEE681BC90C5F753

961D3B45B7CC717A62B39CBE3186206E

298BFA22B37A8CF67767737845992D7C

496DB5F985F8B255309D4DC9BC2A5EFA

In both output is of  128-digit hexadecimal number.