Compare commits

...

1 Commits

Author SHA1 Message Date
638e680a97 Upgrade dependencies, add encrypted connection strings
- Updated NuGet packages across projects for compatibility and bug fixes
- Switched to Microsoft.OpenApi and refactored Swagger setup
- Added AES encryption/decryption for connection strings
- Stored encrypted DB/cache connection strings in config
- Improved encryption reliability in Program.cs
- Added AutoMapper to multiple projects for mapping support
- Enhanced security and code maintainability
2026-03-14 22:57:00 +05:30
10 changed files with 72 additions and 66 deletions

View File

@ -94,10 +94,10 @@ static string EncryptDataWithAes(string plainText, string keyBase64, out string
{
using (StreamWriter sw = new StreamWriter(cs))
{
sw.Write(plainText);
sw.Write(plainText); // Missing explicit flush before dispose
}
encryptedData = ms.ToArray();
}
encryptedData = ms.ToArray();
}
return Convert.ToBase64String(encryptedData);

View File

@ -1,6 +1,6 @@
using Asp.Versioning.ApiExplorer;
using Microsoft.Extensions.Options;
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi;
using Swashbuckle.AspNetCore.SwaggerGen;
public class ConfigureSwaggerOptions : IConfigureOptions<SwaggerGenOptions>

View File

@ -11,22 +11,23 @@
<ItemGroup>
<PackageReference Include="Asp.Versioning.Mvc" Version="8.1.1" />
<PackageReference Include="Asp.Versioning.Mvc.ApiExplorer" Version="8.1.1" />
<PackageReference Include="AutoMapper" Version="16.0.0" />
<PackageReference Include="BCrypt.Net-Next" Version="4.0.3" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="10.0.3" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="9.0.9" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.9" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="9.0.9">
<PackageReference Include="AutoMapper" Version="16.1.1" />
<PackageReference Include="BCrypt.Net-Next" Version="4.1.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="10.0.5" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="10.0.5" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.5" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="9.0.5">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Otp.NET" Version="1.4.0" />
<PackageReference Include="Microsoft.OpenApi" Version="2.4.1" />
<PackageReference Include="Otp.NET" Version="1.4.1" />
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="9.0.0" />
<PackageReference Include="Razor.Templating.Core" Version="2.1.0" />
<PackageReference Include="Serilog.AspNetCore" Version="9.0.0" />
<PackageReference Include="serilog.sinks.console" Version="6.0.0" />
<PackageReference Include="Razor.Templating.Core" Version="3.1.0" />
<PackageReference Include="Serilog.AspNetCore" Version="10.0.0" />
<PackageReference Include="serilog.sinks.console" Version="6.1.1" />
<PackageReference Include="serilog.sinks.file" Version="7.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="9.0.6" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="10.1.5" />
</ItemGroup>
<ItemGroup>

View File

@ -5,7 +5,7 @@ using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.FileProviders;
using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi;
using PortBlog.API.DbContexts;
using PortBlog.API.Extensions;
using PortBlog.API.Middleware;
@ -13,6 +13,7 @@ using Serilog;
using System.Reflection;
using System.Text;
using KBR.Shared.Extensions;
using Swashbuckle.AspNetCore.SwaggerGen;
var builder = WebApplication.CreateBuilder(args);
@ -143,15 +144,6 @@ builder.Services.AddSwaggerGen(c =>
Scheme = "ApiKeyScheme"
});
var key = new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "ApiKey"
}
};
// JWT Bearer Security Definition
c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
@ -162,23 +154,6 @@ builder.Services.AddSwaggerGen(c =>
Scheme = "Bearer",
BearerFormat = "JWT"
});
var bearerScheme = new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
}
};
var requirement = new OpenApiSecurityRequirement
{
{ key, new List<string>() },
{ bearerScheme, new List<string>() }
};
c.AddSecurityRequirement(requirement);
});
builder.Services.ConfigureOptions<ConfigureSwaggerOptions>();

View File

