Adding SHA256 password encryption and password verify
This commit is contained in:
@@ -59,10 +59,13 @@ public class AuthController_Tests
|
|||||||
LastName = "test",
|
LastName = "test",
|
||||||
Email = "test",
|
Email = "test",
|
||||||
PasswordHash = "test",
|
PasswordHash = "test",
|
||||||
|
PasswordSalt = "test",
|
||||||
|
Password = "test",
|
||||||
Role = new DatabaseSqlServer.Role()
|
Role = new DatabaseSqlServer.Role()
|
||||||
{
|
{
|
||||||
Name = "test"
|
Name = "test"
|
||||||
}
|
},
|
||||||
|
IsTestUser = true
|
||||||
};
|
};
|
||||||
AuthenticatedUser authenticatedUser = new AuthenticatedUser(user);
|
AuthenticatedUser authenticatedUser = new AuthenticatedUser(user);
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,8 @@
|
|||||||
"ExpiredAfterMinsOfInactivity": 15
|
"ExpiredAfterMinsOfInactivity": 15
|
||||||
},
|
},
|
||||||
"EncryptionSettings": {
|
"EncryptionSettings": {
|
||||||
"Salt": "S7VIidfXQf1tOQYX"
|
"Salt": "S7VIidfXQf1tOQYX",
|
||||||
|
"Pepper": ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,8 @@
|
|||||||
"ExpiredAfterMinsOfInactivity": 15
|
"ExpiredAfterMinsOfInactivity": 15
|
||||||
},
|
},
|
||||||
"EncryptionSettings": {
|
"EncryptionSettings": {
|
||||||
"Salt": "AAAAA"
|
"Salt": "AAAAA",
|
||||||
|
"Pepper": ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,10 +29,13 @@ public class AuthenticatedUser_Tests
|
|||||||
LastName = "test",
|
LastName = "test",
|
||||||
Email = "test",
|
Email = "test",
|
||||||
PasswordHash = "test",
|
PasswordHash = "test",
|
||||||
|
PasswordSalt = "test",
|
||||||
|
Password = "test",
|
||||||
Role = new DatabaseSqlServer.Role()
|
Role = new DatabaseSqlServer.Role()
|
||||||
{
|
{
|
||||||
Name = "test"
|
Name = "test"
|
||||||
}
|
},
|
||||||
|
IsTestUser = true
|
||||||
};
|
};
|
||||||
AuthenticatedUser authenticatedUser = new AuthenticatedUser(user);
|
AuthenticatedUser authenticatedUser = new AuthenticatedUser(user);
|
||||||
|
|
||||||
|
|||||||
@@ -74,10 +74,13 @@ public class AuthenticateResponse_Tests
|
|||||||
LastName = "test",
|
LastName = "test",
|
||||||
Email = "test",
|
Email = "test",
|
||||||
PasswordHash = "test",
|
PasswordHash = "test",
|
||||||
|
PasswordSalt = "test",
|
||||||
|
Password = "test",
|
||||||
Role = new DatabaseSqlServer.Role()
|
Role = new DatabaseSqlServer.Role()
|
||||||
{
|
{
|
||||||
Name = "test"
|
Name = "test"
|
||||||
}
|
},
|
||||||
|
IsTestUser = true
|
||||||
};
|
};
|
||||||
AuthenticatedUser data = new AuthenticatedUser(user);
|
AuthenticatedUser data = new AuthenticatedUser(user);
|
||||||
var authenticateResponse = new AuthenticateResponse(200, "This is a test message", data);
|
var authenticateResponse = new AuthenticateResponse(200, "This is a test message", data);
|
||||||
|
|||||||
@@ -101,6 +101,67 @@ public class CryptoUtils_Tests
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void GenerateSalt()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var salt = CryptUtils.GenerateSalt();
|
||||||
|
Assert.IsTrue(!String.IsNullOrEmpty(salt));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine(ex.InnerException);
|
||||||
|
Assert.Fail($"An exception was thrown: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void ComputeHash_Hashed()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var password = "P4ssw0rd@1!";
|
||||||
|
var salt = CryptUtils.GenerateSalt();
|
||||||
|
Assert.IsTrue(!String.IsNullOrEmpty(salt));
|
||||||
|
|
||||||
|
WebApplicationBuilder builder = WebApplication.CreateBuilder(Array.Empty<string>());
|
||||||
|
AppSettings appSettings = ProgramUtils.AddConfiguration(ref builder, System.AppDomain.CurrentDomain.BaseDirectory + "/JsonData");
|
||||||
|
CryptUtils cryptoUtils = new CryptUtils(appSettings);
|
||||||
|
var encryptedPassword = cryptoUtils.GeneratePassword(password, salt, 0);
|
||||||
|
Assert.IsTrue(password != encryptedPassword);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine(ex.InnerException);
|
||||||
|
Assert.Fail($"An exception was thrown: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void VerifyPassword_True()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var password = "P4ssw0rd@1!";
|
||||||
|
var salt = "Afi7PQYgEL2sPbNyVzduvg==";
|
||||||
|
var hashedPassword = "2lMeySZ9ciH1KtSg1Z7oSJRmJEjHMeDvdaNRcJcGutM=";
|
||||||
|
|
||||||
|
WebApplicationBuilder builder = WebApplication.CreateBuilder(Array.Empty<string>());
|
||||||
|
AppSettings appSettings = ProgramUtils.AddConfiguration(ref builder, System.AppDomain.CurrentDomain.BaseDirectory + "/JsonData");
|
||||||
|
CryptUtils cryptoUtils = new CryptUtils(appSettings);
|
||||||
|
var verified = cryptoUtils.VerifyPassword(password, salt, 0, hashedPassword);
|
||||||
|
Console.WriteLine(cryptoUtils.GeneratePassword(password, salt, 0));
|
||||||
|
|
||||||
|
Assert.IsTrue(verified);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine(ex.InnerException);
|
||||||
|
Assert.Fail($"An exception was thrown: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
154
MainProject/Migrations/20250311195750_AlterTableUser.Designer.cs
generated
Normal file
154
MainProject/Migrations/20250311195750_AlterTableUser.Designer.cs
generated
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using BasicDotnetTemplate.MainProject.Core.Database;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace MainProject.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(SqlServerContext))]
|
||||||
|
[Migration("20250311195750_AlterTableUser")]
|
||||||
|
partial class AlterTableUser
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "9.0.2")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 128);
|
||||||
|
|
||||||
|
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.Role", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreationTime")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<int>("CreationUserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<DateTime>("DeletionTime")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<int>("DeletionUserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Guid")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<bool>("IsDeleted")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("UpdateTime")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<int>("UpdateUserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Role");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.User", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreationTime")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<int>("CreationUserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<DateTime>("DeletionTime")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<int>("DeletionUserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Email")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("FirstName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Guid")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<bool>("IsDeleted")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<string>("LastName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Password")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("PasswordHash")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("PasswordSalt")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<int>("RoleId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<DateTime>("UpdateTime")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<int>("UpdateUserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Username")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("RoleId");
|
||||||
|
|
||||||
|
b.ToTable("Users");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.User", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.Role", "Role")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("RoleId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Role");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
84
MainProject/Migrations/20250311195750_AlterTableUser.cs
Normal file
84
MainProject/Migrations/20250311195750_AlterTableUser.cs
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace MainProject.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class AlterTableUser : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "Guid",
|
||||||
|
table: "Users",
|
||||||
|
type: "nvarchar(max)",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: "");
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<bool>(
|
||||||
|
name: "IsDeleted",
|
||||||
|
table: "Users",
|
||||||
|
type: "bit",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: false);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "Password",
|
||||||
|
table: "Users",
|
||||||
|
type: "nvarchar(max)",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: "");
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "PasswordSalt",
|
||||||
|
table: "Users",
|
||||||
|
type: "nvarchar(max)",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: "");
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "Guid",
|
||||||
|
table: "Role",
|
||||||
|
type: "nvarchar(max)",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: "");
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<bool>(
|
||||||
|
name: "IsDeleted",
|
||||||
|
table: "Role",
|
||||||
|
type: "bit",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "Guid",
|
||||||
|
table: "Users");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "IsDeleted",
|
||||||
|
table: "Users");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "Password",
|
||||||
|
table: "Users");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "PasswordSalt",
|
||||||
|
table: "Users");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "Guid",
|
||||||
|
table: "Role");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "IsDeleted",
|
||||||
|
table: "Role");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,7 +17,7 @@ namespace MainProject.Migrations
|
|||||||
{
|
{
|
||||||
#pragma warning disable 612, 618
|
#pragma warning disable 612, 618
|
||||||
modelBuilder
|
modelBuilder
|
||||||
.HasAnnotation("ProductVersion", "8.0.8")
|
.HasAnnotation("ProductVersion", "9.0.2")
|
||||||
.HasAnnotation("Relational:MaxIdentifierLength", 128);
|
.HasAnnotation("Relational:MaxIdentifierLength", 128);
|
||||||
|
|
||||||
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
|
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
|
||||||
@@ -42,6 +42,13 @@ namespace MainProject.Migrations
|
|||||||
b.Property<int>("DeletionUserId")
|
b.Property<int>("DeletionUserId")
|
||||||
.HasColumnType("int");
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Guid")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<bool>("IsDeleted")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
b.Property<string>("Name")
|
b.Property<string>("Name")
|
||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasColumnType("nvarchar(max)");
|
.HasColumnType("nvarchar(max)");
|
||||||
@@ -85,14 +92,29 @@ namespace MainProject.Migrations
|
|||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasColumnType("nvarchar(max)");
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Guid")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<bool>("IsDeleted")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
b.Property<string>("LastName")
|
b.Property<string>("LastName")
|
||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasColumnType("nvarchar(max)");
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Password")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
b.Property<string>("PasswordHash")
|
b.Property<string>("PasswordHash")
|
||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasColumnType("nvarchar(max)");
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("PasswordSalt")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
b.Property<int>("RoleId")
|
b.Property<int>("RoleId")
|
||||||
.HasColumnType("int");
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
|||||||
@@ -8,10 +8,13 @@ namespace BasicDotnetTemplate.MainProject.Models.Database.SqlServer
|
|||||||
public required string FirstName { get; set; }
|
public required string FirstName { get; set; }
|
||||||
public required string LastName { get; set; }
|
public required string LastName { get; set; }
|
||||||
public required string Email { get; set; }
|
public required string Email { get; set; }
|
||||||
|
public required string PasswordSalt { get; set; }
|
||||||
|
public required string PasswordHash { get; set; }
|
||||||
public required Role Role { get; set; }
|
public required Role Role { get; set; }
|
||||||
|
public required bool IsTestUser { get; set; }
|
||||||
|
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public required string PasswordHash { get; set; }
|
public required string Password { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,5 +4,6 @@ public class EncryptionSettings
|
|||||||
{
|
{
|
||||||
#nullable enable
|
#nullable enable
|
||||||
public string? Salt { get; set; }
|
public string? Salt { get; set; }
|
||||||
|
public string? Pepper { get; set; }
|
||||||
#nullable disable
|
#nullable disable
|
||||||
}
|
}
|
||||||
@@ -6,34 +6,36 @@ using BasicDotnetTemplate.MainProject.Models.Settings;
|
|||||||
namespace BasicDotnetTemplate.MainProject.Utils;
|
namespace BasicDotnetTemplate.MainProject.Utils;
|
||||||
public class CryptUtils
|
public class CryptUtils
|
||||||
{
|
{
|
||||||
private readonly string secretKey;
|
private readonly string _secretKey;
|
||||||
private const int M = 16;
|
private readonly string _pepper;
|
||||||
private const int N = 32;
|
private const int _M = 16;
|
||||||
|
private const int _N = 32;
|
||||||
|
|
||||||
public CryptUtils(AppSettings appSettings)
|
public CryptUtils(AppSettings appSettings)
|
||||||
{
|
{
|
||||||
secretKey = appSettings.EncryptionSettings?.Salt ?? String.Empty;
|
_secretKey = appSettings.EncryptionSettings?.Salt ?? String.Empty;
|
||||||
|
_pepper = appSettings.EncryptionSettings?.Pepper ?? String.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Decrypt(string encryptedData)
|
public string Decrypt(string encryptedData)
|
||||||
{
|
{
|
||||||
var decrypted = String.Empty;
|
var decrypted = String.Empty;
|
||||||
|
|
||||||
if (String.IsNullOrEmpty(this.secretKey) || this.secretKey.Length < M)
|
if (String.IsNullOrEmpty(this._secretKey) || this._secretKey.Length < _M)
|
||||||
{
|
{
|
||||||
throw new ArgumentException("Unable to proceed with decryption due to invalid settings");
|
throw new ArgumentException("Unable to proceed with decryption due to invalid settings");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!String.IsNullOrEmpty(encryptedData) && encryptedData.Length > N)
|
if (!String.IsNullOrEmpty(encryptedData) && encryptedData.Length > _N)
|
||||||
{
|
{
|
||||||
var iv = encryptedData.Substring(0, M);
|
var iv = encryptedData.Substring(0, _M);
|
||||||
|
|
||||||
var cipherText = encryptedData.Substring(N);
|
var cipherText = encryptedData.Substring(_N);
|
||||||
var fullCipher = Convert.FromBase64String(cipherText);
|
var fullCipher = Convert.FromBase64String(cipherText);
|
||||||
|
|
||||||
using (var aes = Aes.Create())
|
using (var aes = Aes.Create())
|
||||||
{
|
{
|
||||||
aes.Key = Encoding.UTF8.GetBytes(this.secretKey);
|
aes.Key = Encoding.UTF8.GetBytes(this._secretKey);
|
||||||
aes.IV = Encoding.UTF8.GetBytes(iv);
|
aes.IV = Encoding.UTF8.GetBytes(iv);
|
||||||
|
|
||||||
using (var decryptor = aes.CreateDecryptor(aes.Key, aes.IV))
|
using (var decryptor = aes.CreateDecryptor(aes.Key, aes.IV))
|
||||||
@@ -55,5 +57,37 @@ public class CryptUtils
|
|||||||
return decrypted;
|
return decrypted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string GenerateSalt()
|
||||||
|
{
|
||||||
|
using var rng = RandomNumberGenerator.Create();
|
||||||
|
var byteSalt = new byte[16];
|
||||||
|
rng.GetBytes(byteSalt);
|
||||||
|
var salt = Convert.ToBase64String(byteSalt);
|
||||||
|
return salt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GeneratePassword(string password, string salt, int iteration)
|
||||||
|
{
|
||||||
|
string hashedPassword = password;
|
||||||
|
for(var i = 0; i <= iteration; i++)
|
||||||
|
{
|
||||||
|
using var sha256 = SHA256.Create();
|
||||||
|
var passwordSaltPepper = $"{hashedPassword}{salt}{this._pepper}";
|
||||||
|
var byteValue = Encoding.UTF8.GetBytes(passwordSaltPepper);
|
||||||
|
var byteHash = sha256.ComputeHash(byteValue);
|
||||||
|
hashedPassword = Convert.ToBase64String(byteHash);
|
||||||
|
}
|
||||||
|
|
||||||
|
return hashedPassword;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool VerifyPassword(string password, string salt, int iteration, string userPassword)
|
||||||
|
{
|
||||||
|
string hashedPassword = this.GeneratePassword(password, salt, iteration);
|
||||||
|
return hashedPassword.Equals(userPassword, StringComparison.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ public class JwtTokenUtils
|
|||||||
}
|
}
|
||||||
catch(Exception exception)
|
catch(Exception exception)
|
||||||
{
|
{
|
||||||
Logger.Error($"[JwtTokenUtils][ValidateToken] | {exception.Message}");
|
Logger.Error($"[JwtTokenUtils][ValidateToken] | {exception}");
|
||||||
return guid;
|
return guid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,8 @@
|
|||||||
"ExpiredAfterMinsOfInactivity": 15
|
"ExpiredAfterMinsOfInactivity": 15
|
||||||
},
|
},
|
||||||
"EncryptionSettings": {
|
"EncryptionSettings": {
|
||||||
"Salt": "S7VIidfXQf1tOQYX"
|
"Salt": "S7VIidfXQf1tOQYX",
|
||||||
|
"Pepper": ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user