Das Net-Framework bietet mit der Binär-Serialisierung eine bequeme Möglichkeit, den Inhalt von strukturierten Datenklassen in einer Datei zu speichern. Um diese Informationen mit einem Passwort zu schützen, können die Kryptographie-Methoden im System.Security-Namespace herangezogen werden. Als Beispiel habe ich eine Klasse von der generischen Dictionary abgeleitet und zwei Methoden für das Verschlüsseln sowie Serialisieren der Auflistung der Schlüssel-Wert-Paare eingefügt. Voraussetzung ist dabei, daß die Datentypen der Schlüssel und der Werte serialisierbar sind. Wenn eigene Klassen in der Dictionary verwendet werden, sind sie durch das entsprechende Attribut zu kennzeichnen (vgl. Beispiel).<(p> Eine (unvollständige) Liste der binär-serialisierbaren Net-Klassen: Den Code zur Verschlüsselung habe ich dem VB-Archiv-Tipp 1351 "(Text-) Verschlüsselung (VB.NET)" entnommen. Option Strict Off Imports System Imports System.Collections.Generic ' Dictionary Imports System.Runtime.Serialization ' Formatters Imports System.Security 'Verschlüsselung (Cryptography) <System.Serializable> Public Class SerializableDictionary(Of TKey As IEquatable(Of TKey), TValue) Inherits Dictionary(Of TKey, TValue) Const Version As String = "SerializableDictionary 1.0" Dim fmt As New Formatters.Binary.BinaryFormatter Public Sub New() MyBase.New End Sub Public Sub New(info As SerializationInfo, context As StreamingContext) MyBase.New(info, context) End Sub ''' <summary>Speichern des Daten-Inhalts (Schlüssel-Wert-Paare)</summary> ''' <param name="filepath">Pfad und Name der Datei, die gelesen werden soll</param> ''' <param name="password">Optionales Passwort (falls Verschlüsselung erfolgen soll)</param> ''' <param name="AllowOverwrite">Überschreiben einer vorhandenen Datei erlauben</param> ''' <param name="msg">Meldung, falls Serialisieren, Verschlüsseln, Speichern scheitert</param> ''' <returns>Alles OK?</returns> Public Function Serialize(ByVal filepath As String, Optional ByVal password As String = "", Optional ByVal AllowOverwrite As Boolean = False, Optional ByRef msg As String = "") As Boolean If AllowOverwrite Then IO.File.Delete(filepath) Else If IO.File.Exists(filepath) Then msg = "Datei existiert bereits" Return False End If End If Dim data() As Byte ' Serialisierung der Daten innerhalb des Speichers durchführen Try Using msdata As New IO.MemoryStream ' Versions-Kennung ausgeben fmt.Serialize(msdata, Version) ' Daten serialisieren fmt.Serialize(msdata, Me) fmt.Serialize(msdata, Version) ' Bytearray aus dem Stream erstellen data = msdata.ToArray End Using Catch ex As Exception msg = "Fehler bei Serialisierung" & vbCrLf & ex.Message Return False End Try If password <> String.Empty Then ' Verschlüsselung der serialisierten Bytefolge Dim rd As New Cryptography.RijndaelManaged Dim md5 As New Cryptography.MD5CryptoServiceProvider Dim key() As Byte = md5.ComputeHash(System.Text.Encoding.UTF8.GetBytes(password)) md5.Clear() rd.Key = key rd.GenerateIV() Dim iv() As Byte = rd.IV Try Using msenc As New IO.MemoryStream, cs As New Cryptography.CryptoStream (msenc, rd.CreateEncryptor, Cryptography.CryptoStreamMode.Write) msenc.Write(iv, 0, iv.Length) cs.Write(data, 0, data.Length) cs.FlushFinalBlock() ' Array mit verschlüsselter Bytefolge füllen data = msenc.ToArray End Using Catch msg = "Fehler bei Verschlüsselung" : Return False End Try End If Try ' Schreiben der Daten-Bytes in die Datei IO.File.WriteAllBytes(filepath, data) Return True Catch ex As Exception msg = "Datei - Fehler beim Schreiben" & vbCrLf & ex.Message Return False End Try End Function ''' <summary>Lesen der serialisierten Daten eines Dictionary</summary> ''' <param name="filepath">Pfad und Name der Datei, die gelesen werden soll</param> ''' <param name="password">Optionales Passwort (falls Verschlüsselung vorliegt)</param> ''' <param name="msg">Meldung, falls Lesen, Entschlüsseln oder Deserialisieren scheitert</param> Public Function Deserialize(ByVal filepath As String, Optional ByVal password As String = "", Optional ByRef msg As String = "") As Boolean msg = "" Dim datadec(), data(0) As Byte Try datadec = IO.File.ReadAllBytes(filepath) Catch ex As Exception msg = "Lesefehler Datei " & vbCrLf & ex.Message Return False End Try Dim rd As New Cryptography.RijndaelManaged Dim rijndaelIvLength As Integer = 16 Dim md5 As New Security.Cryptography.MD5CryptoServiceProvider Dim key() As Byte = md5.ComputeHash(System.Text.Encoding.UTF8.GetBytes(password)) If password <> String.Empty Then Try ' Entschlüsselung der Daten-Bytes Using msdec As New IO.MemoryStream(datadec) Dim iv(15) As Byte md5.Clear() msdec.Read(iv, 0, rijndaelIvLength) rd.IV = iv rd.Key = key Using cs As New Cryptography.CryptoStream _ (msdec, rd.CreateDecryptor, Cryptography.CryptoStreamMode.Read) Array.Resize(Of Byte)(data, CInt(msdec.Length - rijndaelIvLength)) cs.Read(data, 0, data.Length) End Using End Using Catch ex As Exception msg = "Fehler bei Entschlüsselung" Return False End Try Else data = datadec 'Die Daten sind nicht passwortgeschützt End If Try ' Deserialisierung der Daten-Bytes Using ms As New IO.MemoryStream(data) Dim vers As String = DirectCast(fmt.Deserialize(ms), String) If vers <> Version Then msg = "Falsche Serialisierungs-Version" Return False End If Dim dic_temp As SerializableDictionary(Of TKey, TValue) = DirectCast(fmt.Deserialize(ms), SerializableDictionary(Of TKey, TValue)) vers = DirectCast(fmt.Deserialize(ms), String) If vers <> Version Then msg = "Falsches Dateiende gefunden" Return False End If Me.Clear() For Each kvp As KeyValuePair(Of TKey, TValue) In dic_temp Me.Add(kvp.Key, kvp.Value) Next kvp dic_temp = Nothing Return True End Using Catch ex As Exception msg = "Fehler bei Deserialisierung" & vbCrLf & ex.Message Return False End Try End Function End Class Beispiel: <System.Serializable> Private Class Person Implements IEquatable(Of Person) Public Property Name As String Public Property Vorname As String Public Property Alter As Integer Public Property Ausbildung As List(Of String) Public Function Equals1(other As Person) As Boolean Implements IEquatable(Of Person).Equals Dim sc As StringComparer = StringComparer.CurrentCultureIgnoreCase With other If sc.Compare(Name, .Name) <> 0 Then Return False If sc.Compare(Vorname, .Vorname) <> 0 Then Return False If Alter <> .Alter Then Return False If Ausbildung.Count <> .Ausbildung.Count Then Return False For i As Integer = 0 To Ausbildung.Count - 1 If sc.Compare(Ausbildung(i), .Ausbildung(i)) <> 0 Then Return False Next i End With Return True End Function Public Shared Operator <>(ByVal a As Person, ByVal b As Person) As Boolean Return Not a.Equals1(b) End Operator Public Shared Operator =(ByVal a As Person, ByVal b As Person) As Boolean Return a.Equals1(b) End Operator End Class Demonstration: Private Sub Demo() ' Erstellung der Dictionary Dim personen As New SerializableDictionary(Of Integer, Person) ' Erstellung von Testdaten Dim vn As String() = {"Hans", "Gerhard", "Dieter", "Elke", "Gudrun", "Meike"} Dim hn As String() = {"Müller", "Meier", "Schneider", "Schuster", "Meyer", "Özoguz"} Dim sch() As String = {"ohne Abschluß", "Realschule", "Fachakademie", "Handwerk", "Hochschule"} Dim ber() As String = {"Verkäufer", "Schreiner", "Installateur", "Techniker", "Lehrer", "Arzt"} Dim rndm As New Random(1234) For i As Integer = 1 To 100 Dim p As New Person p.Vorname = vn(rndm.Next(0, 6)) p.Name = hn(rndm.Next(0, 6)) p.Alter = rndm.Next(10, 61) p.Ausbildung = New List(Of String) p.Ausbildung.Add(sch(rndm.Next(0, 5))) p.Ausbildung.Add(ber(rndm.Next(0, 6))) ' Füllen der Dictionary / eindeutige Kennung als Schlüssel personen.Add(1000 + i, p) Next i Dim msg As String = "" Dim filepath As String = "G:Datenpersonendictionary.ser" Dim password As String = "az162xe" 'in der Praxis per Dialog vom User abfragen ' Verschlüsseltes Speichern der Daten If Not personen.Serialize(filepath, password, False, msg) Then MsgBox(msg, MsgBoxStyle.Exclamation) End If ' Lesen und Entschlüsseln der Daten Dim personen2 As New SerializableDictionary(Of Integer, Person) If Not personen2.Deserialize(filepath, password, msg) Then MsgBox(msg, MsgBoxStyle.Exclamation) End If ' Vergleich des Dateninhalts der beiden Klasseninstanzen For Each key As Integer In personen2.Keys If personen2(key) <> personen(key) Then Stop Next key End Sub Dieser Tipp wurde bereits 3.634 mal aufgerufen. Voriger Tipp | Zufälliger Tipp | Nächster Tipp
Anzeige
Diesen und auch alle anderen Tipps & Tricks finden Sie auch auf unserer aktuellen vb@rchiv Vol.6 Ein absolutes Muss - Geballtes Wissen aus mehr als 8 Jahren vb@rchiv! - nahezu alle Tipps & Tricks und Workshops mit Beispielprojekten - Symbol-Galerie mit mehr als 3.200 Icons im modernen Look Weitere Infos - 4 Entwickler-Vollversionen (u.a. sevFTP für .NET), Online-Update-Funktion u.v.m. |
sevISDN 1.0 Überwachung aller eingehender Anrufe! Die DLL erkennt alle über die CAPI-Schnittstelle eingehenden Anrufe und teilt Ihnen sogar mit, aus welchem Ortsbereich der Anruf stammt. Weitere Highlights: Online-Rufident, Erkennung der Anrufbehandlung u.v.m. Tipp des Monats Dezemeber 2024 Roland Wutzke MultiSort im ListView-Control Dieses Beispiel zeigt, wie sich verschiedene Sortierfunktionen für ein ListView Control realisieren lassen. TOP! Unser Nr. 1 Neu! sevDataGrid 3.0 Mehrspaltige Listen, mit oder ohne DB-Anbindung. Autom. Sortierung, Editieren von Spalteninhalten oder das interaktive Hinzufügen von Datenzeilen sind ebenso möglich wie das Erstellen eines Web-Reports. |
||||||||||||||||
Microsoft, Windows und Visual Basic sind entweder eingetragene Marken oder Marken der Microsoft Corporation in den USA und/oder anderen Ländern. Weitere auf dieser Homepage aufgeführten Produkt- und Firmennamen können geschützte Marken ihrer jeweiligen Inhaber sein. |