Datenschutz mit den Kryptografie-Namespaces von .NET Framework

Veröffentlicht: 07. Sep 2002 | Aktualisiert: 22. Jun 2004

Von Dan Fox

Das .NET Framework stellt eine Reihe kryptografischer Dienste bereit, die die von Windows über die Krypto-API bereitgestellten Dienste erweitern. In diesem Artikel untersucht der Autor den Namespace System.Security.Cryptography und das Programmiermodell, das für die Anwendung der kryptografischen Transformationen verwendet wird. Er erläutert die Gründe, warum die Kryptografie in .NET einfacher ist. Weiterhin veranschaulicht er den Unterschied zwischen symmetrischen und asymmetrischen Algorithmen und erläutert häufig verwendete Algorithmen wie RSA, DSA, Rijndael, SHA und andere Hashalgorithmen.

Auf dieser Seite

Der Kryptografie-Namespace
Verschlüsselungsalgorithmen
Verwenden von Kryptografiediensten
Starke Verschlüsselung in Windows

Dieser Artikel enthält Links zu englischsprachigen Seiten.

In diesem Artikel wird vorausgesetzt, dass Sie mit C# und der Krypto-API vertraut sind.

Das explosive Wachstum im E-Commerce-Bereich unterstreicht den Bedarf nach sicheren Algorithmen für den Datenschutz. Microsoft® hat sich erstmals 1996 durch die Einführung der Kryptografie-API (Krypto-API) mit dem Datenschutz auseinandergesetzt. Heute treibt die kontinuierliche Entwicklung neuer Sicherheitsstandards die Entwicklung kryptografischer Dienste wie dem Namespace System.Security.Cryptography der gemeinsamen Sprachlaufzeit (CLR = Common Langurage Runtime) von Microsoft .NET voran.

Dieser Namespace ermöglicht einen programmtechnischen Zugriff auf zahlreiche kryptografische Dienste, die Sie in Ihre Anwendungen zur Ver- und Entschlüsselung der Daten, zum Sicherstellen der Datenintegrität und zur Behandlung von digitalen Signaturen und Zertifikaten integrieren können.

Einige dieser Dienste werden an anderer Stelle im Framework genutzt (z.B. die ASP.NET-Authentifizierung). Ich werde die Grundlagen der vom .NET Framework bereitgestellten kryptografischen Dienste vorstellen und anhand einiger Codebeispiele zeigen, wie Sie diese Klassen in Ihren Anwendungen verwenden können.

Der Kryptografie-Namespace

Auf der obersten Ebene kann der Kryptografie-Namespace in vier Hauptbereiche unterteilt werden (siehe Tabelle 1). Der Kryptografie-Namespace stellt im Wesentlichen Klassen bereit, die Algorithmen für die Verschlüsselung und das Erstellen von Hashobjekten implementieren. Diese Algorithmen werden mithilfe eines erweiterten Musters implementiert, das aus zwei Vererbungsebenen besteht.

Bereich

Beschreibung

Verschlüsselungsalgorithmen

Ein Klassensatz, der zur Implementierung von symmetrischen und asymmetrischen Verschlüsselungs- und Hashalgorithmen verwendet wird.

Hilfsklassen

Klassen, die zur Generierung von Zufallszahlen, Konvertierungen, Interaktion mit dem Krypto-API-Speicher und zur tatsächlichen Verschlüsselung mithilfe eines streambasierten Modells verwendet werden.

X.509-Zertifikate

Im Namespace System.Security. Cryptography.X509Certificates definierte Klassen, die zur Darstellung digitaler Zertifikate verwendet werden.

Digitale XML-Signaturen

Im Namespace System. Cryptography.Xml definierte Klassen, die zur Darstellung digitaler Signaturen in XML-Dokumenten verwendet werden.

Tabelle 1. Komponenten

Eine abstrakte Basisklasse wie AsymmetricAlgorithm oder HashAlgorithm befindet sich oben in der Hierarchie und gibt den Algorithmustyp an. Von der primären Klasse wird dann zur Bereitstellung einer öffentlichen Schnittstelle für den Algorithmus eine sekundäre abstrakte Klasse abgeleitet. So ist z.B. die SHA1-Klasse (Secure Hash Algorithm) von HashAlgorithm abgeleitet und enthält an den SHA1-Algorithmus angepasste Methoden und Eigenschaften.