@ -1,12 +1,12 @@
{
"ConnectionStrings": {
"PortBlogDBConnectionString": "SERVER=192.168.0.197; DATABASE=cv_blog; UID=PortBlogDevUser; PWD=p@$$w0rd1234",
"Encryption": "false",
"PortBlogDBConnectionString": "XHIrOTmGNBQ8xE5DPwiEvtoNkU5YT6HsgwPYYawv7sRsMCnPGrAxbaiUZZ4mveUBP5yIAzzU5KSXK5XeoA9xxXugBF3nji2icvCQvoFxRqc=:CbDuLYbh/dAGyNU38qCHBQ==",
"Encryption": "true",
"Key": "rgdBsYjrgQV9YaE+6QFK5oyTOWwbl2bSWkuc2JXcIyw="
},
"Cache": {
"ConnectionString": "SERVER=192.168.0.197; DATABASE=cv_blog; UID=PortBlogDevUser; PWD=p@$$w0rd1234;Allow User Variables=true;",
"Encryption": "false",
"ConnectionString": "pxv9z73rYXioZIToJ4A4CfpmR3m6OeQ5CD5bdjXAKuH1UBu/RvdOPuUnxokDytq/vlDYfDdrsffNAs5t5r6VSVD/H/bvgGQV+I3X2mzo1343XbJfncPMORbJPP/tSdl0Yu5R5pMhrSXnG7vOHPu+Bw==:gHnavGn1ASf0Sovu3zquGg==",
"Encryption": "true",
"Provider": "SqlServer"
},
"Jwt": {

View File

@ -8,11 +8,12 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="AutoMapper" Version="16.1.1" />
<PackageReference Include="coverlet.collector" Version="8.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.3.0" />
<PackageReference Include="xunit" Version="2.9.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
<PrivateAssets>all</PrivateAssets>

View File

@ -7,14 +7,15 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="10.0.3" />
<PackageReference Include="Microsoft.Extensions.Caching.SqlServer" Version="10.0.3" />
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="10.0.3" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="10.0.3" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="10.0.3" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.3" />
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="10.0.3" />
<PackageReference Include="Microsoft.Extensions.Options" Version="10.0.3" />
<PackageReference Include="AutoMapper" Version="16.1.1" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="10.0.5" />
<PackageReference Include="Microsoft.Extensions.Caching.SqlServer" Version="10.0.5" />
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="10.0.5" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="10.0.5" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="10.0.5" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.5" />
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="10.0.5" />
<PackageReference Include="Microsoft.Extensions.Options" Version="10.0.5" />
<PackageReference Include="Pomelo.Extensions.Caching.MySql" Version="2.2.1" />
</ItemGroup>

View File

@ -7,6 +7,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="AutoMapper" Version="16.1.1" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
</ItemGroup>

View File

@ -1,13 +1,45 @@
using Microsoft.Extensions.Configuration;
using System.Security.Cryptography;
using System.Text;
namespace KBR.Shared.Extensions
{
public static class ConfigurationExtensions
{
public static string EncryptConnectionString(this IConfiguration configuration, string plainConnectionString)
{
string keyBase64 = configuration.GetSection("ConnectionStrings:Key").Value;
using (Aes aesAlgorithm = Aes.Create())
{
aesAlgorithm.Key = Convert.FromBase64String(keyBase64);
aesAlgorithm.GenerateIV();
aesAlgorithm.Mode = CipherMode.CBC;
aesAlgorithm.Padding = PaddingMode.PKCS7;
ICryptoTransform encryptor = aesAlgorithm.CreateEncryptor();
byte[] encryptedData;
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
{
byte[] plainBytes = Encoding.UTF8.GetBytes(plainConnectionString);
cs.Write(plainBytes, 0, plainBytes.Length);
cs.FlushFinalBlock(); // Explicitly apply padding
}
encryptedData = ms.ToArray();
}
string cipherBase64 = Convert.ToBase64String(encryptedData);
string ivBase64 = Convert.ToBase64String(aesAlgorithm.IV);
return $"{cipherBase64}:{ivBase64}";
}
}
public static string DecryptConnectionString(this IConfiguration configuration, string encryptedConnectionString)
{
// Fix: Use GetSection and Value instead of GetValue (since GetValue is not available on IConfiguration)
string keyBase64 = configuration.GetSection("ConnectionStrings:Key").Value;
string vectorBase64 = encryptedConnectionString.Split(":")[1];
@ -17,24 +49,18 @@ namespace KBR.Shared.Extensions
{
aesAlgorithm.Key = Convert.FromBase64String(keyBase64);
aesAlgorithm.IV = Convert.FromBase64String(vectorBase64);
aesAlgorithm.Mode = CipherMode.CBC;
aesAlgorithm.Padding = PaddingMode.PKCS7;
Console.WriteLine($"Aes Cipher Mode : {aesAlgorithm.Mode}");
Console.WriteLine($"Aes Padding Mode: {aesAlgorithm.Padding}");
Console.WriteLine($"Aes Key Size : {aesAlgorithm.KeySize}");
Console.WriteLine($"Aes Block Size : {aesAlgorithm.BlockSize}");
// Create decryptor object
ICryptoTransform decryptor = aesAlgorithm.CreateDecryptor();
byte[] cipher = Convert.FromBase64String(cipherText);
//Decryption will be done in a memory stream through a CryptoStream object
using (MemoryStream ms = new MemoryStream(cipher))
{
using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
{
using (StreamReader sr = new StreamReader(cs))
using (StreamReader sr = new StreamReader(cs, Encoding.UTF8))
{
return sr.ReadToEnd();
}

View File

@ -7,8 +7,9 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="10.0.3" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="10.0.3" />
<PackageReference Include="AutoMapper" Version="16.1.1" />
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="10.0.5" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="10.0.5" />
</ItemGroup>
<ItemGroup>