رمزنگاری داده‌ها در دیتابیس با EF Core

رمزنگاری داده‌ها در دیتابیس با EF Core
فهرست مقاله [نمایش]


    مقدمه ای بر  رمزنگاری داده‌ها


    ضرورت رمزنگاری داده‌ها


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

    تجربه تلخ ایرانیان از عدم رمزنگاری داده‌ها


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

    معرفی EF Core


    Entity Framework Core که به‌اختصار EF Core نامیده می‌شود، یک ابزار قدرتمند و مدرن برای دسترسی به دیتابیس‌ها در برنامه‌های .NET است. این فریم‌ورک به ما این امکان را می‌دهد که با استفاده از اشیاء و کلاس‌های معمولی در زبان C#، با دیتابیس‌های مختلف ارتباط برقرار کنیم. به‌این‌ترتیب، کار با دیتابیس‌ها برای برنامه‌نویسان آسان‌تر و کارآمدتر می‌شود. EF Core با ارائه روش‌های ساده و انعطاف‌پذیر برای کار با دیتابیس‌ها، به یکی از محبوب‌ترین ابزارها در جامعه توسعه‌دهندگان . ET تبدیل شده است.

     

    اصول رمزنگاری داده‌ها


    رمزنگاری (Encryption) فرایندی است که طی آن داده‌ها را به شکلی تبدیل می‌کنیم که تنها افراد مجاز قادر به خواندن آن باشند. این فرایند شبیه به نوشتن نامه‌ای به یک‌زبان مخفی است که تنها گیرنده‌ی نامه می‌تواند آن را ترجمه کند. در دنیای دیجیتال، رمزنگاری با استفاده از الگوریتم‌ها (Algorithms) و کلیدهای رمزنگاری (Encryption Keys) انجام می‌شود. این الگوریتم‌ها داده‌های عادی را به داده‌های رمزنگاری شده (Ciphertext) تبدیل می‌کنند. به‌این‌ترتیب، اطلاعات حساس مانند رمزهای عبور (Passwords) یا اطلاعات بانکی در برابر دسترسی‌های غیرمجاز محافظت می‌شوند.


    تفاوت رمزنگاری و رمزگشایی


    رمزنگاری (Encryption) و رمزگشایی (Decryption) دوروی یک سکه هستند. رمزنگاری فرایند تبدیل داده‌های قابل‌فهم به داده‌های رمزنگاری شده است. این کار با استفاده از کلید رمزنگاری (Encryption Key) و الگوریتم‌های خاص انجام می‌شود. در مقابل، رمزگشایی فرایند تبدیل داده‌های رمزنگاری شده (Ciphertext) به حالت اولیه‌ی خود (Plaintext) است. این کار با استفاده از کلید رمزگشایی (Decryption Key) انجام می‌شود که می‌تواند همان کلید رمزنگاری باشد یا کلیدی متفاوت در سیستم‌های رمزنگاری نامتقارن (Asymmetric Encryption).

    معرفی روش‌های رمزنگاری


    در دنیای رمزنگاری، دو دسته اصلی از روش‌های رمزنگاری وجود دارد: رمزنگاری متقارن و رمزنگاری نامتقارن . رمزنگاری متقارن از یک کلید واحد برای هم رمزنگاری و هم رمزگشایی استفاده می‌کند. این روش سریع و کارآمد است؛ اما نیازمند مدیریت دقیق کلیدهای رمزنگاری است. در مقابل، رمزنگاری نامتقارن از دو کلید مختلف استفاده می‌کند: یک کلید عمومی (Public Key) برای رمزنگاری و یک کلید خصوصی (Private Key) برای رمزگشایی. این روش امنیت بیشتری ارائه می‌دهد؛ اما در مقایسه با رمزنگاری متقارن، کندتر است.

    پیاده‌سازی رمزنگاری در EF Core
     

    معرفی ابزارهای موردنیاز


    برای رمزنگاری داده‌ها در EF Core، نیاز به استفاده از برخی کتابخانه‌ها و ابزارهای خاص داریم. این ابزارها به ما کمک می‌کنند تا بتوانیم الگوریتم‌های رمزنگاری استاندارد را به‌راحتی در پروژه‌های خود به کار ببریم. به‌عنوان‌مثال، می‌توان از کتابخانه‌هایی مانند System.Security.Cryptography در .NET استفاده کرد که امکانات گسترده‌ای برای رمزنگاری و رمزگشایی فراهم می‌کند.


    ساختار کلی برای رمزنگاری داده‌ها


    در این بخش، بر ساختار کلی برای رمزنگاری داده‌ها در EF Core تمرکز می‌کنیم. این ساختار شامل چندین مرحله است:
    1.    تعریف کلاس رمزنگاری: ایجاد یک کلاس در پروژه که وظیفه رمزنگاری و رمزگشایی داده‌ها را بر عهده دارد. این کلاس می‌تواند از الگوریتم‌های رمزنگاری موجود در .NET استفاده کند و باید توانایی رمزنگاری و رمزگشایی داده‌ها را با استفاده از کلیدهای تعریف شده داشته باشد.
    2.    تعبیه رمزنگاری در EF Core: ادغام سازوکار رمزنگاری با DbContext در EF Core به‌نحوی‌که هنگام ذخیره‌سازی اطلاعات در دیتابیس، داده‌ها به‌صورت خودکار رمزنگاری شوند و هنگام خواندن از دیتابیس، رمزگشایی شوند. این کار می‌تواند از طریق تعریف کاستوم کانورترها (Custom Converters) یا اورراید کردن متدهای SaveChanges و OnModelCreating انجام گیرد.
    3.    مدیریت کلیدهای رمزنگاری: مدیریت ایمن کلیدهای رمزنگاری یکی دیگر از جنبه‌های مهم در پیاده‌سازی رمزنگاری است. باید اطمینان حاصل کرد که کلیدها در مکانی امن ذخیره شده و تنها برای افراد مجاز قابل‌دسترسی باشند.

     

    نحوه رمزنگاری و رمزگشائی داده‌های حساس با کمک EF Core

     

    ایجاد کلاس EncryptionService

    یک کلاس با نام EncryptionService  به پروژه اضافه می‌کنیم، این کلاس نقش کلیدی در رمزنگاری و رمزگشایی داده‌های حساس ایفا می‌کند. این کلاس دارای دو متد اصلی، Encrypt و Decrypt  می‌باشد که به ترتیب برای رمزنگاری و رمزگشایی داده‌ها استفاده می‌شوند.


    متد Encrypt 
     

    متد Encrypt داده‌های ورودی را با استفاده از الگوریتم رمزنگاری پیشرفته (AES) رمزنگاری می‌کند. این فرآیند شامل تبدیل داده‌های متنی به بایت، رمزنگاری آن‌ها با استفاده از کلید رمزنگاری، و در نهایت تبدیل داده‌های رمزنگاری شده به فرمت Base64 برای ذخیره‌سازی ایمن در دیتابیس است.


    متد Decrypt
     

    متد Decrypt برای تبدیل داده‌های رمزنگاری شده به حالت اولیه‌شان استفاده می‌شود. این متد داده‌های رمزنگاری شده را از فرمت Base64 خارج کرده، و با استفاده از همان کلید و الگوریتمی که برای رمزنگاری به‌کاررفته بود، آن‌ها را رمزگشایی می‌کند.


    کلید رمزنگاری
     

    هر دو متد Encrypt و Decrypt از یک کلید رمزنگاری ثابت که در متغیری با نام  _encryptionKey ذخیره شده است استفاده می‌کنند که باید به‌گونه‌ای امن و مطمئن تعیین شود. این کلید نقش مهمی در تضمین امنیت داده‌های رمزنگاری شده دارد.


    کد کلاس  EncryptionService  :

     

    public class EncryptionService
    {
        private readonly string _encryptionKey = "your-secret-key";
    
    
    
        public string Encrypt(string input)
        {
            byte[] clearBytes = Encoding.Unicode.GetBytes(input);
            using (Aes encryptor = Aes.Create())
            {
                Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(_encryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
                encryptor.Key = pdb.GetBytes(32);
                encryptor.IV = pdb.GetBytes(16);
                using (MemoryStream ms = new MemoryStream())
                {
                    using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
                    {
                        cs.Write(clearBytes, 0, clearBytes.Length);
                        cs.Close();
                    }
                    input = Convert.ToBase64String(ms.ToArray());
                }
            }
            return input;
        }  
        
        public string Decrypt(string cipherText)
        {
            byte[] buffer = Convert.FromBase64String(cipherText);
    
            using (Aes aes = Aes.Create())
            {
                Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(_encryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
                aes.Key = pdb.GetBytes(32);
                aes.IV = pdb.GetBytes(16);
    
                ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
    
                using (MemoryStream memoryStream = new MemoryStream(buffer))
                {
                    using (CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
                    {
                        using (StreamReader streamReader = new StreamReader(cryptoStream))
                        {
                            return streamReader.ReadToEnd();
                        }
                    }
                }
            }
        }
    
    } 


    ایجاد کلاس EncryptionConverter

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

    پس ما نیاز داریم که یک کلاس با نام EncryptionConverter   که از ValueConverter ارث بری می‌کند در پروژه ایجاد کنیم.

     

    public class EncryptionConverter : ValueConverter<string, string>
    {
       public EncryptionConverter(EncryptionService encryptionService)
           : base(
               v => encryptionService.Encrypt(v) ,
               v => encryptionService.Decrypt(v))
       {
       }
    }

    کلاس EncryptionConverter  یک ValueConverter است که برای تبدیل انواع داده‌ها در EF Core مورداستفاده قرار می‌گیرد. در این مورد، این کلاس به‌منظور تبدیل داده‌های متنی به نسخه‌ی رمزنگاری شده‌شان و برعکس طراحی شده است.


    نقش و عملکرد


    •    تبدیل داده‌ها: کلاس EncryptionConverter در عملیات ذخیره‌سازی و بازیابی داده‌ها از دیتابیس نقش اساسی ایفا می‌کند. هنگامی که داده‌ای برای ذخیره‌سازی به دیتابیس فرستاده می‌شود، این کلاس داده‌های متنی را به فرمت رمزنگاری شده تبدیل می‌کند. به همین ترتیب، هنگام بازیابی داده‌ها، داده‌های رمزنگاری شده را به حالت اصلی (متن خوانا) بازمی‌گرداند.
    •    استفاده از کلاس EncryptionService :  کلاس EncryptionConverter    از کلاس EncryptionService برای انجام عملیات رمزنگاری و رمزگشایی داده‌ها استفاده می‌کند. این  یعنی هر گونه تغییر در نحوه رمزنگاری یا رمزگشایی در EncryptionService به طور خودکار در EncryptionConverter نیز اعمال می‌شود.


    مزایا


    •    یکپارچگی و امنیت: استفاده از EncryptionConverter به توسعه‌دهندگان امکان می‌دهد تا به‌راحتی امنیت داده‌ها را تضمین کنند، بدون اینکه نیاز به دخالت دستی در هر عملیات CRUD داشته باشند.
    •    سادگی و کارایی: با این کلاس، رمزنگاری و رمزگشایی داده‌ها به طور خودکار و بدون نیاز به کدهای تکراری در بخش‌های مختلف برنامه انجام می‌شود.

     

     ایجاد کلاس User

    کلاس   User  که در پروژه ما تعریف شده، به‌عنوان یک انتیتی  در EF Core عمل می‌کند. این کلاس نمایانگر اطلاعات کاربران در دیتابیس ما است و شامل فیلدهای مختلفی است. هدف اصلی ما در این بخش، رمزنگاری دو فیلد حساس Email  و  PhoneNumber  است تا امنیت اطلاعات کاربران را تضمین کنیم.

    
    public class User
    {
       public int Id { get; set; }
       public string? Name { get; set; }
       public string? LastName { get; set; }
       public required string Email { get; set; }
       public string? PhoneNumber { get; set; }
       public required string Password { get; set; }
    }


    استفاده از کلاس EncryptionConverter در کلاس MyDbContext
     

    در کلاس MyDbContext، که نقش اصلی را در ارتباط با دیتابیس ایفا می‌کند، ما با استفاده از کلاس EncryptionConverter، فرایند رمزنگاری و رمزگشایی داده‌های حساس را به‌صورت خودکار انجام می‌دهیم. این کلاس، که از DbContext در Entity Framework Core ارث‌بری می‌کند، مسئول تعریف و مدیریت نحوه ارتباط اشیاء با دیتابیس است.
    در OnModelCreating، ما ساختار و قواعد مربوط به مدل‌های داده‌ای را تعریف می‌کنیم. در اینجا، EncryptionConverter برای تبدیل خودکار داده‌های فیلدهای Email و PhoneNumber کلاس User به کار گرفته می‌شود. این کار با استفاده از متد HasConversion انجام می‌شود که به EF Core دستور می‌دهد تا برای هر عملیات خواندن یا نوشتن این داده‌ها، از EncryptionConverter استفاده کند.
    متد HasConversion به EF Core می‌گوید که هنگام ذخیره‌سازی داده‌های Email و PhoneNumber در دیتابیس، آن‌ها را با استفاده از متد Encrypt کلاس EncryptionService رمزنگاری کند و هنگام بازیابی از دیتابیس، با استفاده از متد Decrypt همین کلاس، آن‌ها را رمزگشایی کند. این رویکرد امنیت داده‌های حساس را تضمین می‌کند و از دسترسی غیرمجاز به اطلاعات جلوگیری می‌کند.
    این فرایند که به طور خودکار و پشت پرده انجام می‌گیرد، به توسعه‌دهندگان اجازه می‌دهد تا بدون نگرانی از جزئیات فنی رمزنگاری، بر روی منطق اصلی برنامه تمرکز کنند.

    Public class MyDbContext : DbContext
    {
    
       public DbSet<User> User { get; set; }
       protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
       {
           if (! optionsBuilder.IsConfigured)
           {
               optionsBuilder.UseSqlServer(“Server=.;Database=DB-EncryptSensitiveData; Integrated Security=True ;TrustServerCertificate=True”) ;
           }
       }
       private readonly EncryptionService _encryptionService = new EncryptionService() ;
       protected override void OnModelCreating(ModelBuilder modelBuilder)
       {
           var encryptionConverter = new EncryptionConverter(_encryptionService);
           modelBuilder.Entity<User> ()
               .Property(u => u.Email)
               .HasConversion(encryptionConverter);
           modelBuilder.Entity<User> ()
               .Property(u => u.PhoneNumber)
               .HasConversion(encryptionConverter);
       }
    }


    بررسی نتیجه نهایی


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

    MyDbContext myDbContext = new MyDbContext() ;
    myDbContext.Add(new User
    {
        Email="info@bugeto.net",
        Name="Ehsan",
        LastName="Babaei",
        Password="123",
        PhoneNumber="09120000000"
    }) ;
    myDbContext.SaveChanges() ;
    var firstUser=myDbContext.User.First() ;
    Console.WriteLine($"Name:{firstUser.Name}  {firstUser.LastName}") ;
    Console.WriteLine($"Email:{firstUser.Email}  ") ;
    Console.WriteLine($"PhoneNumber :{firstUser.PhoneNumber}  ") ;

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

    داده های رمزنگاری شده با EF Core و  dot net در دیتابیس SQL

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

    رمزگشایی داده های رمزنگاری شده و و نمایش ان

    در انتهای مقاله سورس کامل را بصورت یکجا قرار داده ایم که می توانید کپی و استفاده نمایید.


    مسائل امنیتی


    نگهداری کلیدهای رمزنگاری


    نحوه‌ی نگهداری و مدیریت کلیدهای رمزنگاری بر امنیت کلی سیستم شما تأثیر بسزایی دارد. کلیدهای رمزنگاری باید در مکانی امن و دور از دسترس ذخیره شوند. استفاده از سیستم‌های مدیریت کلید (Key Management Systems) یا حتی استفاده از مکانیزم‌های سخت‌افزاری مانند HSMها (Hardware Security Modules) برای نگهداری این کلیدها توصیه می‌شود. علاوه بر این، دسترسی به کلیدها باید تنها به افرادی که نیاز مبرم به آن‌ها دارند محدود شود.

    رعایت اصول امنیتی در رمزنگاری داده‌ها


    هنگام رمزنگاری داده‌ها، باید از الگوریتم‌های رمزنگاری استاندارد و به روز استفاده شود. از الگوریتم‌های قدیمی و منسوخ شده باید پرهیز کرد. همچنین، توجه به مسائلی مانند طول کلید رمزنگاری و استفاده صحیح از IVها (Initialization Vectors) برای افزایش امنیت بسیار مهم است. در رمزنگاری داده‌ها، باید از تکنیک‌های رمزنگاری متناسب با نوع داده‌ها و حساسیت اطلاعات استفاده کرد تا از تهدیدات امنیتی مانند حملات مرد میانی (Man-in-the-Middle Attacks) و حملات تکرار (Replay Attacks) جلوگیری شود.

    چالش‌ها و راه‌حل‌ها


    مواجهه با مشکلات عملی


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

    راهکارهای مقابله با چالش‌های امنیتی

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

    تفاوت هش با رمزنگاری


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

    نتیجه‌گیری


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


    مزایا


    1.    افزایش امنیت: با رمزنگاری داده‌های حساس، از دسترسی و استفاده غیرمجاز جلوگیری می‌شود.
    2.    حفظ اعتماد کاربران: حفاظت از اطلاعات شخصی کاربران، اعتماد آن‌ها را به برنامه شما حفظ می‌کند.
    3.    اطمینان به استانداردهای امنیتی: رمزنگاری به پاسخگویی به الزامات قانونی و استانداردهای امنیتی کمک می‌کند.


    معایب


    1.    کاهش عملکرد: فرآیندهای رمزنگاری ممکن است عملکرد سیستم را تحت تأثیر قرار دهند.
    2.    پیچیدگی مدیریت کلیدها: مدیریت کلیدهای رمزنگاری نیازمند اقدامات امنیتی و تدابیر خاص است.

     

     

    کد کامل:

    برای این پروژه نیاز است پکیج های زیر را نصب کنید.

    Microsoft.EntityFrameworkCore
    Microsoft.EntityFrameworkCore.SqlServer
    Microsoft.EntityFrameworkCore.Tools

    و بعد دستورات زیر را در   Package Manager Console اجرا کنید تا دیتابیس  برای شما ایجاد شود.

    Add-Migration init
    Update-Database

    در اینجا هم کد کامل پروژه را مشاده می نمایید

    // See https://aka.ms/new-console-template for more information
    using Microsoft.EntityFrameworkCore;
    using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
    using System.Security.Cryptography;
    using System.Text;
    
    MyDbContext myDbContext = new MyDbContext();
    myDbContext.Add(new User
    {
         Email="info@bugeto.net",
         Name="Ehsan",
         LastName="Babaei",
         Password="123",
         PhoneNumber="09120000000"
    });
    
    myDbContext.SaveChanges();
    
     var firstUser=myDbContext.User.First();
    Console.WriteLine($"Name:{firstUser.Name}  {firstUser.LastName}");
    Console.WriteLine($"Email:{firstUser.Email}  ");
    Console.WriteLine($"PhoneNumber :{firstUser.PhoneNumber}  ");
    
    
    //-----------------------
    
    public class User
    {
        public int Id { get; set; }
        public string? Name { get; set; }
        public string? LastName { get; set; }
        public required string Email { get; set; }
        public string? PhoneNumber { get; set; }
        public required string Password { get; set; }
    }
    
    
    public class EncryptionService
    {
        private readonly string _encryptionKey = "your-secret-key";
    
    
    
        public string Encrypt(string input)
        {
            byte[] clearBytes = Encoding.Unicode.GetBytes(input);
            using (Aes encryptor = Aes.Create())
            {
                Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(_encryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
                encryptor.Key = pdb.GetBytes(32);
                encryptor.IV = pdb.GetBytes(16);
                using (MemoryStream ms = new MemoryStream())
                {
                    using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
                    {
                        cs.Write(clearBytes, 0, clearBytes.Length);
                        cs.Close();
                    }
                    input = Convert.ToBase64String(ms.ToArray());
                }
            }
            return input;
        }  
        
        public string Decrypt(string cipherText)
        {
            byte[] buffer = Convert.FromBase64String(cipherText);
    
            using (Aes aes = Aes.Create())
            {
                Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(_encryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
                aes.Key = pdb.GetBytes(32);
                aes.IV = pdb.GetBytes(16);
    
                ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
    
                using (MemoryStream memoryStream = new MemoryStream(buffer))
                {
                    using (CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
                    {
                        using (StreamReader streamReader = new StreamReader(cryptoStream))
                        {
                            return streamReader.ReadToEnd();
                        }
                    }
                }
            }
        }
    
    } 
    public class EncryptionConverter : ValueConverter<string, string>
    {
        public EncryptionConverter(EncryptionService encryptionService)
            : base(
                v => encryptionService.Encrypt(v),
                v => encryptionService.Decrypt(v))
        {
        }
    }
    
    public class MyDbContext : DbContext
    {
     
        public DbSet<User> User { get; set; }
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            if (!optionsBuilder.IsConfigured)
            {
                optionsBuilder.UseSqlServer("Server=.;Database=DB-EncryptSensitiveData; Integrated Security=True ;TrustServerCertificate=True");
            }
        }
    
        private readonly EncryptionService _encryptionService = new EncryptionService();
    
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            var encryptionConverter = new EncryptionConverter(_encryptionService);
    
            modelBuilder.Entity<User>()
                .Property(u => u.Email)
                .HasConversion(encryptionConverter);
    
            modelBuilder.Entity<User>()
                .Property(u => u.PhoneNumber)
                .HasConversion(encryptionConverter);
        }
    
    }
    
    
    
    

     

    معرفی دوره آموزشی:


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

     


    • نویسنده: احسان بابائی

    ارسال دیدگاه

    برای افزودن دیدگاه خود، نیاز است ابتدا وارد حساب کاربری‌تان شوید


    دیدگاه کاربران

    avatar
    morteza baya
    1402/11/15

    سلام . مرسی  بابت مقاله خوبتون، 
    این مورد رمزنگاری رو در identity  و روی فیلد های ایمیل و شماره موبایل روی جدول User میتونیم اعمال کنیم؟ مشکلی در استفاده از سرویس های usermanager و ... ایجاد نمیکنه ؟

    avatar
    پشتیبانی باگتو
    1402/11/24

    سلام بله، امکان رمزنگاری فیلدهای ایمیل و شماره تلفن در جدول کاربران (User) در Identity وجود دارد. با این حال، این کار چالش‌های خاصی را به همراه دارد، زیرا سرویس‌هایی مانند UserManager در ASP.NET Core Identity برای کار با این داده‌ها در حالت غیر رمزنگاری شده طراحی شده‌اند. بنابراین، در صورت رمزنگاری این فیلدها، باید مطمئن شوید که فرایندهای مرتبط با احراز هویت و مدیریت کاربر به درستی کار می‌کنند.


    avatar
    مرتضی
    1402/09/13

    عالی بود مهندس 

    avatar
    احسان بابائی
    1402/09/14

    زنده باشید🌹


    avatar
    Rohollah Hoseyni
    1402/09/10

    خیلی کاربردی و جامع

    avatar
    احسان بابائی
    1402/09/14

    تشکر جناب حسینی