09-03-16, 12:36 AM
(07-03-16, 02:36 PM)silverlight كتب : كما وعدتك سابقاشكرا اخي الكريم على المجهود الجبار والتوضيح الهائل وادعو الله ان يجعلها لك في ميزلن الحسنات
عليك أن تضيف الكلاسات التالية الي مشروعك
الكلاس الأول يعبر عن المدخلات الخاصة بكل رابط
PHP كود :
Public Class AssetInfo
Public Index As String
Public UriString As String
End Class
الكلاس الثاني هو الكلاس المسئول عن تشقير المدخلات قبل حفظها في الملف ثم يقوم بإلغاء التشفير أثناء قراءة البيانات من الملف
PHP كود :
Imports System.IO
Imports System.Security.Cryptography
Imports System.Text
Friend NotInheritable Class AssetObfuscation
Public Shared Function Obfuscate(value As String, guard As String) As String
Dim salt = CalculateKeyGuard(guard)
Dim rgbIV = CalculateKeyGuard(guard)
Dim bytes = Encoding.UTF8.GetBytes(value)
Using rfc = New Rfc2898DeriveBytes(guard, salt, 1000)
Dim rgbKey = rfc.GetBytes(256 \ 8)
Using sk = New RijndaelManaged()
sk.BlockSize = 256
sk.Mode = CipherMode.CBC
sk.Padding = PaddingMode.PKCS7
Using encryptor = sk.CreateEncryptor(rgbKey, rgbIV)
Using ms = New MemoryStream()
Using cs = New CryptoStream(ms, encryptor, CryptoStreamMode.Write)
cs.Write(bytes, 0, bytes.Length)
cs.FlushFinalBlock()
Dim buffer = salt
buffer = buffer.Concat(rgbIV).ToArray()
buffer = buffer.Concat(ms.ToArray()).ToArray()
ms.Close()
cs.Close()
Return Convert.ToBase64String(buffer)
End Using
End Using
End Using
End Using
End Using
End Function
Public Shared Function DeObfuscate(hash As String, guard As String) As String
Dim bytes = Convert.FromBase64String(hash)
Dim salt = bytes.Take(256 \ 8).ToArray()
Dim rgbIV = bytes.Skip(256 \ 8).Take(256 \ 8).ToArray()
Dim buffer = bytes.Skip((256 \ 8) * 2).Take(bytes.Length - ((256 \ 8) * 2)).ToArray()
Using rfc = New Rfc2898DeriveBytes(guard, salt, 1000)
Dim rgbKey = rfc.GetBytes(256 \ 8)
Using sk = New RijndaelManaged()
sk.BlockSize = 256
sk.Mode = CipherMode.CBC
sk.Padding = PaddingMode.PKCS7
Using decryptor = sk.CreateDecryptor(rgbKey, rgbIV)
Using ms = New MemoryStream(buffer)
Using cs = New CryptoStream(ms, decryptor, CryptoStreamMode.Read)
Dim buffers = New Byte(buffer.Length - 1) {}
Dim count = cs.Read(buffers, 0, buffers.Length)
ms.Close()
cs.Close()
Return Encoding.UTF8.GetString(buffers, 0, count)
End Using
End Using
End Using
End Using
End Using
End Function
Private Shared Function CalculateKeyGuard(value As String) As Byte()
Dim result As Byte() = CType(Nothing, Byte())
Using hash As HashAlgorithm = New SHA256CryptoServiceProvider()
Dim bytes As Byte() = Encoding.UTF8.GetBytes(value)
result = hash.ComputeHash(bytes)
End Using
Return result
End Function
End Class
الكلاس الثالث هو مجرد كلاس مساعد يمكنك اسخدامه إن أردت للتأكد من أن المدخلات عبارة عن روابط و في واقع الأمر أنا لم أستخدمه داخل الكود و تركت الأمر لك أنت لتقرر هل عليك أن تتأكد من أن المدخلات عبارة عن روابط أم لا
PHP كود :
Friend NotInheritable Class AssetsValidator
Private Shared Function IsValidHttp(value As Uri) As Boolean
Return value.Scheme.Equals("http", StringComparison.OrdinalIgnoreCase) OrElse value.Scheme.Equals("https", StringComparison.OrdinalIgnoreCase)
End Function
Friend Shared Function IsValidHttpOrNull(value As Uri) As Boolean
Return value IsNot Nothing AndAlso IsValidHttp(value)
End Function
End Class
الكلاس الرابع هو الكلاس الرئيسي والمسئول عن عملية حفظ البيانات في ملف وأيضا مسئول عن قراءة البيانات من الملف
و هنا عملية الحفظ تتم علي صورة مصفوفة وبالتبعية يتم قراءة و استرجاع البيانات من الملف علي هيئة مصفوفة أيضا
أنا استخدمت كلة سر لحفظ البيانات يمكنك أن تغيرها إن أردت و أيضا الملف يتم حفظه في فهرس المشروع و هذا ايضا يمكنك ان تغيره و أيضا استخدمت نفس كلمة السر لللتشفير و إلغاء التشفير و هذا ايضا يمكنك تغييره إن أردت
PHP كود :
Imports System.Text
Public Class AssetContext
Private Const DataProtector As String = "12345"
Private Const DataFileName As String = ".\assets.dat"
Private Shared characterEncoding As Encoding
Private Shared lock As Object = New Object
Private Shared context As AssetContext
Public Shared ReadOnly Property Instance As AssetContext
Get
Dim result As AssetContext = CType(Nothing, AssetContext)
SyncLock lock
If context Is Nothing Then
context = New AssetContext
End If
result = context
End SyncLock
Return result
End Get
End Property
Friend Function Write(list As List(Of AssetInfo)) As Boolean
Return Write(list, DataFileName, DataProtector)
End Function
Friend Function Write(list As List(Of AssetInfo), filename As String, guard As String) As Boolean
If characterEncoding Is Nothing Then
Dim encoder As Encoding = CType(Encoding.UTF8.Clone(), Encoding)
encoder.EncoderFallback = EncoderFallback.ReplacementFallback
characterEncoding = encoder
End If
Using writer As New System.IO.BinaryWriter(System.IO.File.Open(filename, System.IO.FileMode.Create), characterEncoding)
writer.Write(AssetObfuscation.Obfuscate(guard, guard))
writer.Write(list.Count)
For Each current As AssetInfo In list
writer.Write(AssetObfuscation.Obfuscate(current.Index, guard))
writer.Write(AssetObfuscation.Obfuscate(current.UriString, guard))
Next
Return True
End Using
Return False
End Function
Friend Function Read() As List(Of AssetInfo)
Return Read(DataFileName, DataProtector)
End Function
Friend Function Read(filename As String, guard As String) As List(Of AssetInfo)
Dim assets As List(Of AssetInfo) = CType(Nothing, List(Of AssetInfo))
If (System.IO.File.Exists(filename)) Then
Using reader As New System.IO.BinaryReader(System.IO.File.Open(filename, System.IO.FileMode.Open), New System.Text.UTF8Encoding(False, False))
Dim protection As String = AssetObfuscation.DeObfuscate(reader.ReadString, guard)
If protection <> guard Then
Return Nothing
End If
Dim count As Integer = reader.ReadInt32()
assets = New List(Of AssetInfo)()
For i As Integer = 0 To count - 1
Dim asset As AssetInfo = New AssetInfo
asset.Index = AssetObfuscation.DeObfuscate(reader.ReadString, guard)
asset.UriString = AssetObfuscation.DeObfuscate(reader.ReadString, guard)
assets.Add(asset)
Next
End Using
End If
Return assets
End Function
End Class
الإستخدام
اولا عليك تعريف متغير يعبر عن الكلاس الخاص بحفظ و قراءة البيانات كالتالي
PHP كود :
Private context As AssetContext = New AssetContext
ثم و لحفظ البيانات إلي ملف يتم أولا إنشاء مصفوفة للبيانات ثم يتم حفظها في الملف و الكود التالي يوضح ذلك
بعد ذلك وكنوع من الإختبار لا غير لتذهب الي فهرس المشروع و افتح الملف ببرنامج NotePad ستجد ان البيانات كلها مشفرة ولا يمكن فهم شئ منها
PHP كود :
Dim list As List(Of AssetInfo) = New List(Of AssetInfo)()
list.Add(New AssetInfo With {.Index = "1", .UriString = "First"})
list.Add(New AssetInfo With {.Index = "2", .UriString = "Second"})
list.Add(New AssetInfo With {.Index = "3", .UriString = "Third"})
If context.Write(list) Then
MessageBox.Show("Data has been Saved to file")
Else
MessageBox.Show("Do Not know how to Save Data to file")
End If
و لقراءة البيانات من الملف يمكنك استخدام الكود التالي و انا هنا قمت بإضافة البيانات الي ListBox بعد قرائتها من الملف و هذا لمجرد التوضيح فقط أما انت فيمكن ان تضيفها الي الكونترول الذي يناسبك
PHP كود :
For Each current As AssetInfo In context.Read
ListBox1.Items.Add(current.Index + "- " + current.UriString)
Next
نصيحة أخيرة
هنا أنا كتبت كل شئ في مشروع واحد لكن نصيحتي لك أن تقسم الفكرة علي مرحلتين
المرحلة الأولي تحفظ الروابط في ملف و تقوم بتشفيرها
أما في البرنامج الرئيسي نفسه يتم اضافة الملف الموجودة به الروابط لفهرس المشروع وهنا سيكون عليك فقط قراءته و فك التشفير
أي ان الكلاسات اعلاه يجب تجزئتها بحيث يتم استخدام الجزء الخاص بفك التشفير و قراءة الملف من المشروع الرئيسي فقط
تقبل تحياتي
الله ما نور طريقك ويسر امورك كلها يارب
وعذرني استاذنا الكريم على الازعاج

