Password hashing using HMACSHA512 in asp.net application


πŸ‘€Β Diwas Poudel Β Β  πŸ•’ 31 May 2023 Β Β  πŸ“ TECH

Storing passwords 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 them use the best approach for storing password :

Hashing

Hashing a password is the best approach to storing passwords. 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 User Page

Here, I have registered user "Diwas Poudel"

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

Created User : You can see in Postgresql
fig. Created User successfully in Postgresql

Let's log in to the same user

4) Let's create Login Action Method in Account Controller.

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>  
Simple Login Form
fig. Simple Login Form

Let's just visualize it :

A hash of "a" using HMAC SHA 512 produces:

239254CD9E54392DDE39BC8F975F2498

CF709CAA598CE3762BE282D860DBEA5D

8034EEE86F19BBDF3EFDAB22C6BE610A

8908FAF2800AF46243364135E9BB206E

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

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

3F1E17B76F871F6DDEE681BC90C5F753

961D3B45B7CC717A62B39CBE3186206E

298BFA22B37A8CF67767737845992D7C

496DB5F985F8B255309D4DC9BC2A5EFA

In both outputs is of Β 128-digit hexadecimal number.

Β 

Β 

Β 

Β 

Β