آموزش رمزگذاری و رمزگشایی در زبان سی شارپ
منظور از رمزگذاری (Encryption) فرآیندی است که طی آن اطلاعات مهم با استفاده از یک یا چند الگوریتم خاص به شکل دیگری تبدیل می شوند. در رمزگذاری داده ها معمولا از یک کلید برای رمزگذاری و رمزگشایی استفاده می شود. همانطور که احتمالا می دانید، رمزگذاری داده ها کار ساده ای نیست که هر کسی بتواند برای خودش یک الگوریتم رمزگذاری ایجاد کند. بنابراین بهتر است به منظور حفظ امنیت داده ها از الگوریتم هایی که توسط مختصصان این زمینه ایجاد شده اند استفاده کنیم.
در مبحث رمزگذاری دو روش مهم وجود دارد که عبارت اند از: رمزگذاری متقارن و رمزگذاری نامتقارن. رمزگذاری متقارن و نامتقارن فرآیندهای مختلفی را به منظور کدگذاری داده ها انجام می دهند. رمزگذاری متقارن بر روی Stream انجام می شود و بنابراین می تواند برای رمزگذاری مقدار زیادی از داده ها استفاده شود. اما رمزگذاری نامتقارن بر روی تعداد کمی از بایت ها اعمال می شود، در نتیجه برای رمزگذاری داده هایی با مقدار کم مورد استفاده قرار می گیرد.
رمزگذاری متقارن
کلاس های رمزنگاری متقارن کنترل شده به همراه یک کلاس Stream ویژه به نام CryptoStream استفاده می شوند که داده ها رمزگذاری شده در آن Stream نوشته می شوند. کلاس CryptoStream با یک کلاس مدیریت شده از نوع Stream، یک کلاس پیاده سازی شده بر اساس اینترفیس ICryptoTransform و یک enum از نوع CryptoStreamMode که شکل دسترسی به CryptoStream را توصیف می کند مقداردهی اولیه می شود. کلاس CryptoStream می تواند با هر کلاسی که از کلاس Stream ارث بری می کند (مانند FileStream، MemoryStream و NetworkStream)، مقداردهی اولیه شود. با استفاده از این کلاس می توانید انواع مختلف شیء هایی که از نوع Stream هستند را رمزگذاری کنید.
رمزگذاری نامتقارن
الگوریتم های نامتقارن منابع زیادی را به منظور انجام عملیات رمزگذاری بر روی داده ها نیاز دارند و این موضوع باعث می شود تا امنیت آن نیز افزایش یابد. در این نوع الگوریتم ها هر چه طول کلید بیشتر باشد، امنیت داده رمزگذاری شده نیز افزایش می یابد. رمزگذاری نامتقارن در مواردی خاص مورد استفاده قرار می گیرند (مثلا برای Authentication). به همین دلیل نمی توان از آن برای رمزگذاری های داده هایی با اندازه زیاد استفاده کرد. به طور معمول طول کلیدهای استفاده شده در الگوریتم ها نامتقارن بین ۲۰۴۸ تا ۴۰۹۶ می باشد.
الگوریتم های نامتقارن معمولا برای رمزگذاری مقادیر کوچک داده ها استفاده می شود. به طور معمول، شخصی که رمزگذاری نامتقارن را انجام می دهد، از کلید عمومی تولید شده توسط یک طرف دیگر استفاده می کند. در فریم ورک .Net کلاس RSACryptoServiceProvider برای این منظور ایجاد شده است.
مثالی از الگوریتم AES در زبان سی شارپ
مثال زیر نحوه رمزگذاری متن و فایل با استفاده از الگوریتم رمزگذاری متقارن AES در زبان سی شارپ را نشان می دهد. ظاهر مثال زیر شامل موارد زیر است:
کنترل | نام | متن |
TextBox | TxtPassword | |
TextBox | TxtPlainText | |
TextBox | TxtEncryptedText | |
TextBox | TxtDecryptedText | |
TextBox | TxtOriginalFilePath | |
TextBox | TxtEncryptedFilePath | |
Button | BtnEncryptText | رمزگذاری متن |
Button | BtnDecryptText | رمزگشایی متن |
Button | BtnBrowseOriginalFile | . . . |
Button | BtbBrowseEncryptedFile | . . . |
Button | BtnEncryptFile | رمزگذاری فایل |
Button | BtnDecryptFile | رمزگشایی فایل |
تصویری از ظاهر برنامه:
به منظور انجام عملیات رمزگذاری و رمزگشایی یک کلاس با نام Cryptography ایجاد کنید و کد زیر را در آن بنویسید:
کدهای فایل AesCryptography.cs
using System; using System.IO; using System.Security.Cryptography; using System.Text; namespace CSharpAesCryptography { public static class AesCryptography { /// <summary> /// برای رمزگذاری بایت ها استفاده می شود /// </summary> /// <param name="bytesToEncrypted">بایت های فایل یا متنی که باید رمزگذاری شود</param> /// <param name="passwordBytes">بایت های رشته ایی که به عنوان پسورد وارد شده است</param> /// <returns>آرایه ای از بایت ها</returns> private static byte[] AesEncrypt(byte[] bytesToEncrypted, byte[] passwordBytes) { byte[] encryptedBytes; var saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 }; using (var memoryStream = new MemoryStream()) { using (var aes = new RijndaelManaged()) { aes.KeySize = 256; aes.BlockSize = 128; var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000); aes.Key = key.GetBytes(aes.KeySize / 8); aes.IV = key.GetBytes(aes.BlockSize / 8); aes.Mode = CipherMode.CBC; using (var cs = new CryptoStream(memoryStream, aes.CreateEncryptor(), CryptoStreamMode.Write)) { cs.Write(bytesToEncrypted, 0, bytesToEncrypted.Length); cs.Close(); } encryptedBytes = memoryStream.ToArray(); } } return encryptedBytes; } /// <summary> /// برای رمزگشایی بایت ها استفاده می شود /// </summary> /// <param name="bytesToDecrypted">بایت های فایل یا متنی که باید رمزگشایی شود</param> /// <param name="passwordBytes">بایت های رشته ایی که به عنوان پسورد وارد شده است</param> /// <returns>آرایه ای از بایت ها</returns> private static byte[] AesDecrypt(byte[] bytesToDecrypted, byte[] passwordBytes) { byte[] decryptedBytes; var saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 }; using (var memoryStream = new MemoryStream()) { using (var aes = new RijndaelManaged()) { aes.KeySize = 256; aes.BlockSize = 128; var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000); aes.Key = key.GetBytes(aes.KeySize / 8); aes.IV = key.GetBytes(aes.BlockSize / 8); aes.Mode = CipherMode.CBC; using (var cs = new CryptoStream(memoryStream, aes.CreateDecryptor(), CryptoStreamMode.Write)) { cs.Write(bytesToDecrypted, 0, bytesToDecrypted.Length); cs.Close(); } decryptedBytes = memoryStream.ToArray(); } } return decryptedBytes; } /// <summary> /// برای رمزگذاری متن استفاده می شود /// </summary> /// <param name="input">متنی که باید رمزگذاری شود</param> /// <param name="password">پسوردی که متن ورودی بر اساس آن رمزگذاری می شود</param> /// <returns></returns> public static string EncryptText(string input, string password) { // بررسی آرگومان ها if (string.IsNullOrEmpty(input)) throw new ArgumentNullException(nameof(input)); if (string.IsNullOrEmpty(password)) throw new ArgumentNullException(nameof(password)); // تبدیل متن ورودی به آرایه ای از بایت var bytesToEncrypted = Encoding.UTF8.GetBytes(input); // تبدیل پسورد به آرایه ای از بایت var passwordBytes = Encoding.UTF8.GetBytes(password); // Hash کردن بایت های پسورد passwordBytes = SHA256.Create().ComputeHash(passwordBytes); // رمزگذاری بایت های متن ورودی بر اساس پسورد با استفاده از متد AesEcrypt var bytesEncrypted = AesEncrypt(bytesToEncrypted, passwordBytes); // تبدیل خروجی متد AesEcrypt به رشته var result = Convert.ToBase64String(bytesEncrypted); // بازگردانی متن رمزگذاری شده return result; } /// <summary> /// برای رمزگشایی متن استفاده می شود /// </summary> /// <param name="input">متن رمزگذاری شده با استفاده از متد EncryptText</param> /// <param name="password">پسوردی که متن ورودی بر اساس آن رمزگشایی می شود</param> /// <returns></returns> public static string DecryptText(string input, string password) { // بررسی آرگومان ها if (string.IsNullOrEmpty(input)) throw new ArgumentNullException(nameof(input)); if (string.IsNullOrEmpty(password)) throw new ArgumentNullException(nameof(password)); // تبدیل متن ورودی به آرایه ای از بایت ها var bytesToDecrypted = Convert.FromBase64String(input); // تبدیل پسورد به آرایه ای از بایت هد var passwordBytes = Encoding.UTF8.GetBytes(password); // تبدیل بایت های پسورد به Hash passwordBytes = SHA256.Create().ComputeHash(passwordBytes); // رمزگشایی بایت های متن رمزگذاری شده بر اساس پسورد با استفاده از متد AesDecrypt var bytesDecrypted = AesDecrypt(bytesToDecrypted, passwordBytes); // تبدیل خروجی متد AesDecrypt به رشته var result = Encoding.UTF8.GetString(bytesDecrypted); // بازگردانی متن رمزگشایی شده return result; } /// <summary> /// برای رمزگذاری فایل استفاده می شود /// </summary> /// <param name="filePath">آدرس فایلی که باید رمزگذاری شود</param> /// <param name="password">پسوردی که فایل باید بر اساس آن رمزگذاری می شود</param> public static void EncryptFile(string filePath, string password) { // بررسی آرگومان ها if (string.IsNullOrEmpty(filePath)) throw new ArgumentNullException(nameof(filePath)); if (string.IsNullOrEmpty(password)) throw new ArgumentNullException(nameof(password)); // گرفتن کل بایت های فایل var bytesToEncrypted = File.ReadAllBytes(filePath); // تبدیل پسورد به آرایه ای از بایت ها var passwordBytes = Encoding.UTF8.GetBytes(password); // تبدیل بایت های پسورد به Hash passwordBytes = SHA256.Create().ComputeHash(passwordBytes); // رمزگذاری بایت های فایل با استفاده از متد AesEncrypt var bytesEncrypted = AesEncrypt(bytesToEncrypted, passwordBytes); // نوشتن بایت ها رمزگذاری شده درون فایل File.WriteAllBytes(filePath, bytesEncrypted); } /// <summary> /// برای رمزگشایی فایل استفاده می شود /// </summary> /// <param name="filePath">آدرس فایل رمزگذاری شده با متد EncryptFile</param> /// <param name="password">پسوردی که فایل باید بر اساس آن رمزگشایی می شود</param> public static void DecryptFile(string filePath, string password) { // بررسی آرگومان ها if (string.IsNullOrEmpty(filePath)) throw new ArgumentNullException(nameof(filePath)); if (string.IsNullOrEmpty(password)) throw new ArgumentNullException(nameof(password)); // گرفتن کل بایت های فایل var bytesToDecrypted = File.ReadAllBytes(filePath); // تبدیل پسورد به آرایه ای از بایت ها var passwordBytes = Encoding.UTF8.GetBytes(password); // تبدیل بایت های پسورد به Hash passwordBytes = SHA256.Create().ComputeHash(passwordBytes); // رمزگشایی بایت های فایل با استفاده از متد AesDecrypt var bytesDecrypted = AesDecrypt(bytesToDecrypted, passwordBytes); // نوشتن بایت ها رمزگشایی شده درون فایل File.WriteAllBytes(filePath, bytesDecrypted); } } }
کدهای فایل Form1.cs
using System; using System.Threading.Tasks; using System.Windows.Forms; using CSharpAesCryptography; namespace CSharpAESCryptography { public partial class Form1 : Form { public Form1() { InitializeComponent(); } /// <summary> /// انتخاب فایل با استفاده از کلاس OpenFileDialog /// </summary> /// <param name="toDecrypt">مشخص می کنه که آیا فایل برای رمزگذاری انتخاب می شود یا رمزگشایی</param> private void SelectFile(bool toDecrypt = false) { using (var fileDialog = new OpenFileDialog()) { if (fileDialog.ShowDialog() != DialogResult.OK) return; if (toDecrypt) TxtEncryptedFilePath.Text = fileDialog.FileName; else TxtOriginalFilePath.Text = fileDialog.FileName; } } private void BtnEncryptText_Click(object sender, EventArgs e) { try { var input = TxtPlainText.Text; var password = TxtPassword.Text; var result = AesCryptography.EncryptText(input, password); TxtEncryptedText.Text = result; } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void BtnDecryptText_Click(object sender, EventArgs e) { try { var input = TxtEncryptedText.Text; var password = TxtPassword.Text; var result = AesCryptography.DecryptText(input, password); TxtDecryptedText.Text = result; } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void BtnBrowseOriginalFile_Click(object sender, EventArgs e) { SelectFile(); } private void BtbBrowseEncryptedFile_Click(object sender, EventArgs e) { SelectFile(true); } private async void BtnEncryptFile_Click(object sender, EventArgs e) { try { var mainTitle = Text; Text = @"در حال رمزگذاری فایل ..."; var filePath = TxtOriginalFilePath.Text; var password = TxtPassword.Text; // برای آن که برنامه در هنگام عملیات رمزگذاری قفل نشود // متد زیر را با استفاده از Task فراخوانی می کنیم await Task.Run(() => AesCryptography.EncryptFile(filePath, password)); Text = mainTitle; MessageBox.Show(@"Done"); } catch (Exception ex) { MessageBox.Show(ex.Message); } } private async void BtnDecryptFile_Click(object sender, EventArgs e) { try { var mainTitle = Text; Text = @"در حال رمزگشایی فایل ..."; var filePath = TxtEncryptedFilePath.Text; var password = TxtPassword.Text; // برای آن که برنامه در هنگام عملیات رمزگشایی قفل نشود // متد زیر را با استفاده از Task فراخوانی می کنیم await Task.Run(() => AesCryptography.DecryptFile(filePath, password)); Text = mainTitle; MessageBox.Show(@"Done"); } catch (Exception ex) { MessageBox.Show(ex.Message); } } } }
مثالی از الگوریتم RSA در زبان سی شارپ
مثال زیر نحوه رمزگذاری متن با استفاده از الگوریتم رمزگذاری نامتقارن RSA را نشان می دهد. ظاهر مثال زیر شامل موارد زیر است:
کنترل | نام | متن |
TextBox | TxtPlainText | |
TextBox | TxtEncryptedText | |
TextBox | TxtDecrytedText | |
Button | BtnEncrypt | رمزگذاری |
Button | BtnDecrypt | رمزگشایی |
تصویری از ظاهر برنامه:
به منظور انجام عملیات رمزگذاری و رمزگشایی یک کلاس با نام Cryptography ایجاد کنید و کد زیر را در آن بنویسید:
کدهای فایل RsaCryptography.cs
using System; using System.IO; using System.Security.Cryptography; using System.Text; using System.Xml.Serialization; namespace CSharpRSACryptography { public static class RsaCryptography { public static string GetKeyString(RSAParameters publicKey) { var stringWriter = new StringWriter(); var xmlSerializer = new XmlSerializer(typeof(RSAParameters)); xmlSerializer.Serialize(stringWriter, publicKey); return stringWriter.ToString(); } public static string Encrypt(string input, string publicKeyString) { var bytesToEncrypt = Encoding.UTF8.GetBytes(input); using (var rsa = new RSACryptoServiceProvider(2048)) { try { rsa.FromXmlString(publicKeyString); var encryptedData = rsa.Encrypt(bytesToEncrypt, true); var base64Encrypted = Convert.ToBase64String(encryptedData); return base64Encrypted; } finally { rsa.PersistKeyInCsp = false; } } } public static string Decrypt(string input, string privateKeyString) { using (var rsa = new RSACryptoServiceProvider(2048)) { try { rsa.FromXmlString(privateKeyString); var resultBytes = Convert.FromBase64String(input); var decryptedBytes = rsa.Decrypt(resultBytes, true); var decryptedData = Encoding.UTF8.GetString(decryptedBytes); return decryptedData; } finally { rsa.PersistKeyInCsp = false; } } } } }
محتوای فایل Form1.cs
using System; using System.Security.Cryptography; using System.Windows.Forms; namespace CSharpRSACryptography { public partial class Form1 : Form { private readonly RSACryptoServiceProvider _cryptoServiceProvider; public Form1() { InitializeComponent(); _cryptoServiceProvider = new RSACryptoServiceProvider(2048); } private void BtnEncrypt_Click(object sender, EventArgs e) { // تولید کلید عمومی var publicKey = _cryptoServiceProvider.ExportParameters(false); // تبدیل کلید به رشته var publicKeyString = RsaCryptography.GetKeyString(publicKey); // رمزگذاری متن ساده var result = RsaCryptography.Encrypt(TxtPlainText.Text, publicKeyString); // نمایش متن رمزگذاری شده TxtEncryptedText.Text = result; } private void BtnDecrypt_Click(object sender, EventArgs e) { // تولید کلید خصوصی var privateKey = _cryptoServiceProvider.ExportParameters(true); // تبدیل کلید به رشته var privateKeyString = RsaCryptography.GetKeyString(privateKey); // رمزگشایی متن رمزگذاری شده var result = RsaCryptography.Decrypt(TxtEncryptedText.Text, privateKeyString); // نمایش متن رمزگشایی شده TxtDecrytedText.Text = result; } } }
نوشته آموزش رمزگذاری (Encryption) و رمزگشایی (Decryption) در زبان سی شارپ اولین بار در سورس سرا - آموزش برنامه نویسی. پدیدار شد.