Die Algorithmusimplementierung wird abschließend von der sekundären Ebene abgeleitet, in der Regel als Instanz definiert und von Clientanwendungen verwendet. Auf dieser konkreten Ebene können die Implementierungen entweder verwaltet, nicht verwaltet oder gleichzeitig verwaltet und nicht verwaltet werden.
Nicht verwaltete Implementierungen enthalten in der Regel das Suffix "CryptoServiceProvider" z.B. SHA1CryptoServiceProvider, um anzuzeigen, dass die Implementierung vom Kryptografiedienstanbieter bereitgestellt wird, der auf Betriebssystemebene installiert ist und als Wrapper für die Krypto-API fungiert. Verwaltete Implementierungen enthalten das Suffix "Managed" z.B. SHA1Managed, sind nicht auf die Krypto-API angewiesen und werden daher ausschließlich im verwalteten Code implementiert.
Ein weiterer bei diesen Algorithmen zu berücksichtigender Punkt ist, dass beim Erstellen einer Instanz von einer dieser konkreten Klassen die Standardkonstruktoren (wenn möglich) immer die Standardparameter des Algorithmus mit sinnvollen und sicheren Werten auffüllen. Die asymmetrischen Algorithmen, die z.B. auf eine Kryptografie mit öffentlichen Schlüsseln angewiesen sind, generieren ein zufälliges Schlüsselpaar, während symmetrische Algorithmen einen zufälligen Schlüssel und einen Initialisierungsvektor (IV) generieren und Eigenschaften wie Mode und Padding automatisch festlegen. Zusätzlich verwenden die Algorithmen ggf. die Strong-Standardeinstellungen.
Die zweite wichtige Klassenauflistung im Namespace System.Security.Cryptography enthält die Klassen, die bei der Ver- und Entschlüsselung der Daten tatsächlich verwendet werden, und auch zahlreiche Hilfsklassen. Der Namespace enthält Klassen wie die abstrakte Klasse RandomNumberGenerator, von der RNGCryptoServiceProvider abgeleitet wird, und die Klassen ToBase64Transform und FromBase64Transform, die für die Datentransformation von und in Base 64 verwendet werden.
Zusätzlich zur Offenlegung der kryptografischen Algorithmen enthält der Kryptografie-Namespace den untergeordneten Namespace X509Certificates. Dieser Namespace enthält nur drei Klassen, die zur Darstellung und Verwaltung von Authenticode-Zertifikaten (X.509 v.3) verwendet werden. Die X509Certificate-Klasse legt die statischen Methoden CreateFromCertFile und CreateFromSignedFile zur Erstellung einer Zertifikatinstanz offen:

Dim c As X509Certificate
c = X509Certificate.CreateFromCertFile("myCert.cer")
Console.WriteLine(c.GetName)
Console.WriteLine(c.GetPublicKeyString)
Console.WriteLine(c.GetSerialNumberString)
Console.WriteLine(c.GetExpirationDateString)

