0% found this document useful (0 votes)
66 views7 pages

Part - 1 - How - To - Store - Password - in - Hash - Format - in - ASP - NET - Core - Web

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
66 views7 pages

Part - 1 - How - To - Store - Password - in - Hash - Format - in - ASP - NET - Core - Web

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 7

How to Store Password in Hash Format in ASP.

NET Core Web API


Now, I will discuss How to Store Password in Hash Format in ASP.NET Core Web API Application.
Here, I will show you the different Cryptographic algorithms to store the Password hash in the
database using Entity Framework Core.

What is Password in Hash Format?


A Password in Hash Format refers to the output produced by applying a cryptographic hash function
(HMACSHA256, or HMACSHA512) to a password. Cryptographic hash functions are designed to
take an input (or 'message') and return a fixed-size string of bytes. The output, known as the hash, is
typically a string of hexadecimal characters that appears random.

The following are the key characteristics of hashed passwords:


 The same password will always produce the same hash when the same hash function and
same salt (if used) are applied.
 Regardless of the length of the original input (password), the hash output will have a fixed
length, which depends on the hash function used (e.g., SHA-256 always produces a 256-bit
hash).
 Even a small change in the password will result in a completely different hash, which makes
hashes useful for ensuring data integrity.

Example to Understand Password in Hash Format in ASP.NET Core Web API:


Let us see an example to understand how to Store and use password in Hash Format in ASP.NET
Core Web API Application. I will show you the use of SHA256 and SHA512 hashing algorithm and
then I will show you the differences between these two cryptographic hashing algorithms and when to
use which one in real-time application.

Creating a New ASP.NET Core Web API Project:


First, create a new ASP.NET Core Web API Project named PasswordHashingDemo. We are going to
use SQL Server as the database where we will store the password in Hash format and Entity
Framework Core as the Data access technology. So, please install the following two packages either
using Package Manager Console or using NuGet Package Manager for solution.
 Microsoft.EntityFrameworkCore.SqlServer
 Microsoft.EntityFrameworkCore.Tools

Define User Model


First, create a folder named Models at the Project root directory where we will create all our Models
and DTOs. We need to create a user model with properties for Id, Username, and PasswordHash. So,
create a class file named User.cs within the Models folder and then copy and paste the following
code:
namespace PasswordHashingDemo.Models
{
public class User
{
public int Id { get; set; }
public string Username { get; set; }
public byte[] PasswordHash { get; set; }
public byte[] PasswordSalt { get; set; }
}
}

Define UserDTO
Next, create another class file named UserDTO.cs within the Models folder and then copy and paste
the following code. This will be our Data Transfer Object which include the required properties which
are required for user Registration and Login functionalities. The action method of our controller will
use this model to get the data from the client.
namespace PasswordHashingDemo.Models
{
public class UserDTO
{
public string UserName { get; set; }
public string Password { get; set; }
}
}

Configure the Database Connection


Instead of hard coding the connection string with the DbContext class, we will store the connection
string in appsettings.json file. So, add the database connection string within the appsettings.json file
as follows:
{
"ConnectionStrings": {
"EFCoreDBConnection": "Server=LAPTOP-6P5NK25R\\
SQLSERVER2022DEV;Database=UserDB;Trusted_Connection=True;TrustServerCertificate=Tr
ue;"
}
}

Create Db Context:
Define a context class that inherits from DbContext. So, add a class file named UserDbContext.cs
within the Models folder and then copy and paste the following code. Here, you can see we are using
DbSet<User> as a property for which the entity framework is going to create a database table named
Users which will mapped to the User entity.
using Microsoft.EntityFrameworkCore;
namespace PasswordHashingDemo.Models
{
public class UserDbContext : DbContext
{
public UserDbContext(DbContextOptions<UserDbContext> options) : base(options) { }

public DbSet<User> Users { get; set; }


}
}

Registering the Connection String and DbContext Class:


