Store Passwords Securely in Database Using SHA256 - ASP .NET Core - by Juldhais Hengkyawan - Medium
Store Passwords Securely in Database Using SHA256 - ASP .NET Core - by Juldhais Hengkyawan - Medium
Get unlimited access to all of Medium for less than $1/week. Become a member
226 2
https://juldhais.net/secure-way-to-store-passwords-in-database-using-sha256-asp-net-core-898128d1c4ef 1/31
8/22/23, 2:55 PM Store Passwords Securely in Database using SHA256 — ASP .NET Core | by Juldhais Hengkyawan | Medium
Plain-Text
https://juldhais.net/secure-way-to-store-passwords-in-database-using-sha256-asp-net-core-898128d1c4ef 2/31
8/22/23, 2:55 PM Store Passwords Securely in Database using SHA256 — ASP .NET Core | by Juldhais Hengkyawan | Medium
Storing passwords in the plain-text is the worst thing we can do. If someone
has access to the database, that person can immediately find out the
password of each registered user.
Plain-Text Password
Unfortunately, there are still many programmers who do this. I’ve come
across applications that store passwords in plain-text form many times, both
private and government-made applications.
It turns out that the application that I made ten years ago saves passwords in
plain-text form, with the combo “admin admin” as username and password
as well 😆
https://juldhais.net/secure-way-to-store-passwords-in-database-using-sha256-asp-net-core-898128d1c4ef 3/31
8/22/23, 2:55 PM Store Passwords Securely in Database using SHA256 — ASP .NET Core | by Juldhais Hengkyawan | Medium
Encrypted
https://juldhais.net/secure-way-to-store-passwords-in-database-using-sha256-asp-net-core-898128d1c4ef 4/31
8/22/23, 2:55 PM Store Passwords Securely in Database using SHA256 — ASP .NET Core | by Juldhais Hengkyawan | Medium
There are two types of encryption used: reversible encryption and non-
reversible encryption.
The downside of reversible encryption is that if the attacker can guess the
encryption logic, they can easily retrieve the actual passwords.
Encrypted Password
https://juldhais.net/secure-way-to-store-passwords-in-database-using-sha256-asp-net-core-898128d1c4ef 5/31
8/22/23, 2:55 PM Store Passwords Securely in Database using SHA256 — ASP .NET Core | by Juldhais Hengkyawan | Medium
In the table above, the saved passwords have been encrypted. It is very
difficult for ordinary people to know the value of an encrypted password.
However, if we pay attention, admin and budi have the same
PasswordEncrypted value. If one of them is leaked, we can assume all users
who have the same password are also leaked.
Hash Function
Using a hash function to store passwords in the database is the most
common. Hashes are non-reversible encryption; even if someone has access
to the database and knows the hash algorithm used, they cannot decrypt the
hash of the password. The commonly used hash algorithms are SHA256 and
SHA512.
https://juldhais.net/secure-way-to-store-passwords-in-database-using-sha256-asp-net-core-898128d1c4ef 6/31
8/22/23, 2:55 PM Store Passwords Securely in Database using SHA256 — ASP .NET Core | by Juldhais Hengkyawan | Medium
Hashed Password
Similar to the encrypted password, admin and budi have the same hash
value. And if we google the hashed password, the result is:
https://juldhais.net/secure-way-to-store-passwords-in-database-using-sha256-asp-net-core-898128d1c4ef 7/31
8/22/23, 2:55 PM Store Passwords Securely in Database using SHA256 — ASP .NET Core | by Juldhais Hengkyawan | Medium
Salt is a “condiment” added to the hashing process so that the hash value is
different even though the original password is the same. Salt is a random
value that is unique to each user. Salt can be stored in the database without
needing to be encrypted. Adding salt to the hashing process will make it
impossible to obtain the hash via search engines or a hash decryptor
application. The value of the salt must be changed every time there is a
change in user data, for example, a change in password or email.
https://juldhais.net/secure-way-to-store-passwords-in-database-using-sha256-asp-net-core-898128d1c4ef 8/31
8/22/23, 2:55 PM Store Passwords Securely in Database using SHA256 — ASP .NET Core | by Juldhais Hengkyawan | Medium
Using salt and pepper, even if admin and budi have the same password, the
password hash generated will be different.
https://juldhais.net/secure-way-to-store-passwords-in-database-using-sha256-asp-net-core-898128d1c4ef 9/31
8/22/23, 2:55 PM Store Passwords Securely in Database using SHA256 — ASP .NET Core | by Juldhais Hengkyawan | Medium
https://juldhais.net/secure-way-to-store-passwords-in-database-using-sha256-asp-net-core-898128d1c4ef 10/31
8/22/23, 2:55 PM Store Passwords Securely in Database using SHA256 — ASP .NET Core | by Juldhais Hengkyawan | Medium
Entities
Add the User class to the Entities folder:
https://juldhais.net/secure-way-to-store-passwords-in-database-using-sha256-asp-net-core-898128d1c4ef 11/31
8/22/23, 2:55 PM Store Passwords Securely in Database using SHA256 — ASP .NET Core | by Juldhais Hengkyawan | Medium
1 namespace PasswordHashExample.WebAPI.Entities;
2
3 public sealed class User
4 {
5 public int Id { get; set; }
6 public string Username { get; set; }
7 public string Email { get; set; }
8 public string PasswordSalt { get; set; }
9 public string PasswordHash { get; set; }
10 }
Data Context
Add the DataContext class to the Data folder:
https://juldhais.net/secure-way-to-store-passwords-in-database-using-sha256-asp-net-core-898128d1c4ef 12/31
8/22/23, 2:55 PM Store Passwords Securely in Database using SHA256 — ASP .NET Core | by Juldhais Hengkyawan | Medium
1 using Microsoft.EntityFrameworkCore;
2 using PasswordHashExample.WebAPI.Entities;
3
4 namespace PasswordHashExample.WebAPI.Data;
5
6 public sealed class DataContext : DbContext
7 {
8 public DataContext(DbContextOptions<DataContext> options) : base(options)
9 {
10 }
11
12 public DbSet<User> Users { get; set; }
13 }
Resources
In the Resources folder, add these record classes: LoginResource ,
1 namespace PasswordHashExample.WebAPI.Resources;
2
3 public sealed record LoginResource(string Username, string Password);
https://juldhais.net/secure-way-to-store-passwords-in-database-using-sha256-asp-net-core-898128d1c4ef 13/31
8/22/23, 2:55 PM Store Passwords Securely in Database using SHA256 — ASP .NET Core | by Juldhais Hengkyawan | Medium
1 namespace PasswordHashExample.WebAPI.Resources;
2
3 public sealed record RegisterResource(string Username, string Email, string Password);
1 namespace PasswordHashExample.WebAPI.Resources;
2
3 public sealed record UserResource(int Id, string Username, string Email);
Password Hasher
In the Services folder, we will create a class for computing a hash with salt,
pepper, and iteration. The class name is PasswordHasher :
https://juldhais.net/secure-way-to-store-passwords-in-database-using-sha256-asp-net-core-898128d1c4ef 14/31
8/22/23, 2:55 PM Store Passwords Securely in Database using SHA256 — ASP .NET Core | by Juldhais Hengkyawan | Medium
1 using System.Security.Cryptography;
2 using System.Text;
3
4 namespace PasswordHashExample.WebAPI.Services;
5
6 public static class PasswordHasher
7 {
8 public static string ComputeHash(string password, string salt, string pepper, int iteration)
9 {
10 if (iteration <= 0) return password;
11
12 using var sha256 = SHA256.Create();
13 var passwordSaltPepper = $"{password}{salt}{pepper}";
14 var byteValue = Encoding.UTF8.GetBytes(passwordSaltPepper);
15 var byteHash = sha256.ComputeHash(byteValue);
16 var hash = Convert.ToBase64String(byteHash);
17 return ComputeHash(hash, salt, pepper, iteration - 1);
18 }
19
20 public static string GenerateSalt()
21 {
22 using var rng = RandomNumberGenerator.Create();
23 var byteSalt = new byte[16];
24 rng.GetBytes(byteSalt);
25 var salt = Convert.ToBase64String(byteSalt);
26 return salt;
27 }
28 }
https://juldhais.net/secure-way-to-store-passwords-in-database-using-sha256-asp-net-core-898128d1c4ef 15/31
8/22/23, 2:55 PM Store Passwords Securely in Database using SHA256 — ASP .NET Core | by Juldhais Hengkyawan | Medium
The process of combining password, salt, and pepper happened in line 13:
var passwordSaltPepper = $”{password}{salt}{pepper}”;
Similar to cooking, the process of adding salt and pepper can be adjusted
according to taste until the desired complexity is reached 😆
The hash result in the byte array is converted to a base 64 string, which is
then re-entered as a password parameter into the ComputeHash() function
until the iteration process is complete.
Services
In the Services folder, add the IUserService interface and the UserService
class:
https://juldhais.net/secure-way-to-store-passwords-in-database-using-sha256-asp-net-core-898128d1c4ef 16/31
8/22/23, 2:55 PM Store Passwords Securely in Database using SHA256 — ASP .NET Core | by Juldhais Hengkyawan | Medium
1 using PasswordHashExample.WebAPI.Resources;
2
3 namespace PasswordHashExample.WebAPI.Services;
4
5 public interface IUserService
6 {
7 Task<UserResource> Register(RegisterResource resource, CancellationToken cancellationToken);
8 Task<UserResource> Login(LoginResource resource, CancellationToken cancellationToken);
9 }
https://juldhais.net/secure-way-to-store-passwords-in-database-using-sha256-asp-net-core-898128d1c4ef 17/31
8/22/23, 2:55 PM Store Passwords Securely in Database using SHA256 — ASP .NET Core | by Juldhais Hengkyawan | Medium
1 using Microsoft.EntityFrameworkCore;
2 using PasswordHashExample.WebAPI.Data;
3 using PasswordHashExample.WebAPI.Entities;
4 using PasswordHashExample.WebAPI.Resources;
5
6 namespace PasswordHashExample.WebAPI.Services;
7
8 public sealed class UserService : IUserService
9 {
10 private readonly DataContext _context;
11 private readonly string _pepper;
12 private readonly int _iteration = 3;
13
14 public UserService(DataContext context)
15 {
16 _context = context;
17 _pepper = Environment.GetEnvironmentVariable("PasswordHashExamplePepper");
18 }
19
20 public async Task<UserResource> Register(RegisterResource resource, CancellationToken cancell
21 {
22 var user = new User
23 {
24 Username = resource.Username,
25 Email = resource.Email,
26 PasswordSalt = PasswordHasher.GenerateSalt()
27 };
28 user.PasswordHash = PasswordHasher.ComputeHash(resource.Password, user.PasswordSalt, _pep
29 await _context.Users.AddAsync(user, cancellationToken);
30 await _context.SaveChangesAsync(cancellationToken);
31
32 return new UserResource(user.Id, user.Username, user.Email);
33 }
https://juldhais.net/secure-way-to-store-passwords-in-database-using-sha256-asp-net-core-898128d1c4ef 18/31
8/22/23, 2:55 PM Store Passwords Securely in Database using SHA256 — ASP .NET Core | by Juldhais Hengkyawan | Medium
33 }
34
35 public async Task<UserResource> Login(LoginResource resource, CancellationToken cancellationT
36 {
37 var user = await _context.Users
38 .FirstOrDefaultAsync(x => x.Username == resource.Username, cancellationToken);
39
40 if (user == null)
41 throw new Exception("Username or password did not match.");
42
43 var passwordHash = PasswordHasher.ComputeHash(resource.Password, user.PasswordSalt, _pepp
44 if (user.PasswordHash != passwordHash)
45 throw new Exception("Username or password did not match.");
46
47 return new UserResource(user.Id, user.Username, user.Email);
48 }
49 }
PasswordSalt = PasswordHasher.GenerateSalt()
https://juldhais.net/secure-way-to-store-passwords-in-database-using-sha256-asp-net-core-898128d1c4ef 19/31
8/22/23, 2:55 PM Store Passwords Securely in Database using SHA256 — ASP .NET Core | by Juldhais Hengkyawan | Medium
Next, the password hashing process using salt, pepper, and iteration:
user.PasswordHash = PasswordHasher.ComputeHash(resource.Password,
user.PasswordSalt, _pepper, _iteration);
The value of the _pepper is retrieved from the Environment Variables, and the
value of _iteration is set to 3.
Controllers
In the Controllers folder, add a controller named UserController :
https://juldhais.net/secure-way-to-store-passwords-in-database-using-sha256-asp-net-core-898128d1c4ef 20/31
8/22/23, 2:55 PM Store Passwords Securely in Database using SHA256 — ASP .NET Core | by Juldhais Hengkyawan | Medium
1 using Microsoft.AspNetCore.Mvc;
2 using PasswordHashExample.WebAPI.Resources;
3 using PasswordHashExample.WebAPI.Services;
4
5 namespace PasswordHashExample.WebAPI.Controllers;
6
7 [ApiController]
8 [Route("user")]
9 public class UserController : ControllerBase
10 {
11 private readonly IUserService _userService;
12
13 public UserController(IUserService userService)
14 {
15 _userService = userService;
16 }
17
18 [HttpPost("register")]
19 public async Task<IActionResult> Register([FromBody] RegisterResource resource, CancellationT
20 {
21 try
22 {
23 var response = await _userService.Register(resource, cancellationToken);
24 return Ok(response);
25 }
26 catch (Exception e)
27 {
28 return BadRequest(new { ErrorMessage = e.Message });
29 }
30 }
31
32 [HttpPost("login")]
33 public async Task<IActionResult> Login([FromBody] LoginResource resource CancellationToken c
https://juldhais.net/secure-way-to-store-passwords-in-database-using-sha256-asp-net-core-898128d1c4ef 21/31
8/22/23, 2:55 PM Store Passwords Securely in Database using SHA256 — ASP .NET Core | by Juldhais Hengkyawan | Medium
33 public async Task<IActionResult> Login([FromBody] LoginResource resource, CancellationToken c
34 {
35 try
36 {
37 var response = await _userService.Login(resource, cancellationToken);
38 return Ok(response);
39 }
40 catch (Exception e)
41 {
42 return BadRequest(new { ErrorMessage = e.Message });
43 }
44 }
45 }
Program.cs
Register the DataContext and UserService in the Program.cs file:
https://juldhais.net/secure-way-to-store-passwords-in-database-using-sha256-asp-net-core-898128d1c4ef 22/31
8/22/23, 2:55 PM Store Passwords Securely in Database using SHA256 — ASP .NET Core | by Juldhais Hengkyawan | Medium
1 using Microsoft.EntityFrameworkCore;
2 using PasswordHashExample.WebAPI.Data;
3 using PasswordHashExample.WebAPI.Services;
4
5 var builder = WebApplication.CreateBuilder(args);
6
7 builder.Services.AddDbContext<DataContext>(opt =>
8 opt.UseSqlite(builder.Configuration.GetConnectionString("SqliteDataContext")));
9
10 builder.Services.AddScoped<IUserService, UserService>();
11
12 builder.Services.AddControllers();
13 builder.Services.AddEndpointsApiExplorer();
14 builder.Services.AddSwaggerGen();
15
16 var app = builder.Build();
17 if (app.Environment.IsDevelopment())
18 {
19 var db = app.Services.CreateScope().ServiceProvider.GetService<DataContext>();
20 db?.Database.EnsureCreated();
21 app.UseSwagger();
22 app.UseSwaggerUI();
23 }
24
25 app.UseHttpsRedirection();
26 app.UseAuthorization();
27 app.MapControllers();
28 app.Run();
https://juldhais.net/secure-way-to-store-passwords-in-database-using-sha256-asp-net-core-898128d1c4ef 23/31
8/22/23, 2:55 PM Store Passwords Securely in Database using SHA256 — ASP .NET Core | by Juldhais Hengkyawan | Medium
1 "ConnectionStrings": {
2 "SqliteDataContext": "Data Source=user.db"
3 },
Let’s Try
Run the application and do register and login:
Register
https://juldhais.net/secure-way-to-store-passwords-in-database-using-sha256-asp-net-core-898128d1c4ef 24/31
8/22/23, 2:55 PM Store Passwords Securely in Database using SHA256 — ASP .NET Core | by Juldhais Hengkyawan | Medium
Login
I have created two users: admin and budi. Both users have the same
password: admin. The password hashes are different even though they have
the same password:
User Table
https://juldhais.net/secure-way-to-store-passwords-in-database-using-sha256-asp-net-core-898128d1c4ef 25/31
8/22/23, 2:55 PM Store Passwords Securely in Database using SHA256 — ASP .NET Core | by Juldhais Hengkyawan | Medium
GitHub - juldhais/PasswordHashExample
github.com
https://juldhais.net/secure-way-to-store-passwords-in-database-using-sha256-asp-net-core-898128d1c4ef 26/31
8/22/23, 2:55 PM Store Passwords Securely in Database using SHA256 — ASP .NET Core | by Juldhais Hengkyawan | Medium
951 Followers
828 16 471 5
175 2 283 3
https://juldhais.net/secure-way-to-store-passwords-in-database-using-sha256-asp-net-core-898128d1c4ef 28/31
8/22/23, 2:55 PM Store Passwords Securely in Database using SHA256 — ASP .NET Core | by Juldhais Hengkyawan | Medium
139 14
Lists
https://juldhais.net/secure-way-to-store-passwords-in-database-using-sha256-asp-net-core-898128d1c4ef 29/31
8/22/23, 2:55 PM Store Passwords Securely in Database using SHA256 — ASP .NET Core | by Juldhais Hengkyawan | Medium
60 2 309 5
https://juldhais.net/secure-way-to-store-passwords-in-database-using-sha256-asp-net-core-898128d1c4ef 30/31
8/22/23, 2:55 PM Store Passwords Securely in Database using SHA256 — ASP .NET Core | by Juldhais Hengkyawan | Medium
8 1 966 26
https://juldhais.net/secure-way-to-store-passwords-in-database-using-sha256-asp-net-core-898128d1c4ef 31/31