تصور کن یه بانک اطلاعاتی داری پر از اطلاعات حساس کاربرانت؛ رمز عبور، شماره کارت، اطلاعات شخصی. حالا یه هکر موفق میشه به سرورت نفوذ کنه. اگه اطلاعاتت رمزنگاری نشده باشن، فاجعهای کامل رخ داده. اما اگه رمزنگاری درستی پیاده کرده باشی؟ هکر فقط یه سری کاراکتر بیمعنی میبینه.
رمزنگاری (Cryptography) در برنامهنویسی C# یکی از مهمترین مهارتهاییه که هر توسعهدهندهی حرفهای باید بلد باشه. در این راهنمای جامع، از مفاهیم پایه تا پیادهسازی عملی الگوریتمهای AES، RSA، SHA، HMAC و موارد بیشتر رو باهم یاد میگیریم.
قبل از اینکه بریم سراغ کد، باید چند مفهوم کلیدی رو بشناسیم:
دو نوع اصلی رمزنگاری داریم:
AES (Advanced Encryption Standard) امروزه استاندارد صنعتی رمزنگاری متقارنه و در پروژههای بانکی، نظامی و تجاری ازش استفاده میشه. در C# پیادهسازیش خیلی راحته.
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
public class AesEncryption
{
// رمزنگاری AES-256
public static string Encrypt(string plainText, string key)
{
using (Aes aes = Aes.Create())
{
aes.KeySize = 256;
aes.Key = DeriveKey(key, 32); // 256 bit
aes.GenerateIV();
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
using (var encryptor = aes.CreateEncryptor())
using (var ms = new MemoryStream())
{
// ذخیره IV در ابتدای خروجی
ms.Write(aes.IV, 0, aes.IV.Length);
using (var cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
using (var writer = new StreamWriter(cs, Encoding.UTF8))
{
writer.Write(plainText);
}
return Convert.ToBase64String(ms.ToArray());
}
}
}
// رمزگشایی AES-256
public static string Decrypt(string cipherText, string key)
{
byte[] fullCipher = Convert.FromBase64String(cipherText);
using (Aes aes = Aes.Create())
{
aes.KeySize = 256;
aes.Key = DeriveKey(key, 32);
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
// جداسازی IV از دادههای رمزشده
byte[] iv = new byte[16];
byte[] cipher = new byte[fullCipher.Length - 16];
Array.Copy(fullCipher, 0, iv, 0, 16);
Array.Copy(fullCipher, 16, cipher, 0, cipher.Length);
aes.IV = iv;
using (var decryptor = aes.CreateDecryptor())
using (var ms = new MemoryStream(cipher))
using (var cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
using (var reader = new StreamReader(cs, Encoding.UTF8))
{
return reader.ReadToEnd();
}
}
}
// تبدیل کلید متنی به بایت با PBKDF2
private static byte[] DeriveKey(string password, int keySize)
{
byte[] salt = Encoding.UTF8.GetBytes(“MySaltValue_1234”);
using var pbkdf2 = new Rfc2898DeriveBytes(
password, salt, 100_000, HashAlgorithmName.SHA256);
return pbkdf2.GetBytes(keySize);
}
}
// نحوه استفاده
class Program
{
static void Main()
{
string original = “اطلاعات محرمانه کاربر”;
string key = “MySecretKey@2024”;
string encrypted = AesEncryption.Encrypt(original, key);
string decrypted = AesEncryption.Decrypt(encrypted, key);
Console.WriteLine($“متن اصلی: {original}”);
Console.WriteLine($“رمزشده: {encrypted}”);
Console.WriteLine($“رمزگشایی شده: {decrypted}”);
}
}
نکته مهم: همیشه IV رو تصادفی تولید کن و همراه دادههای رمزشده ذخیرهاش کن. استفاده از IV ثابت یکی از رایجترین اشتباهات امنیتیه.
هشکردن (Hashing) یک عملیات یکطرفهست. یعنی نمیشه از هش به داده اصلی برگشت. این برای ذخیرهی رمز عبور ایدهآله.
using System;
using System.Security.Cryptography;
using System.Text;
public class HashingHelper
{
// هش SHA-256
public static string ComputeSHA256(string input)
{
using (SHA256 sha256 = SHA256.Create())
{
byte[] bytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(input));
return BitConverter.ToString(bytes).Replace(“-”, “”).ToLower();
}
}
// هش SHA-512
public static string ComputeSHA512(string input)
{
using (SHA512 sha512 = SHA512.Create())
{
byte[] bytes = sha512.ComputeHash(Encoding.UTF8.GetBytes(input));
return BitConverter.ToString(bytes).Replace(“-”, “”).ToLower();
}
}
// هش رمز عبور با Salt (روش صحیح!)
public static string HashPassword(string password)
{
// تولید Salt تصادفی 16 بایتی
byte[] salt = RandomNumberGenerator.GetBytes(16);
var pbkdf2 = new Rfc2898DeriveBytes(
password,
salt,
310_000, // تعداد تکرار توصیه شده توسط OWASP
HashAlgorithmName.SHA256);
byte[] hash = pbkdf2.GetBytes(32);
// ترکیب Salt + Hash برای ذخیرهسازی
byte[] combined = new byte[48];
Array.Copy(salt, 0, combined, 0, 16);
Array.Copy(hash, 0, combined, 16, 32);
return Convert.ToBase64String(combined);
}
// تایید رمز عبور
public static bool VerifyPassword(string password, string storedHash)
{
byte[] combined = Convert.FromBase64String(storedHash);
byte[] salt = new byte[16];
byte[] storedHashBytes = new byte[32];
Array.Copy(combined, 0, salt, 0, 16);
Array.Copy(combined, 16, storedHashBytes, 0, 32);
var pbkdf2 = new Rfc2898DeriveBytes(
password, salt, 310_000, HashAlgorithmName.SHA256);
byte[] hash = pbkdf2.GetBytes(32);
// مقایسهی امن (جلوگیری از Timing Attack)
return CryptographicOperations.FixedTimeEquals(hash, storedHashBytes);
}
}
هشدار امنیتی مهم: هرگز از MD5 یا SHA-1 برای هش رمز عبور استفاده نکن! این الگوریتمها قدیمی و شکسته شدن. از PBKDF2، bcrypt یا Argon2 استفاده کن.
RSA یکی از پرکاربردترین الگوریتمهای نامتقارنه. در ارتباطات SSL/TLS، امضای دیجیتال و تبادل کلید امن استفاده میشه.
using System;
using System.Security.Cryptography;
using System.Text;
public class RsaEncryption
{
// تولید جفت کلید RSA-2048
public static (string publicKey, string privateKey) GenerateKeys()
{
using (RSA rsa = RSA.Create(2048))
{
string publicKey = Convert.ToBase64String(
rsa.ExportRSAPublicKey());
string privateKey = Convert.ToBase64String(
rsa.ExportRSAPrivateKey());
return (publicKey, privateKey);
}
}
// رمزنگاری با کلید عمومی
public static string Encrypt(string plainText, string publicKeyBase64)
{
using (RSA rsa = RSA.Create())
{
rsa.ImportRSAPublicKey(
Convert.FromBase64String(publicKeyBase64), out _);
byte[] data = Encoding.UTF8.GetBytes(plainText);
byte[] encrypted = rsa.Encrypt(data, RSAEncryptionPadding.OaepSHA256);
return Convert.ToBase64String(encrypted);
}
}
// رمزگشایی با کلید خصوصی
public static string Decrypt(string cipherText, string privateKeyBase64)
{
using (RSA rsa = RSA.Create())
{
rsa.ImportRSAPrivateKey(
Convert.FromBase64String(privateKeyBase64), out _);
byte[] data = Convert.FromBase64String(cipherText);
byte[] decrypted = rsa.Decrypt(data, RSAEncryptionPadding.OaepSHA256);
return Encoding.UTF8.GetString(decrypted);
}
}
// امضای دیجیتال (Digital Signature)
public static string SignData(string data, string privateKeyBase64)
{
using (RSA rsa = RSA.Create())
{
rsa.ImportRSAPrivateKey(
Convert.FromBase64String(privateKeyBase64), out _);
byte[] dataBytes = Encoding.UTF8.GetBytes(data);
byte[] signature = rsa.SignData(
dataBytes,
HashAlgorithmName.SHA256,
RSASignaturePadding.Pkcs1);
return Convert.ToBase64String(signature);
}
}
// تایید امضا
public static bool VerifySignature(
string data, string signature, string publicKeyBase64)
{
using (RSA rsa = RSA.Create())
{
rsa.ImportRSAPublicKey(
Convert.FromBase64String(publicKeyBase64), out _);
byte[] dataBytes = Encoding.UTF8.GetBytes(data);
byte[] signatureBytes = Convert.FromBase64String(signature);
return rsa.VerifyData(
dataBytes,
signatureBytes,
HashAlgorithmName.SHA256,
RSASignaturePadding.Pkcs1);
}
}
}
HMAC (Hash-based Message Authentication Code) برای تایید صحت و اعتبار یک پیام استفاده میشه. اگه کسی پیام رو دستکاری کنه، HMAC دیگه مطابقت نداره.
using System;
using System.Security.Cryptography;
using System.Text;
public class HmacHelper
{
// تولید HMAC-SHA256
public static string GenerateHmac(string message, string secretKey)
{
byte[] keyBytes = Encoding.UTF8.GetBytes(secretKey);
byte[] messageBytes = Encoding.UTF8.GetBytes(message);
using (HMACSHA256 hmac = new HMACSHA256(keyBytes))
{
byte[] hash = hmac.ComputeHash(messageBytes);
return Convert.ToBase64String(hash);
}
}
// تایید HMAC
public static bool VerifyHmac(
string message, string secretKey, string expectedHmac)
{
string computedHmac = GenerateHmac(message, secretKey);
// مقایسه امن
return CryptographicOperations.FixedTimeEquals(
Convert.FromBase64String(computedHmac),
Convert.FromBase64String(expectedHmac));
}
}
وقتی محتوای فنی و تخصصی مثل این مقاله رو تولید میکنی، گوگل بهت اعتماد میکنه. اما اگه هیچکس این محتوا رو پیدا نکنه، چه فایدهای داره؟ سئوی حرفهای یعنی سرمایهگذاری مستقیم در فروش و درآمد سایتت.
سئوی سایت خود را به متخصصان ما بسپارید. همین حالا برای مشاوره رایگان با ما تماس بگیرید:
📞 09190994063 | 09376846692
برای پروژههای پیشرفتهتر، BouncyCastle یه کتابخانه قدرتمند رمزنگاری برای .NET هست که الگوریتمهای بیشتری مثل ChaCha20، AES-GCM و ECC رو پشتیبانی میکنه.
// نصب از NuGet:
// dotnet add package BouncyCastle.Cryptography
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
using System;
public class AesGcmEncryption
{
private const int NonceSize = 12; // 96 bits - استاندارد GCM
private const int TagSize = 16; // 128 bits
public static byte[] Encrypt(byte[] plaintext, byte[] key)
{
byte[] nonce = new byte[NonceSize];
new SecureRandom().NextBytes(nonce);
GcmBlockCipher cipher = new GcmBlockCipher(new AesEngine());
AeadParameters parameters = new AeadParameters(
new KeyParameter(key), TagSize * 8, nonce);
cipher.Init(true, parameters);
byte[] ciphertext = new byte[cipher.GetOutputSize(plaintext.Length)];
int len = cipher.ProcessBytes(plaintext, 0, plaintext.Length, ciphertext, 0);
cipher.DoFinal(ciphertext, len);
// ترکیب nonce + ciphertext
byte[] result = new byte[NonceSize + ciphertext.Length];
Array.Copy(nonce, 0, result, 0, NonceSize);
Array.Copy(ciphertext, 0, result, NonceSize, ciphertext.Length);
return result;
}
}
دانستن الگوریتمها کافی نیست. باید best practice ها رو هم رعایت کنی:
یکی از کاربردهای رایج رمزنگاری در پروژههای واقعی، رمزنگاری فایلهاست. اگه میخوای اسناد، تصاویر یا بکاپها رو رمزنگاری کنی:
using System;
using System.IO;
using System.Security.Cryptography;
public class FileEncryption
{
public static void EncryptFile(
string inputPath, string outputPath, string password)
{
byte[] salt = RandomNumberGenerator.GetBytes(16);
byte[] key = DeriveKey(password, salt, 32);
byte[] iv = RandomNumberGenerator.GetBytes(16);
using (FileStream output = new FileStream(
outputPath, FileMode.Create, FileAccess.Write))
{
// نوشتن Salt و IV در ابتدای فایل
output.Write(salt, 0, salt.Length);
output.Write(iv, 0, iv.Length);
using (Aes aes = Aes.Create())
{
aes.Key = key;
aes.IV = iv;
using (CryptoStream cs = new CryptoStream(
output, aes.CreateEncryptor(), CryptoStreamMode.Write))
using (FileStream input = new FileStream(
inputPath, FileMode.Open, FileAccess.Read))
{
input.CopyTo(cs);
}
}
}
}
public static void DecryptFile(
string inputPath, string outputPath, string password)
{
using (FileStream input = new FileStream(
inputPath, FileMode.Open, FileAccess.Read))
{
byte[] salt = new byte[16];
byte[] iv = new byte[16];
input.Read(salt, 0, 16);
input.Read(iv, 0, 16);
byte[] key = DeriveKey(password, salt, 32);
using (Aes aes = Aes.Create())
{
aes.Key = key;
aes.IV = iv;
using (CryptoStream cs = new CryptoStream(
input, aes.CreateDecryptor(), CryptoStreamMode.Read))
using (FileStream output = new FileStream(
outputPath, FileMode.Create, FileAccess.Write))
{
cs.CopyTo(output);
}
}
}
}
private static byte[] DeriveKey(string password, byte[] salt, int keySize)
{
using var pbkdf2 = new Rfc2898DeriveBytes(
password, salt, 310_000, HashAlgorithmName.SHA256);
return pbkdf2.GetBytes(keySize);
}
}
در نسخههای جدید .NET، کلاسها و روشهای بهتری اضافه شدن:
تولید محتوای تخصصی و باکیفیت مثل این مقاله، فقط یه قدم از مسیر طولانی سئوی حرفهایه. بدون یه استراتژی سئوی درست، حتی بهترین محتوا هم توی صفحات گوگل گم میشه. زنگخور سایتت رو چند برابر کن!
📞 برای مشاوره رایگان: 09190994063 | 09376846692
رمزنگاری یه عملیات دوطرفهست؛ یعنی میتونی داده رو رمزنگاری کنی و بعد با کلید صحیح، رمزگشاییاش کنی. اما هشکردن یکطرفهست و نمیشه از هش به داده اصلی برگشت. رمزنگاری برای ذخیرهی اطلاعاتی که بعداً باید بهشون دسترسی داشته باشی استفاده میشه، هشکردن برای تایید هویت (مثل رمز عبور) که نیازی به دیدن مقدار اصلی نداری.
AES-128 هم از نظر فنی بسیار امنه و تا به حال شکسته نشده. اما AES-256 استاندارد صنعتی توصیهشدهست، به خصوص برای دادههای حساس مثل اطلاعات مالی، پزشکی یا دولتی. تفاوت کارایی بین ۱۲۸ و ۲۵۶ بیتی در اکثر پروژهها قابل توجه نیست، پس همیشه AES-256 رو انتخاب کن.
هرگز کلید رو مستقیم در کد سورس ننویس! بهترین روشها به ترتیب اولویت: Azure Key Vault یا AWS KMS برای پروژههای ابری، Environment Variables برای پروژههای معمولی، User Secrets در محیط توسعه، و Windows Data Protection API (DPAPI) برای اپلیکیشنهای دسکتاپ. فایلهای کانفیگ رو هم در .gitignore قرار بده.
دو رویکرد اصلی وجود داره: رمزنگاری سمت اپلیکیشن (قبل از ذخیره در دیتابیس) که کنترل بیشتری بهت میده و توصیه میشه، یا Always Encrypted در SQL Server که رمزنگاری سطح ستون رو مستقیم در دیتابیس انجام میده. برای دادههای بسیار حساس مثل شماره کارت، Always Encrypted یا رمزنگاری سمت اپلیکیشن با AES-256 بهترین انتخابه.
AES-CBC فقط رمزنگاری انجام میده و نیاز به مکانیزم جداگانه برای تایید صحت داده داره. AES-GCM هم رمزنگاری میکنه هم یه تگ احراز هویت (Authentication Tag) تولید میکنه که از دستکاری داده جلوگیری میکنه. در .NET 8 کلاس AesGcm به صورت بیلتاین وجود داره. اگه نسخه جدید .NET داری، AES-GCM انتخاب بهتریه.
در اکثر پروژههای واقعی، تاثیر بر کارایی بسیار ناچیزه. AES یه الگوریتم بسیار سریعه و پردازندههای مدرن دستورالعملهای سختافزاری AES-NI دارن که سرعتش رو چند برابر میکنه. تنها جایی که ممکنه اثر قابل توجهی داشته باشه، رمزنگاری حجمهای بسیار بزرگ داده (چند گیگابایت) یا درخواستهای همزمان زیاد در سرورهاست که با استفاده از async/await قابل بهینهسازیه.
این مقاله نه تنها کدها رو آموزش داد، بلکه best practice ها رو هم پوشش داد که خیلی ارزشمنده. تفاوت MD5 و SHA-1 با PBKDF2 رو خوب روشن کردید.
هدف ما ارائه محتوای کامل شامل کدنویسی و بهترین شیوههای امنیتی است. ممنون از بازخورد سازنده شما. برای مشاوره در مورد سئوی محتواهای فنی با ما تماس بگیرید: 09190994063 | 09376846692
توضیح تفاوت CBC و GCM در AES خیلی مفید بود. اینکه GCM هم رمزنگاری و هم احراز هویت رو انجام میده، اونو به گزینه بهتری تبدیل میکنه. ممنون.
بله، AES-GCM به دلیل ارائه 'Authenticated Encryption with Associated Data' (AEAD) گزینه بسیار مطمئنتری است و توصیه میشود. خوشحالیم که توضیحات مفید بوده است. برای مشاوره تخصصی سئو با ما تماس بگیرید: 09190994063 | 09376846692
بخش هش کردن رمز عبور با Salt و PBKDF2 واقعا عالی بود. خیلیها هنوز از روشهای قدیمی و ناامن استفاده میکنند. تاکیدتون روی استفاده از FixedTimeEquals هم بسیار بجا بود.
ممنون از لطف شما. امنیت رمز عبور و جلوگیری از حملات Timing Attack از اهمیت بالایی برخوردار است. رعایت این نکات برای حفظ حریم خصوصی کاربران حیاتی است. برای اطلاعات بیشتر تماس بگیرید: 09190994063 | 09376846692
ممنون بابت این راهنمای کامل. آیا رمزنگاری دادهها روی کارایی اپلیکیشنهای C# در مقیاس بزرگ تأثیر منفی قابل توجهی داره؟
در اکثر موارد، تاثیر رمزنگاری بر کارایی ناچیز است؛ به خصوص با وجود دستورالعملهای سختافزاری AES-NI در پردازندههای مدرن. تنها در حجمهای بسیار زیاد داده ممکن است نیاز به بهینهسازیهایی مثل استفاده از async/await باشد. با ما تماس بگیرید: 09190994063 | 09376846692
نکته مربوط به ذخیره امن کلیدها در Key Vault خیلی مهم بود. آیا در پروژههای کوچکتر که به Key Vault دسترسی نداریم، راهکار امن دیگری برای ذخیره کلید وجود دارد؟
بله، برای پروژههای کوچکتر میتوانید از Environment Variables، User Secrets در محیط توسعه، و Windows Data Protection API (DPAPI) برای اپلیکیشنهای دسکتاپ استفاده کنید. برای راهنمایی بیشتر میتوانید با ما تماس بگیرید: 09190994063 | 09376846692
مثال رمزنگاری فایل با C# خیلی به دردم خورد. دقیقاً چیزی بود که دنبالش بودم برای بکاپهای رمزنگاری شده. ممنونم.
بسیار خوشحالیم که مثال رمزنگاری فایل برای شما کاربردی بوده است. امنیت فایلها و بکاپها از اهمیت بالایی برخوردار است. اگر سوال دیگری دارید، با ما تماس بگیرید: 09190994063 | 09376846692
مقاله بسیار جامع و کاربردی بود. به خصوص بخش AES و RSA که با مثال کد ارائه شده بود، واقعا مفید بود. ممنون از توضیحات کاملتون!
خوشحالیم که مقاله برای شما مفید بوده است. هدف ما ارائه محتوای کاربردی و جامع برای توسعهدهندگان عزیز است. با ما در تماس باشید: 09190994063 | 09376846692
همیشه برام سوال بود که آیا AES-128 کافیه یا باید حتماً از AES-256 استفاده کنم. ممنون از توضیحات شفافتون در FAQ. تصمیم گرفتم از این به بعد حتماً از 256 استفاده کنم.
خوشحالیم که ابهام شما برطرف شد. AES-256 به دلیل طول کلید بیشتر، سطح امنیتی بالاتری را فراهم میکند و برای دادههای حساس توصیه میشود. برای مشاوره تخصصی سئو با ما تماس بگیرید: 09190994063 | 09376846692
استفاده از BouncyCastle رو برای پروژههای پیشرفتهتر معرفی کردید. آیا برای پیادهسازی AES-GCM در .NET Framework قدیمیتر، BouncyCastle تنها گزینه مطمئنه؟
BouncyCastle یک کتابخانه بسیار قدرتمند و مطمئن برای پیادهسازی الگوریتمهای پیشرفته در .NET Framework های قدیمیتر است، زیرا بسیاری از این الگوریتمها به صورت native در نسخههای قدیمیتر .NET وجود ندارند. برای مشاوره بیشتر میتوانید با ما تماس بگیرید: 09190994063 | 09376846692
در بخش FAQ به Always Encrypted در SQL Server اشاره کردید. آیا استفاده از اون به تنهایی برای دادههای حساس مثل اطلاعات بانکی کافیه یا باید رمزنگاری سمت اپلیکیشن همزمان انجام بشه؟
Always Encrypted در SQL Server یک راهکار قوی برای رمزنگاری ستونی است. برای دادههای بسیار حساس، برخی سازمانها رویکرد دفاع عمقی (Defense in Depth) را ترجیح میدهند و علاوه بر Always Encrypted، رمزنگاری سمت اپلیکیشن را نیز پیادهسازی میکنند. برای مشاوره دقیقتر تماس بگیرید: 09190994063 | 09376846692
نکته مهم در مورد IV که همیشه باید تصادفی باشه و همراه داده ذخیره بشه، خیلی حیاتی بود. متاسفانه دیدم جاهایی که IV ثابت استفاده میکنند.
دقیقا همینطور است. استفاده از IV ثابت یکی از بزرگترین آسیبپذیریهای امنیتی در رمزنگاری متقارن است. ممنون از دقت شما. برای مشاوره در زمینه سئوی وبسایتتان، با ما تماس بگیرید: 09190994063 | 09376846692