Das Zertifikat kann anschließend für vieles verwendet werden, einschließlich einer Webserverbestätigung durch Anhängen an eine Clientanforderung über die Eigenschaft ClientCertificates (die ein X509CertificateCollection-Objekt offen legt) des System.Net.HttpWebRequest-Objekts.
Der Kryptografie-Namespace enthält auch einen untergeordneten XML-Namespace, der vom .NET-Framework-Sicherheitssystem zur digitalen Signierung von XML-Objekten verwendet wird. Das Framework hält sich bei der XML-Signatursyntax und -verarbeitung an einen W3C-Spezifikationsentwurf (http://www.w3.org/TR/2000/WD-xmldsig-core-20000228/). Dieser Entwurf umfasst Regeln für die XML-Syntax und -verarbeitung zum Generieren und Darstellen von digitalen Signaturen, die auf beliebigen Inhalt angewendet werden können, der sich innerhalb oder außerhalb des XML-Dokuments befindet, das eine dieser Signaturen enthält. Während der Entwurf (noch) nicht auf die XML-Verschlüsselung eingeht, sollte er sicherlich bei der Bereitstellung von Datenintegrität, Nachrichtenauthentifizierung und Signaturgeber-Authentifizierungsdiensten für XML-Dokumente berücksichtigt werden.
Auf den nachfolgenden Seiten dieses Artikels werde ich mich auf die Verschlüsselungsalgorithmen und das Programmiermodell für die Anwendung der kryptografischen Transformationen konzentrieren.

Verschlüsselungsalgorithmen

Wie in Abbildung 1 beschrieben, ist einer der im Kryptografie-Namespace vorhandenen Verschlüsselungsalgorithmen ein symmetrischer Kryptografiealgorithmus. Symmetrische Algorithmen werden so bezeichnet, weil sie einen einzelnen geheimen Schlüssel enthalten, der für die Ver- und Entschlüsselung verwendet wird. Offensichtlich müssen Absender und Empfänger den Schlüssel für eine sichere Verschlüsselung geheimhalten.

Im CBC-Modus ist für symmetrische Algorithmen zusätzlich ein IV erforderlich, ein nicht geheimer Binärwert, der für die Algorithmusinitialisierung und Einführung einer zusätzlichen kryptografischen Varianz verwendet wird. Die SymmetricAlgorithm-Klasse ist eine abstrakte Basisklasse, von der weitere algorithmusspezifische Klassen abgeleitet sind.
Zu den unterstützten symmetrischen Algorithmen gehören DES (Data Encryption Standard), RC2, Rijndael und TripleDES (Triple Data Encryption Standard). Jeder Algorithmus enthält eine von SymmetricAlgorithm abgeleitete abstrakte Basisklasse, z.B. DES. Sie enthalten ebenfalls eine Dienstanbieterklasse bzw. verwaltete Klasse, die z.B. von der Basisklasse DESCryptoServiceProvider abgeleitet wurde. Diese Klasse enthält die Methoden zur Ver- und Entschlüsselung von Daten. Die Hierarchie der symmetrischen Algorithmen ist in Abbildung 1 dargestellt.

Bild01

Abbildung 1 Symmetrische Algorithmen

Konkrete Klassen wie RijndaelManaged, dargestellt in Abbildung 1, können dann instantiert und deren Eigenschaften aufgerufen werden (siehe Listing 1). In Listing 1 wird eine neue Instanz des Algorithmus erstellt, die automatisch einen Schlüsselwert und einen IV als Bytearrays generiert, die dann als Zeichenfolgenwerte serialisiert und auf der Konsole ausgegeben werden. Beachten Sie, dass Eigenschaften wie KeySize und BlockSize verwendet werden können, um die Schlüssellänge und den Umfang der in einem Vorgang ver- und entschlüsselbaren Daten (in Bits) zu bestimmen.

Dim oEnc As New RijndaelManaged()
Dim i As Short
Dim strKey, strIV As String
For i = 1 To (oEnc.KeySize / 8)
  strKey &= oEnc.Key(i - 1).ToString & " "
Next
For i = 1 To 16
  strIV &= oEnc.IV(i - 1).ToString & " "
Next
Console.WriteLine(strKey)
Console.WriteLine(strIV)
Console.WriteLine(oEnc.KeySize.ToString)
Console.WriteLine(oEnc.BlockSize.ToString)

Listing 1. "RijndaelManaged" verwenden

Der zweite Algorithmustyp wird als Algorithmus mit öffentlichem Schlüssel oder asymmetrischer Algorithmus bezeichnet; er wird von der abstrakten Klasse AsymmetricAlgorithm abgeleitet. Dazu gehören bekannte Algorithmen wie DSA (Digital Signature Algorithm) und RSA (benannt nach dessen Entwicklern Ron Rivest, Adi Shamir und Len Adleman).

Asymmetrische Algorithmen sind auf ein Schlüsselpaar angewiesen, wobei ein Schlüssel privat und der andere öffentlich ist. Der öffentliche Schlüssel ist in der Regel für jeden verfügbar und wird vom Absender zur Datenverschlüsselung verwendet, wohingegen der private Schlüssel geschützt ist und für die Entschlüsselung der mit dem öffentlichen Schlüssel verschlüsselten Daten verwendet wird. RSA wird häufig auf diese Weise für den Datenschutz eingesetzt.
Diese Algorithmen sind letztendlich von den abstrakten Klassen DSA und RSA abgeleitet, die wiederum von AsymmetricAlgorithm abgeleitet sind, wie in Abbildung 2 dargestellt. Darüber hinaus sind für die komplexe Natur der Algorithmen zusätzliche Hilfsklassen wie die von AsymmetricKeyExchangeFormatter und AsymmetricSignatureFormatter abgeleiteten Klassen erforderlich.

Bild02

Abbildung 2 Asymmetrische Algorithmen

Da es möglich ist, dass der Standardkonstruktor der asymmetrischen Algorithmen ein Schlüsselpaar generiert, können Sie zusätzlich ein vorhandenes Schlüsselpaar aus dem vom CSP verwalteten Speicher abrufen. Dazu erstellen Sie eine Instanz der asymmetrischen Algorithmen mit den Schlüsselcontainernamen eines im Schlüsselspeicher der Krypto-API vorhandenen Paares, indem Sie ein CspParameters-Objekt mit dem Schlüsselcontainernamen füllen und diese Instanz dem Konstruktor des asymmetrischen Algorithmus bereitstellen. Ein Beispiel für das Speichern und Abrufen von asymmetrischen Schlüsselpaaren finden Sie unter http://www.gotdotnet.com/team/clr/about_security.aspx.

Der letzte vom Kryptografie-Namespace offen gelegte Algrorithmustyp ist der Hashalgorithmus. Dieser Algorithmus verarbeitet eine eindeutige Sequenz von Binärwerten mit fester Größe (als Digest bezeichnet) basierend auf einer längeren Bytesequenz. Sie verwenden einen Hashalgorithmus, um festzustellen, ob Daten geändert wurden. Wenn Sie das Digest mit den Daten senden, kann der Empfänger es erneut verarbeiten. Da die Ausgabe eines Hashalgorithmus unterschiedlich ist, wenn auch die Dateneingabe unterschiedlich ist, zeigt ein Vergleich des neuen mit dem alten Digest, ob sich die Daten geändert haben. Hashalgorithmen werden in der Regel als Grundlage für digitale Signaturen verwendet.
Der Kryptografie-Namespace enthält eine Basisklasse mit der Bezeichnung HashAlgorithm und abgeleitete Klassen, die die Algorithmen MD5, SHA1, SHA256, SHA384 und SHA512 unterstützen. Der MD5-Algorithmus generiert einen 128-Bit-Hash, während der SHA1-Algorithmus einen 160-Bit-Hash generiert. Die in den anderen SHA-Versionen enthaltenen Nummern zeigen die Hashlänge an. Je größer die Hashlänge, desto sicherer ist der Algorithmus und umso schwieriger kann der Algorithmus durch einen Brute-Force-Angriff entschlüsselt werden. Diese Algorithmen werden als nicht verwaltete und verwaltete Versionen bereitgestellt, wie in Abbildung 3 gezeigt.

Bild03

Abbildung 3 Hashalgorithmen

Zur Digestverarbeitung können Sie einfach den Hashalgorithmus instantieren und dessen überladene, von HashAlgorithm vererbte ComputeHash-Methode folgendermaßen aufrufen:

Dim fsData As New FileStream("mydata.txt", _
    FileMode.Open, FileAccess.Read)
  Dim digest() As Byte
Dim oSHA As New SHA512Managed()
digest = oSHA.ComputeHash(fsData)
fsKey.Close()

In diesem Beispiel wird die ComputeHash-Methode an ein Stream-Objekt übergeben, sie kann aber auch ein Bytearray als Argument akzeptieren.
Der Kryptografie-Namespace enthält ebenfalls eine abstrakte Klasse mit der Bezeichnung KeyedHashAlgorithm (siehe Abbildung 3). In die Klassen HMACSHA1 und MACTripleDES implementierte Argumente sind von KeyedHashAlgorithm abgeleitet, um "Nachrichtenauthentifizierungscodes" (Message Authentication Codes = MAC) zu generieren. Mit einem MAC kann festgestellt werden, ob über einen unsicheren Kanal gesendete Daten geändert wurden, wenn Absender und Empfänger einen gemeinsamen sicheren Schlüssel verwenden.
Obwohl die abstrakten Basisklassen SymmetricAlgorithm, AsymmetricAlgorithm, HashAlgorithm und KeyedHashAlgorithm nicht direkt von einem Client instantiiert werden können, legen sie jeweils eine überladene statische (freigegebene) Methode mit dem Namen Create offen. Diese Methode kann ohne Parameter aufgerufen werden, um eine Instanz des bestimmten Algorithmus zu erstellen, d.h. standardmäßig RijndaelManaged für symmetrische, RSACryptoServiceProvider für asymmetrische, SHA1CryptoServiceProvider für Hash- und HMACSHA1 für Schlüssel-Hashalgorithmen.

Eine zweite Version akzeptiert ebenfalls eine Zeichenfolge, die der Implementierung zugeordnet ist (die Zuordnungsliste ist in der Onlinehilfe im .NET Framework enthalten). Auf genau dieselbe Weise enthält die abstrakte Klasse für jeden Algorithmus, z.B. SHA, ebenfalls eine überladene statische Create-Methode, die die Standardimplementierung für diesen bestimmten Algorithmus instantiiert oder den Zeichenfolgenbezeichner akzeptiert.
In beiden Fällen wird das Objekt durch den Aufruf der CreateFromName-Methode der CryptoConfig-Klasse und Übergabe eines Zeichenfolgenbezeichners erstellt. Diese Zuordnungsliste verarbeitet die beim Aufruf der Create-Methode verwendeten Standardwerte. Zusätzlich verarbeitet sie die Zeichenfolgenzuordnungen, die an die Create-Methode für eine bestimmte Klasse übergeben wurden. Wenn die Create-Methode z.B. ohne einen Parameter aufgerufen wurde, ordnet sie die Standardzeichenfolge "System.Security.Cryptography.HashAlgorithm" der SHA1CryptoServiceProvider-Klasse zu. Wenn die Zeichenfolge "SHA1" übergeben wurde, wird die Methode derselben Klasse zugeordnet.
Zur Illustration dieser Methoden ist der folgende Code geeignet, bei dem jede Anweisung der anderen entspricht und eine Instanz der RijndaelManaged-Klasse erstellt:

Dim r, r1, r2, r3 As RijndaelManaged
r3 = CType(CryptoConfig.CreateFromName("Rijndael"), "_
           RijndaelManaged)
r2 = CType(SymmetricAlgorithm.Create, RijndaelManaged)
r1 = CType(Rijndael.Create, RijndaelManaged)
r = New RijndaelManaged()

Dies kann verwirrend erscheinen, die Klassen wurden jedoch auf diese Weise entworfen, so dass die Entscheidung darüber, welcher Algorithmus verwendet werden soll, bis zur Laufzeit verschoben oder bei der Systemkonfiguration festgelegt werden kann. Tatsächlich kann die systemübergreifende Konfigurationsdatei (machine.config) um einen cryptoNameMapping-Abschnitt erweitert werden, der dazu dient, die Standardzuordnungen außer Kraft zu setzen oder sie der in Mscorlib.dll festcodierten Zuordnungsliste hinzuzufügen. So kann z.B. der in Listing 2 gezeigte XML-Code in den Konfigurationsabschnitt der Datei machine.config eingefügt werden, um die standardmäßige Hashimplementierung auf MD5CryptoServiceProvider festzulegen und eine neue Zuordnung aus der Zeichenfolge "dan" für die Implementierung zu erstellen.

<mscorlib>
 <cryptographySettings>
   <cryptoNameMapping>
     <cryptoClasses>
       <cryptoClass myMD5=
        "System.Security.Cryptography.MD5CryptoServiceProvider,
        mscorlib, Ver=1.0.2411.0, Culture=neutral, 
        PublicKeyToken=b77a5c561934e089"/>
       </cryptoClasses>
       <nameEntry name="dan" class="myMD5"/>
       <nameEntry name="System.Security.Cryptography.HashAlgorithm" 
        class="myMD5"/>
     </cryptoNameMapping>
  </cryptographySettings>
</mscorlib>

Listing 2. Kryptografiekonfiguration

Ist es möglich, eigene Zuordnungen zu erstellen? Sie können ein cryptoClass-Element innerhalb des cryptoClasses-Elements hinzufügen, um einen Namen als Verweis zu definieren, in diesem Fall "myMD5", und eine vollständige Beschreibung für die Klasse und Assembly zu liefern. Die nameEntry-Elemente werden dann zum Erstellen der Zuordnungen verwendet. Anschließend kann der folgende Clientcode geschrieben werden:

Dim m, m1 As MD5CryptoServiceProvider
m = CType(HashAlgorithm.Create, MD5CryptoServiceProvider)
m1 = CType(CryptoConfig.CreateFromName("dan"), "_
           MD5CryptoServiceProvider)

In beiden Instanzen werden Objekte vom Typ MD5CryptoServiceProvider erstellt.

Verwenden von Kryptografiediensten

Das streambasierte Programmiermodell wird mehr und mehr im .NET Framework genutzt. Von System.IO.Stream abgeleitete Streamklassen werden für die Datendarstellung aus Speichern wie Textdateien, XML-Dokumenten, MSMQ-Nachrichten, Arbeitsspeicher sowie Netzwerk verwendet und können abwechselnd zur Datenübertragung aus und in diese Speicher genutzt werden. Es sollte wenig überraschend sein, dass der Kryptografie-Namespace dieses Konzept übernommen hat, um eine elegante und effiziente Methode zur Ver- und Entschlüsslung der zuvor erörterten Algorithmen bereitzustellen. Das Kernstück dieser Funktionen ist die CryptoStream-Klasse, die von System.IO.Stream abgeleitet ist und als streambasiertes Modell für kryptografische Transformationen dient.
Zur Illustration der Verwendung der grundlegenden kryptografischen Funktionen in diesem Namespace wird in Listing 3 die einfache TextFileCrypto-Klasse herangezogen. Diese Klasse kann für die symmetrische Ver- und Entschlüsselung einer Datei mit Hilfe von DES und einem von der Klasse generierten und in einer Datei gespeicherten Schlüssel verwendet werden.

Option Strict On
 Imports System.Security.Cryptography
 Imports System.IO
 Imports System.Threading
 Public Class TextFileCrypto
   ' Textdatei wird mit Schlüssel ver- und entschlüsselt
   Private mstrFile As String ' Zu entschlüsselnde Datei
   Private mstrKey As String ' Schlüsseldatei
   Private mKey(7) As Byte  ' DES-Schlüssel
   Private mDES As DESCryptoServiceProvider
   Private mIV(7) As Byte ' Initialisierungsvektor
   Public Sub New()
     mDES = New DESCryptoServiceProvider()
   End Sub
   Public Property KeyFile() As String
     Get
       Return mstrKey
     End Get
     Set(ByVal Value As String)
       If File.Exists(Value) Then
         mstrKey = Value
         OpenKeyFile() ' Schlüsseldatei öffnen und Inhalt lesen
       Else
         Throw New FileNotFoundException(Value & " file does not exist.")
       End If
     End Set
   End Property
   Public Property FileName() As String
     Get
       Return mstrFile
     End Get
     Set(ByVal Value As String)
       If File.Exists(Value) Then
         mstrFile = Value
       Else
         Throw New FileNotFoundException(Value & " does not exist.")
       End If
     End Set
   End Property
   Private Sub OpenKeyFile()
     Dim fsKey As New FileStream(mstrKey, _
       FileMode.Open, FileAccess.Read)
     ' Schlüsseldatei öffnen und Schlüssel auslesen
     fsKey.Read(mKey, 0, 8)
     fsKey.Read(mIV, 0, 8)
     fsKey.Close()
     mDES.Key = mKey
     mDES.IV = mIV
   End Sub
   Public Function SaveKeyFile(ByVal FilePath As String) As Boolean
     Dim fsKey As New FileStream(FilePath, _
       FileMode.OpenOrCreate, FileAccess.Write)
     ' Neuen Zufallsschlüssel und IV generieren und als Datei speichern
     ' Beachten Sie, dass diese automatisch nach dem Zufallsprinzip 
     ' generiert werden, wenn Sie diesen Schritt nicht ausführen
     mDES.GenerateKey()
     mDES.GenerateIV()
     mKey = mDES.Key
     mIV = mDES.IV
     fsKey.Write(mKey, 0, mKey.Length)
     fsKey.Write(mIV, 0, mKey.Length)
     fsKey.Close()
     mstrKey = FilePath
   End Function
   Public Function EncryptFile() As Boolean
     ' Angegebene Datei verschlüsseln
     ' Schlüssel überprüfen
     If mKey Is Nothing Then
       Throw New Exception("You must have a key in place first.")
       Return False
     End If
     Dim fsInput As New FileStream(mstrFile, _
       FileMode.Open, FileAccess.Read)
     Dim fsOutput As New FileStream("temp.dat", _
       FileMode.Create, FileAccess.Write)
     fsOutput.SetLength(0)
     Dim arInput() As Byte
     ' DES-Verschlüsselung aus dieser Instanz erstellen
     Dim desEncrypt As ICryptoTransform = mDES.CreateEncryptor()
     ' CryptoStream erstellen, der FileStream mithilfe der DES-Verschlüsselung transformiert
     Dim sCrypto As New CryptoStream(fsOutput, desEncrypt, _
       CryptoStreamMode.Write)
     ReDim arInput(Convert.ToInt32(fsInput.Length - 1))
     fsInput.Read(arInput, 0, Convert.ToInt32(fsInput.Length))
     fsInput.Close()
     ' DES-verschlüsselte Datei schreiben
     sCrypto.Write(arInput, 0, arInput.Length)
     sCrypto.Close()
     ' Löschen und Umbenennen
     File.Copy("temp.dat", mstrFile, True)
     File.Delete("temp.dat")
   End Function
   Public Function DecryptFile() As Boolean
     ' Angegebene Datei entschlüsseln
     ' Schlüssel überprüfen
     If mKey Is Nothing Then
       Throw New Exception("You must have a key in place first.")
       Return False
     End If
     ' FileStream zum Wiedereinlesen der entschlüsselten Datei erstellen
     Dim fsRead As New FileStream(mstrFile, FileMode.Open, _
       FileAccess.Read)
     Dim fsOutput As New FileStream("temp.dat", _
       FileMode.Create, FileAccess.Write)
     ' DES-Verschlüsselung aus DES-Instanz erstellen
     Dim desDecrypt As ICryptoTransform = mDES.CreateDecryptor()
     ' CryptoStream zum Lesen und Ausführen einer DES-Verschlüsselung erstellen 
     ' Eingehende Bytes transformieren
     Dim sCrypto As New CryptoStream(fsRead, desDecrypt, _
       CryptoStreamMode.Read)
     Dim swWriter As New StreamWriter(fsOutput)
     Dim srReader As New StreamReader(sCrypto)
     ' Entschlüsselte Datei schreiben
     swWriter.Write(srReader.ReadToEnd)
     ' Schließen und Bereinigen
     swWriter.Close()
     fsOutput.Close()
     fsRead.Close()
     ' Löschen und Umbenennen
     WaitForExclusiveAccess(mstrFile)
     File.Copy("temp.dat", mstrFile, True)
     File.Delete("temp.dat")
   End Function
   Private Sub WaitForExclusiveAccess(ByVal fullPath As String)
     While (True)
       Try
         Dim file As FileStream
         file = New FileStream(fullPath, FileMode.Append, _
           FileAccess.Write, FileShare.None)
         file.Close()
         Exit Sub
       Catch e As Exception
         Thread.Sleep(100)
       End Try
     End While
   End Sub
 End Class

Listing 3. Basiskryptografie mit dem DES-Algorithmus

Wie Sie sehen können, instantiert der Klassenkonstruktor eine DESCryptoServiceProvider-Klasse auf Klassenebene, die die Methoden CreateEncryptor und CreateDecryptor offen legt. Diese Methoden werden zu einem späteren Zeitpunkt verwendet, um Objekte zurückzugeben, die die Ver- und Entschlüsselung ausführen. Die öffentlichen Eigenschaften KeyFile und FileName werden verwendet, um eine vorhandene Datei zu öffnen, die den Schlüssel und IV enthält, und um den Namen der zu ver- und entschlüsselnden Datei festzulegen.

Wenn die Schlüsseldatei vorhanden ist, wird die Datei mithilfe der privaten OpenKeyFile-Methode geöffnet und der Schlüssel und IV als Bytearrays eingelesen. Die SaveKeyFile-Methode ruft die Methoden GenerateKey und GenerateIV der zugrunde liegenden DES-Klasse auf, um einen zufälligen Schlüssel und IV zu generieren. Diese Werte werden dann in der als Argument übergebenen Datei gespeichert. Zu diesem Zeitpunkt sollte die Schlüsseldatei geheim gehalten und an jemanden übergeben werden, der sie zur Entschlüsselung der Daten verwendet.
Der DES-Algorithmus verwendet einen 56-Bit-Schlüssel (7-Byte). Obwohl DES nur eine einzelne Schlüsselgröße unterstützt, können gültige Schlüsselgrößen für andere Algorithmen durch Abfrage der LegalKeySizes-Eigenschaft ermittelt werden, die ein Array von KeySize-Objekten zurückgibt, die gültige Größen für die Eigenschaften MinSize, MaxSize und SkipSize (Inkrement) darstellen. Der Rijndael-Algorithmus unterstützt beispielsweise Schlüsselgrößen mit 128, 192 und 256 Bits. Für eine stärkere Verschlüsselung kann eine neue Größe mithilfe der KeySize-Eigenschaft festgelegt werden.
Die Methoden EncryptFile und DecryptFile sind das Kernstück der TextFileCrypto-Klasse. Zunächst öffnet die EncryptFile-Methode die zu verschlüsselnde Datei und eine temporäre Datei zur Speicherung der verschlüsselten Daten. Anschließend erstellt sie ein Verschlüsselungsobjekt mithilfe der CreateEncryptor-Methode des Dienstanbieters (in diesem Fall DESCryptoServiceProvider). Dieses Objekt implementiert die ICryptoTransform-Schnittstelle und kann daher an den Konstruktor von CryptoStream übergeben werden, der die Daten, sobald sie in eine durch einen FileStream (in diesem Fall fsOutput) gesicherte Datei geschrieben sind, transformiert. Die temporäre Datei überschreibt dann die Originaldatei. Als Ergebnis erhalten Sie eine verschlüsselte Datei, die dann auf sichere Weise per FTP oder als E-Mail-Anhang über das Internet gesendet werden kann.
Die DecryptFile-Methode geht entgegengesetzt vor, indem ein Entschlüsselungsobjekt mithilfe der CreateDecryptor-Methode erstellt wird. Dieses Objekt wird ebenfalls an den CryptoStream-Konstruktor zur Entschlüsselung der Datei beim Lesen aus dem FileStream fsRead übergeben. Abschließend werden die entschlüsselten Daten als Textdatei von der StreamWriter-Klasse mithilfe der ReadToEnd-Methode der StreamReader-Klasse gespeichert.
Ein Client kann die TextFileCrypto-Klasse zur Verschlüsselung von Daten in nur vier einfachen Codezeilen verwenden:

Dim objCrypt As New TextFileCrypto()
objCrypt.FileName = "students.txt"
' Schlüssel generieren und speichern
objCrypt.SaveKeyFile("mykey.dat")
' Datei verschlüsseln
objCrypt.EncryptFile()

Wenn ein Client die Datei empfängt, kann er sie genauso einfach entschlüsseln:

Dim objCrypt As New TextFileCrypto()
objCrypt.FileName = "students.txt"
' Schlüssel lesen
objCrypt.KeyFile = "mykey.dat"
' Datei entschlüsseln
objCrypt.DecryptFile()

Starke Verschlüsselung in Windows

Während eine alte rechtliche Beschränkung, die den Export von stark verschlüsselten Produkten eingegrenzt hatte, aufgehoben wurde, verwendet das .NET Framework die starke Verschlüsselung für nicht verwaltete Implementierungen nicht, wenn Ihr Betriebssystem eine Exportversion ist. Um dies zu umgehen, können Sie das High Encryption Pack installieren. Service Pack 2 für Windows 2000 enthält das High Encryption Pack, das Sie unter Windows 2000 High Encryption Pack downloaden können.
Für Windows NT® 4.0 werden die Service Packs als Version mit Standardverschlüsselung und hoher Verschlüsselung bereitgestellt. Wenn Sie noch kein Service Pack installiert haben, können Sie das High Encryption Pack unter Service Pack 6a downloaden.
Für Windows ME, Windows 98 und Windows 95 ist das High Encryption Pack in Microsoft Internet Explorer 5.5 enthalten. Wenn Sie eine ältere Internet Explorer-Version als 5.5 verwenden, können Sie das entsprechende High Encryption Pack downloaden.

Verwandte Artikel finden Sie unter:
Geek Speak Decoded #9: Cryptography and Encryption
A Simple Guide to Cryptography

Hintergrundinformationen finden Sie unter:
http://www.gotdotnet.com/team/clr/about_security.aspx
http://www.gotdotnet.com/team/clr/cryptofaq.htm

Links zu verwandten Themen

Anzeigen: