PDA

View Full Version : آموزش: قفل کردن فایل ها با الگوریتم Rijndael



juza66
دوشنبه 22 مهر 1392, 07:54 صبح
سلام دوستان

نحوه قفل کردن فایل ها با الگوریتم Rijndael رو براي دوستان شرح ميدم البته با ذكر اينكه تمامي مطالب برگرفته از سايت c-sharp.ir (http://c-sharp.ir) هستش و بنده فقط به اشتراك ميذارم براي دوستان كه استفاده كنند.

با عرض سلام خدمت تمامی کاربران گرامی
بنا به درخواست هایی که خیلی از دوستان کرده بودند تصمیم گرفتم این مقاله را بنویسم.
در این مقاله قصد داریم مجموعه ای از فایل ها را در قالب یک فایل رمزگذاری شده در بیاوریم ، برای این کار از Serialization و Cryptography استفاده خواهیم کرد در نتیجه این مقاله میتواند یک مثال بسیار مفید برای استفاده از این دو مبحث باشد.
یک پروژه ی جدید بسازید و یک کلاس به نام Package به آن اضافه کنید.
این کلاس بسته ی رمزگذاری شده ی ما خواهد بود.
کد زیر را در آن بنویسید :


[Serializable()]
class Package
{
public List<byte[]> FilesData = new List<byte[]>();
public List FilesNames = new List();
}

توجه کنید که ما پراپرتی [Serializable()] را به کلاس داده ایم تا بتوانیم آنرا به مجموعه ای از بایت ها تبدیل کنیم.
از List برای ساخت یک آرایه با تعداد اعضای نامشخص استفاده میشود.
در خط اول کد ، بایت های فایل ها ذخیره میشوند و در خط دوم نام های آنها.
به فرم برگردید و قبل از هر چیز ، ابتدا فضای نامی System.IO را اضافه کنید.
سپس کد زیر را در رویداد Load فرم بنویسید :


OpenFileDialog o = new OpenFileDialog();
o.Multiselect = true;
if (o.ShowDialog() != DialogResult.OK)
return;
Package myPackage = new Package();
string[] files = o.FileNames;
for (int i = 0; i < files.Length; i++)
{
myPackage.FilesData.Add(File.ReadAllBytes(files[i]));
myPackage.FilesNames.Add(new FileInfo(files[i]).Name);
}

4 خط اول ، کدهای جدیدی نیستند ، در خط پنجم یک شئ از کلاس Package ساختیم و با استفاده از یک حلقه فایل هایی که کاربر انتخاب میکنید را در myPackage قرار داده ایم.
حال پکیج ما اماده است ، در ادامه باید آنرا به مجموعه ای از بایت ها تبدیل کنیم که این کار با استفاده از BinaryFormatter به راحتی امکان پذیر است.
ابتدا باید اسمبلی System.Runtime.Serialization.Formatters.Soap را اضافه کنید. برای این کار در Solution Explorer روی References راست کلیک کرده و در زبانه (تب) .Net آنرا پیدا کرده و اضافه کنید.
به کد برگردید و فضای نامی زیر را اضافه کنید.


using System.Runtime.Serialization.Formatters.Binary;


در ادامه کدهای موجود در رویداد Load فرم کدهای زیر را بنویسید :


BinaryFormatter formatter = new BinaryFormatter();
MemoryStream msPackage = new MemoryStream();
formatter.Serialize(msPackage, myPackage);

در خط اول از کلاس BinaryFormatter یک شئ ساختیم ، بدلیل این که متد Serialize کلاس BinaryFormatter یک Stream به عنوان آرگومان میخواهد ، در خط دوم کد یک شئ از کلاس MemoryStream ساختیم.
در خط سوم عملیات سریالیز myPackage را انجام داده ایم.
در ادامه باید عملیات رمزگذاری را انجام دهیم ، اینجاست که ممکن است بحث مشکل شود d:
فضای نامی System.Security.Cryptography را اضافه کنید و در ادامه ی کد رویداد Load کد زیر را بنویسید :


ASCIIEncoding encoder = new ASCIIEncoding();
RijndaelManaged cipher = new RijndaelManaged();
cipher.KeySize = 256;
cipher.Key = encoder.GetBytes("125sa652a2W65e23621w4Z89z4265g1t");
cipher.BlockSize = 256;
cipher.Mode = CipherMode.ECB;
cipher.Padding = PaddingMode.ISO10126;

در خط اول یک شئ از کلاس ASCIIEncoding ساخته ایم ، اگر پسورد شما کاراکترهای فارسی نیز داشته باشد میتوانید از UTF8Encoding استفاده کنید.
در خط دوم الگوریتم رمزنگاری ریندال (Rijndael) را که یک الگوریتم رمزنگاری قدرتمند و استاندارد است انتخاب کرده ایم.
این الگوریتم یک الگوریتم متقارن (Symmetric) است و داده ها را با استفاده از یک کلید (Key) رمز گذاری میکند.
اندازه ی این کلید را 256 بیت یعنی 32 کاراکتر تک بایتی اختیار کردیم.
در خط بعد کلید را که بصورت رشته (String) است به بایت تبدیل و به cipher داده ایم.
این الگوریتم داده ها را به بخش های هم اندازه تقسیم میکنید و عملیات رمزگذاری را روی هرکدام از این بخش ها انجام میدهد.
سایز هر کدام از این بخش ها را 256 بیت در نظر گرفته ایم.
در خط بعد روش رمزنگاری را ECB انتخاب کرده ایم ، بدان معنی که هر بخش بصورت مجزا رمزگذاری شود.
اگر CBC را اختیار میکردیم ، برای رمزگذاری هر بخش به یک ورودی دیگر نیز احتیاج داشتیم که این ورودی از نتیجه ی بخش قبلی حاصل میشود.
اما چون بخش اول داده ها ورودی ندارد باید آنرا دستی به الگوریتم بدهیم که Intalivation Vector ( IV) نام دارد.
همان طور که گفتم الگوریتم داده ها را به بخش هایی هم اندازه که در مثال ما 256 بیت (32 بایت) تقسیم میکند ، اما در این حالت یک مشکل به وجود می آید ، آیا همیشه داده های ما ضریبی از این عدد هستند؟
ممکن است در بلاک آخر تعداد بیت ها به 256 نرسد.
در خط آخر این مشکل را حل کرده ایم ، به الگوریتم گفته ایم که در بلاک آخر داده های تصادفی قرار دهد.
و در ادامه :


ICryptoTransform crypto = cipher.CreateEncryptor();
byte[] uncryptedPackage = msPackage.GetBuffer();
byte[] cryptedPackage = crypto.TransformFinalBlock(uncryptedPackage, 0, uncryptedPackage.Length);
SaveFileDialog s = new SaveFileDialog();
s.Filter = "Secure Package (*.spk)|*.spk";
if (s.ShowDialog() == DialogResult.OK)
File.WriteAllBytes(s.FileName, cryptedPackage);


در خط اول یک شئ بهتر است بگیم از اینترفیس ICryptoTransform با استفاده از متد CreateEncryptor ساخته ایم تا عملیات نهایی اینکریپشن را انجام دهد.
در خط دوم بایت های پکیج اصلی را برای راحتی کار در یک آرایه قرار داده ایم.
سپس عملیات نهایی را در خط سوم و با استفاده از متد TransformFinalBlock انجام داده ایم و در نهایت آنرا در یک فایل خروجی ذخیره کرده ایم.
توجه کنید که برای انجام عملیات رمزنگاری روی فایل ها میتوانید از CryptoStream نیز استفاده کنید ، هدفم از استفاده از ICryptoTransform این است که بتوانید در جاهای مختلف از آن استفاده کنید نه فقط روی فایل ها.
حال وقت آن است که عملیات بالا را به شکل معکوس طی کنیم تا فایل ها را از یک پکیج رمزگذاری شده استخراج کنیم.
یک دکمه روی فرم قرار دهید و روی آن دابل کلیک کنید تا رویداد Click آن ساخته شود و کد زیر را در آن بنویسید.


OpenFileDialog o = new OpenFileDialog();
o.Multiselect = false;
o.Filter = "Secure Package (*.spk)|*.spk";
if (o.ShowDialog() != DialogResult.OK)
return;
byte[] cryptedPackage = File.ReadAllBytes(o.FileName);

تنها کاری که در کدهای بالا کرده ایم این است که بایت های پکیج رمزگذاری شده را خوانده و در آرایه cryptedPackage قرار دادیم.
حال مانند کدهای قبل یک شئ از کلاس RijndaelManaged میسازیم و آنرا تنظیم میکنیم.


ASCIIEncoding encoder = new ASCIIEncoding();
RijndaelManaged cipher = new RijndaelManaged();
cipher.KeySize = 256;
cipher.Key = encoder.GetBytes("125sa652a2W65e23621w4Z89z4265g1t");
cipher.BlockSize = 256;
cipher.Mode = CipherMode.ECB;
cipher.Padding = PaddingMode.ISO10126;

در زیر بایت های پکیج اصلی را بدست می آوریم :


ICryptoTransform crypto = cipher.CreateDecryptor();
byte[] uncryptedPackage = crypto.TransformFinalBlock(cryptedPackage, 0, cryptedPackage.Length);


توجه کنید که این بار از متد CreateDecryptor استفاده میکنیم.
و در نهایت بایت های پکیج را به خود پکیج با استفاده از BinaryFormatter تبدیل میکنیم.


BinaryFormatter formatter = new BinaryFormatter();
MemoryStream msPackage = new MemoryStream(uncryptedPackage);
Package myPackage = (Package)formatter.Deserialize(msPackage);

این بار نیز از متد Deserialize استفاده میکنیم که خروجی object دارد ، آنرا به Package کست میکنیم.
در نهایت فایل های پکیج را استخراج میکنیم :


FolderBrowserDialog fb = new FolderBrowserDialog();
if (fb.ShowDialog() == DialogResult.OK)
{
for (int i = 0; i < myPackage.FilesNames.Count; i++)
File.WriteAllBytes(fb.SelectedPath + "\\" + myPackage.FilesNames[i], myPackage.FilesData[i]);
}

و کارمان تمام شد تبریک میگم ، چیزی در حد WinRar نوشتید ، البته بدون بخش فشرده سازی d:
خوشبختانه الگوریتم های متقارن بسیار سریع عمل میکنند و میتوان از آنها در رمزگذاری داده های بزرگ استفاده کرد.
اگر از این الگوریتم برای امنیت پایگاه داده استفاده میکنید ، بدلیل این که در حالت عادی که های دات نت به راحتی دیکد میشوند بهتر است رمز (کلید) را بصورت صریح در کد ننویسید.
نکته ی دیگر این است که درصورتی که کلید اشتباه باشد ، کد خطا میدهد ، پس بهتر است برای عملیات بازیابی فایل ها از بلاک Try-Catch استفاده کنید.

میتونید پروژه ی کامل را دانلود کنید.
با آرزوی موفقیت همیشه ، خدا نگهدار


Download - دانلود (http://www.mediafire.com/download/6vuce1bq8zcr5we/Secure+Package+Maker.rar)

systam
دوشنبه 22 مهر 1392, 16:16 عصر
سلام
کاره جالبیه بدردم میخوره

فقط یه مشکلی داره برای خارج کردن فایلی به صورت دست چین
نمیشه فایل مورد نظر نمیشه extract کردن همه فایل یکجا با هم extract کرد

juza66
سه شنبه 23 مهر 1392, 07:19 صبح
فعلاً رو Extract كردن همه فايل ها كار شده ان شاا.. در ادامه مطلب به Extract كردن فايل خاصي اشاره خواهم كرد