Next, we need to configure the connection string and register the context class in Program class. So,
modify the Program class as follows. Here, also we telling the Framework to use the property names
as defined in the C# model classes.
using PasswordHashingDemo.Models;
using Microsoft.EntityFrameworkCore;
namespace PasswordHashingDemo
{
public class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers()
.AddJsonOptions(options =>
{
// This will use the property names as defined in the C# model
options.JsonSerializerOptions.PropertyNamingPolicy = null;
});

// Learn more about configuring Swagger/OpenAPI at


https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
//Configure the ConnectionString and DbContext class
builder.Services.AddDbContext<UserDbContext>(options =>
{

options.UseSqlServer(builder.Configuration.GetConnectionString("EFCoreDBConnection"));
});

var app = builder.Build();

// Configure the HTTP request pipeline.


if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();
}
}
}

Database Migration
Next, we need to generate the Migration and update the database schema. So, open Package
Manager Console and Execute the add-migration and update-database commands as follows. You
can give any name to your migration. Here, I am giving Mig1. The name that you are giving it should
not be given earlier.

With this our Database with Users database table is created as shown in the below image:
Implement Password Hashing
For hashing passwords, we can use either HMACSHA256 or HMACSHA512 algorithms. We will
create a utility class to handle password hashing. So, create a class file named PasswordHasher.cs
and then copy and paste the following code:
namespace PasswordHashingDemo.Models
{
public static class PasswordHasher
{
public static void CreatePasswordHash(string password, out byte[] passwordHash, out
byte[] passwordSalt)
{
//var hmac = new System.Security.Cryptography.HMACSHA256()
using (var hmac = new System.Security.Cryptography.HMACSHA512())
{
passwordSalt = hmac.Key; // The Key property provides a randomly generated salt.
passwordHash =
hmac.ComputeHash(System.Text.Encoding.UTF8.GetBytes(password));
}
}

public static bool VerifyPasswordHash(string password, byte[] storedHash, byte[]


storedSalt)
{
//var hmac = new System.Security.Cryptography.HMACSHA256(storedSalt)
using (var hmac = new System.Security.Cryptography.HMACSHA512(storedSalt))
{
var computedHash =
hmac.ComputeHash(System.Text.Encoding.UTF8.GetBytes(password));
return computedHash.SequenceEqual(storedHash);
}
}
}
}
The above class contains two static methods related to password security: CreatePasswordHash and
VerifyPasswordHash. These methods are designed to securely store passwords and verify them
using hash-based message authentication code (HMAC) with the SHA-156 or SHA-512 hashing
algorithms.

CreatePasswordHash
This method is used to create a hash and a salt for a given password. This method takes the following
three parameters:
 string password: The plain text password input by the user.
 out byte[] passwordHash: An output parameter to store the computed hash of the
password.
 out byte[] passwordSalt: An output parameter to store the salt used during the hashing
process.

How it works:
 Initialization of HMACSHA512: An instance of HMACSHA512 is created. This class is
automatically provided with a randomly generated key (used as salt) when instantiated.
 Storing the Salt: The randomly generated key (salt) is stored in the passwordSalt output
parameter.
 Computing the Hash: The password is converted into bytes using UTF-8 encoding standard,
and then it is hashed using the HMACSHA512 instance. The resulting hash is stored in the
passwordHash output parameter.

VerifyPasswordHash
This method is used to verify a password against a stored hash and salt. This method takes the
following three parameters:
 string password: The plain text password to verify.
 byte[] storedHash: The hash stored in the database (or another secure storage) that was
previously computed from the password.
 byte[] storedSalt: The salt stored along with the hash used during the initial hashing
process.

How it Works:
 Initialization of HMACSHA512: An instance of HMACSHA512 is created using the
storedSalt. The salt helps in recreating the same hash from the input password if it is the
same as the original.
 Computing the Hash: The password is again converted into bytes using UTF-8 encoding
and hashed with the initialized HMACSHA512 instance.
 Comparison: The newly computed hash (computedHash) is compared byte-by-byte with the
storedHash using the SequenceEqual method from Linq, which ensures that both sequences
are identical.
 Return Value: The method returns true if the password matches the original (i.e., if
computedHash equals storedHash); otherwise, it returns false.

Integrating Password Hashing in API


Now, we can use PasswordHasher to hash passwords before storing them. So, create an Empty API
Controller named UserController within the Controllers folder and then copy and paste the following
code:
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using PasswordHashingDemo.Models;

namespace PasswordHashingDemo.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class UserController : ControllerBase
{
private readonly UserDbContext _context;

public UserController(UserDbContext context)


{
_context = context;
}

[HttpPost("register")]
public async Task<ActionResult<User>> Register(UserDTO model)
{
byte[] passwordHash, passwordSalt;
PasswordHasher.CreatePasswordHash(model.Password, out passwordHash, out
passwordSalt);

User user = new User


{
Username = model.UserName,
PasswordHash = passwordHash,
PasswordSalt = passwordSalt
};

await _context.Users.AddAsync(user);
await _context.SaveChangesAsync();

//For Demo Purpose we are returning the PasswordHash and PasswordSalt


return Ok(user);
}

[HttpPost("login")]
public async Task<ActionResult<string>> Login(UserDTO model)
{
var user = await _context.Users.FirstOrDefaultAsync(x => x.Username ==
model.UserName);
if (user == null || !PasswordHasher.VerifyPasswordHash(model.Password,
user.PasswordHash, user.PasswordSalt))
{
return Unauthorized("Invalid username or password.");
}

// Generate a token or return a success response


return Ok("User logged in successfully");
}
}
}

As you can see the above Registration action method, it uses the Password Hasher utility to generate
the Password hash and salt and then store the same in the database. In this case, if two users trying
to send the same password, then it is going to create two different password hash. This is possible
because of the dynamic generated salt. On the other hand, the Login action method also uses the
Password Hasher utility to generate and compare the password.

With the above changes in place, run the application and test the functionalities and it should work as
expected. For both the action method, you can use the same request body. For example:
{
"UserName": "Pranaya",
"Password": "Test@1234"
}

Now, create a few users and then verify the database. You can see for each user; it is creating a
different password hash and salt as shown in the below image:

Why do we need to store the password in a hash format in a database?


Storing Passwords in hash format in a database is essential for security reasons. The following are
the main reasons why this is recommended in Real-time applications:
 Security Against Data Breaches: If a database is compromised, hashed passwords do not
reveal the actual passwords. Hashing algorithms transform the original passwords into a
fixed-size string of characters. This means that even if an attacker gains access to the hashed
passwords, they cannot easily figure out the original passwords.
 Prevention of Password Reuse Attacks: Since hashing produces a unique output for each
unique input, identical passwords will result in identical hash values. However, with the
addition of salt (a random value added to the password before hashing), even identical
passwords will result in different hash values, thus enhancing security and preventing
attackers from using pre-computed tables to reverse the hashes.
 Ensuring Data Integrity and Authentication: Hash functions are designed to be sensitive to
changes in the input data. Even a small change in the input (e.g., changing one character in
the password) results in a significantly different hash. This property helps in verifying the
integrity of the data without exposing the actual password.
 Compliance with Data Protection Regulations: Many data protection standards and
regulations require that personal data, particularly passwords, be stored securely. Hashing
passwords is considered a best practice in complying with these standards, thereby avoiding
legal and reputational risks associated with data breaches.

What are the Differences Between HMACSHA256 and HMACSHA512?


In ASP.NET Core Web API, HMACSHA256 and HMACSHA512 are two of the cryptographic hash
functions available for securing data. Both are part of the System.Security.Cryptography
namespace in .NET. Let us first look at each of these Hash functions and then we will see the
differences between them:

HMACSHA256 in ASP.NET Core:


 Hash Size: Generates a hash that is 256 bits (32 bytes) long.
 Security: Provides good security and is widely adopted.
 Performance: Faster than HMACSHA512 due to its smaller hash size, which can be
advantageous in scenarios where performance and lower computational overhead are
priorities.

HMACSHA512 in ASP.NET Core:


 Hash Size: Generates a hash that is 512 bits (64 bytes) long.
 Security: Offers a higher level of security compared to HMACSHA256 because of its larger
hash size.
 Performance: Generally slower than HMACSHA256 because it deals with larger blocks of
data and produces a larger hash. However, on systems with 64-bit processors, the
performance difference may be less noticeable.

Choosing Between HMACSHA256 and HMACSHA512


 Security Needs: If you require higher security and are less concerned about performance,
HMACSHA512 might be the better choice. For general purposes, HMACSHA256 provides a
balanced approach.
 Performance Considerations: In performance-sensitive applications, the quicker
computation of HMACSHA256 might be more suitable.
 Compliance Requirements: Some regulations or industry standards might specify the use of
a particular hash function size.

You might also like