Glengamoi (Forum) · AspHeute · .NET Heute (RSS-Suche) · AspxFiles (Wiki) · .NET Blogs
ASP German Homepage Homepage
 

Liste

.NET 2.0 (1)
.NET Allgemein (16)
.NET Fu (5)
ADO.NET (11)
Aprilscherz (3)
ASP Grundlagen (44)
ASP Tricks (83)
ASP.NET (44)
ASPIntranet.de (5)
C# (28)
Datenbank (44)
Dokumentation (4)
IIS 6.0 (1)
Komponenten (29)
Optimierung (10)
Server (21)
Sicherheit (34)
Tee Off (6)
VB.NET (6)
WAP (8)
Web Services (11)
XML (9)

RSS 2.0 - Die neuesten fünf Artikel auf AspHeute.com


 

Suchen





 

English Articles
Chinese Articles
Unsere Autoren
 
Link zu AspHeute
Impressum
Werben
Anfragen

Unknackbare Verschlüsselung mit Onetime Pads

Geschrieben von: Christoph Wille
Kategorie: Sicherheit

Im Zuge der Terrorangriffe auf das World Trade Center ist - wieder einmal - eine Debatte zur Rolle von Verschlüsselungstechnologien in der Kommunikation von Terroristen ins Laufen gekommen. Hauptaugenmerk wird in solchen Debatten immer auf sogenannte Hintertüren (Backdoors) für die Regierungsbehörden in Verschlüsselungsalgorithmen gelegt - also, wie Behörden ohne Zustimmung der Kommunizierenden den (verschlüsselten) Datenverkehr abhören können.

Es gibt verschiedenste Ansätze soetwas zu realisieren - dies reicht von klassischen Hintertüren bis hin zu Key Escrow (Hinterlegung von Schlüsseln bei Regierungsbehörden). Allerdings entbehrt die gesamte Diskussion nicht einer gewissen Lächerlichkeit: es gibt nämlich einen unknackbaren Verschlüsselungsalgorithmus, den Vernam Algorithmus, besser bekannt unter dem Namen One-time Pad, der speziell unter Spionen beliebt war oder ist. Jedem, der nur ein wenig von Verschlüsselungstechnik versteht, wird dessen mathematisch bewiesene Unknackbarkeit bekannt sein - also auch Terroristen, denen Tätigkeiten der NSA, Carnivore und Echelon sicherlich ebensowenig unbekannt sein werden wie dem durchschnittlichen Netzwerkadministrator.

Das Ziel des Artikels ist zu zeigen, wie lächerlich einfach und mit wie wenig Code man den Vernam Algorithmus in .NET implementieren kann (im engeren Sinne der Implementierung habe ich weniger als hundert Zeilen benötigt). Was damit auch bewiesen ist, daß unknackbare Verschlüsselung in der Reichweite von jedermann ist, inklusive von Leuten, denen man Verschlüsselung eigentlich verbieten möchte (und die gesamten vorgeschlagenen Einschränkungen die Falschen treffen werden).

Funktionsweise des Vernam Algorithmus

Der Vernam Algorithmus ist in seiner Einfachheit absolut bestechend - man benötigt zur Verschlüsselung einer Datei A nur das sogenannte Onetime Pad, welches ebenfalls eine Datei ist. Dieses One-time Pad zeichnet sich durch einige wichtige Eigenschaften aus: es darf nur dem Sender und Empfänger der Nachricht bekannt sein, es sollte mittels eines Pseudo-Zufallszahlengenerator (PRNG - pseudo-random number generator) mit Daten befüllt worden sein, und es dürfen keine Sequenzen des Pads jemals zum Verschlüsseln doppelt verwendet werden.

Wie funktioniert das oben erwähnte Verschlüsseln? Nun, ganz einfach: ein Byte der Ausgangsdatei wird mit je einem Byte des Pads per XOR verschlüsselt. Dann kommt das nächste Byte der Ausgangsdatei als auch des Pads an die Reihe. Jemand, der das Pad nicht in Händen hat, hat nicht die geringste Chance die Nachricht zu entschlüsseln. Für den Empfänger hingegen ist es ein Leichtes.

Der einzige wirkliche Knackpunkt des Vernam Algorithmus ist der Austausch des One-time Pads zwischen Sender und Empfänger. Klarerweise sollte das Pad nicht per Email verschickt werden, aber eine CD per Post dürfte nicht auffällig sein. Vor allem, wenn viele MP3 Dateien darauf sind (als Beispiel), und eine davon statt Musik ein Onetime Pad ist. Ich habe hier nicht vor, eine vollständige Anleitung zu geben.

Wichtig ist, daß nach Verwendung des Pads dasselbe vernichtet werden muß. Liegt das Pad auf der Festplatte, muß die Datei sicher gelöscht (gewiped) werden. Ist es eine CD, reicht gründliches Zerschneiden derselben aus.

Generieren eines Onetime Pads

Wie bereits bei der Beschreibung des Algorithmus erwähnt, soll das Onetime Pad wirklich zufällig mit Zahlen gefüllt sein, und hier bieten sich PRNG's (pseudo-random number generators) an. Natürlich kann man selbst einen solchen entwickeln, aber warum sich selbst die Arbeit machen? Es gibt einige, darunter zum Beispiel Yarrow von Bruce Schneier und John Kelsey.

Ich war aber noch eine Spur fauler. Im WIN32 API gibt es die Funktion CryptGenRandom, die mir kryptographisch sichere Zufallszahlen liefert. Und im .NET Framework findet sich der RNGCryptoServiceProvider, der eben diesen Service in .NET Applikationen zur Verfügung stellt. Also brauche ich diese Klasse nur zu verwenden, um mir meine Funktion zu schreiben, die ein Onetime Pad einer bestimmten Größe erzeugt (otp.cs):

using System;
using System.IO;
using System.Security.Cryptography;

class Onetimepad
{
  public bool Generate(string strFilename, long nSize)
  {
    if (File.Exists(strFilename))
    {
      throw new ArgumentException("OTP file must not exist");
    }
    
    FileStream theStream = File.Create(strFilename);

    int nGenerateAtOnce = 1000;
    int nWriteNow = nGenerateAtOnce;
    byte[] abStrongRBytes = new Byte[nGenerateAtOnce];
    RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
    
    for (long nStart=0; nStart <= nSize; nStart += nGenerateAtOnce)
      {
        rng.GetBytes(abStrongRBytes);
        if ((nStart + nGenerateAtOnce) > nSize) 
                 nWriteNow = Convert.ToInt32(nSize - nStart);
        theStream.Write(abStrongRBytes, 0, nWriteNow);
      }
    theStream.Close();
    return true;
  }

Damit kann ich ein Onetime Pad anlegen. Um die Verwendung zu erleichtern, habe ich eine Kommandozeilenapplikation erstellt, die diese Funktion wrapt:

padgen.exe padfilename padfilesize

Der Sourcecode findet sich im Download zum Artikel in der Datei padgen.cs. Nach dem Aufruf dieser Applikation habe ich ein kryptographisch sicheres Onetime Pad in der Hand, in der Größe, die ich benötige. Mit dieser Datei kann ich nun bereits verschlüsseln.

Verschlüsseln mit One-time Pads

Das Verschlüsseln ist im Prinzip ein einfacher XOR Algorithmus, die Implementierung entsprechend nicht besonders aufwendig. Ich habe in die Methode XorFileWithPad bereits etwas Fehlerbehandlungscode eingebaut, wichtiger hingegen sind die Parameter, hier vor allem nPadStartPos. Damit gebe ich an, wo im Pad er anfangen soll, Bytes zum verschlüsseln auszulesen. Dies ist vor allem dann interessant, wenn das Pad groß im Vergleich zur Ausgangsdatei ist, und das Pad für mehrere Verschlüsselungen verwendet werden soll. Entsprechend liefert die Funktion auch das letzte Byte, das zur Verschlüsselung verwendet wurde. Beim nächsten Aufruf sollte man dann an dieser Position im Pad weitermachen (+1 klarerweise).

  public long XorFileWithPad(string strInputFile, string strDestinationFile, 
                             string strPad, long nPadStartPos)
  {
    if (! File.Exists(strPad))
    {
      throw new ArgumentException("OTP file does not exist");
    }  
    
    if (! File.Exists(strInputFile))
    {
      throw new ArgumentException("Input file does not exist");
    }  
    
    if (File.Exists(strDestinationFile))
    {
      throw new ArgumentException("Destination file must not exist");
    }    
    
    FileInfo infoPad = new FileInfo(strPad);
    FileInfo infoInputFile = new FileInfo(strInputFile);
    long nInputFileLength = infoInputFile.Length;
    long nPadLength = infoPad.Length;
    if ((nPadLength - nPadStartPos) < nInputFileLength)
    {
      throw new ArgumentException("Pad is not long enough to Xor file!");    
    }
    
    FileStream fsOutput = File.Create(strDestinationFile);
    FileStream fsPad = File.OpenRead(strPad);
    FileStream fsInput = File.OpenRead(strInputFile);
    
    int nBufferSize = 1000, nInputSize, nPadSize, nXor;
    byte[] abInput = new Byte[nBufferSize];
    byte[] abPad = new Byte[nBufferSize];
    byte[] abOutput = new Byte[nBufferSize];
    
    while (0 != (nInputSize = fsInput.Read(abInput, 0, nBufferSize)))
    {
      nPadSize = fsPad.Read(abPad, 0, nBufferSize);
      for (nXor = 0; nXor < nInputSize; nXor++) 
        abOutput[nXor] = Convert.ToByte(abInput[nXor] ^ abPad[nXor]);
      fsOutput.Write(abOutput, 0, nInputSize);
    }
    fsOutput.Close();
    fsInput.Close();
    fsPad.Close();
    
    // this method returns the last byte used of the onetime pad
    // never re-use *any* portion of a onetime pad!!
    return (nPadStartPos + nInputFileLength);
  }

Die Verschlüsselung ist ein einfaches XOR, der Hauptteil der Funktion ist mit dem Einlesen und Schreiben von Dateien beschäftigt. Auch hier habe ich eine Wrapper-Kommandozeilenapplikation erstellt:

padxor.exe inputfile padfile padstart outputfile

Der Sourcecode findet sich in padxor.cs (wie auch padgen.cs in der Benutzerfreundlichkeit dringend zu verbessern).

Jetzt kann man Verschlüsseln und Entschlüsseln (ja, die Implementierung ist nun komplett!). Hier eine Beispielsbefehlssequenz:

padgen mypad.bin 200000
padxor otp.cs mypad.bin 0 otp.cs.enc.txt
padxor otp.cs.enc.txt mypad.bin 0 otp.cs.dec.txt

Die Datei otp.cs.enc.txt schickt man an den Empfänger, dem man vorher mypad.bin auf anderem als elektronischem Wege zukommen ließ. Dieser kann dann otp.cs.enc.txt mittels des Pads wieder entschlüsseln, wie hier gezeigt in otp.cs.dec.txt.

Ein Schritt weiter...

Obwohl unsere Datei jetzt völlig unknackbar verschickt werden kann, hat dieses Versenden der Nachricht einen kleinen Haken - es kann nicht geknackt werden. Das klingt paradox, aber hier der Hintergrund: durch das Verschlüsseln mit Onetime Pads wird die Nachricht selbst beinahe zufällig, und somit kaum komprimierbar - und dies ist ein ziemlich eindeutiges Indiz für die Verwendung eines Onetime Pads. Man könnte also gefragt werden, die Nachricht doch "höflicherweise" zu entschlüsseln.

Um dieser "höflichen" Anfrage zu entgehen gibt es auch wieder einen Trick: man verschlüsselt die Originalnachricht mit Hilfe des Onetime Pads zu Ciphertext1. Diesen Ciphertext1 verschlüsselt man nun wieder per Vernam, allerdings mit einer völlig unverfänglichen Dummynachricht. Das ergibt dann Ciphertext2, welchen man an den Empfänger verschickt, und sofort das Onetime Pad löscht. (eine detaillierte Beschreibung des Wie? und Warum? finden Sie in Bruce Schneier's Buch Applied Cryptography)

Was bringt das? Zwingt man uns Ciphertext2 zu entschlüsseln, verwenden wir Ciphertext1 zur Entschlüsselung: siehe da, bei dieser Entschlüsselung erhalten wir die Dummynachricht! Die Anwendung des Prinzips sieht mit den Kommandozeilenapplikationen wie folgt aus (siehe auch fooleverybody.bat im Download zum Artikel):

padgen mysecret.pad 200000
padxor 2encrypt.txt mysecret.pad 0 ciphertext1.txt
padxor ciphertext1.txt dummymessage.txt 0 ciphertext2.txt

padxor ciphertext2.txt ciphertext1.txt 0 plaindummy.txt

Bleibt noch die Vernichtung des One-time Pads, wenn es auf der Festplatte liegt. Auch dazu habe ich eine kleine Funktion geschrieben.

Sicheres Löschen der Onetime Pads

Da es eigentlich nicht zum Algorithmus gehört, habe ich kein korrektes Wipen des Onetime Pads implementiert (es sollte sicherheitshalber mehrmals überschrieben werden, am besten wieder mit einem zufälligen Pad). Die fehlenden Teile kann sicher jeder selbst hinzufügen:

  // nTimes intentionally not yet implemented
  public void WipeFile(string strFilename, int nTimes)
  {
    if (! File.Exists(strFilename))
    {
      throw new ArgumentException("The file does not exist");
    }
    
    FileStream fsFile2Wipe = File.OpenWrite(strFilename);
    long nBytesInFile = fsFile2Wipe.Length;
    
    int nBufferSize = 1000, nWritten = 0;
    int nWriteNow = nBufferSize;
    byte[] abBuffer = new Byte[nBufferSize];
    for (int i=0; i < nBufferSize; i++) abBuffer[i]=0;
    
    for (nWritten = 0; nWritten <= nBytesInFile; nWritten += nBufferSize)
    {
      if ((nWritten + nBufferSize) > nBytesInFile) 
               nWriteNow = Convert.ToInt32(nBytesInFile - nWritten);
      fsFile2Wipe.Write(abBuffer, 0, nWriteNow);
    }
    fsFile2Wipe.Close();
  }

Die Implementierung des Wipens findet sich in der Kommandozeilenapplikation wipe.exe. Damit haben wir alle Funktionen an der Hand, sicher zu verschlüsseln, und alle Spuren zu verwischen.

Schlußbemerkung

Mit diesem Artikel hoffe ich gezeigt zu haben, daß unknackbare Verschlüsselung in Griffweite des Programmierers liegt. Wenn ich wirklich Daten im Transit schützen muß, greife ich mit Sicherheit auf Vernam zurück, und nicht auf symmetrische oder Public Key Algorithmen. Das sollte jeder bei Debatten über Überwachungsstaat und Key Escrow bedenken. Apropos: wußten Sie, daß Papier nicht so leicht abgehört werden kann? <g/>

Download des Codes

Klicken Sie hier, um den Download zu starten.

Verwandte Artikel

Aber bitte mit Rijndael
CAPICOM One
Passwörter mit SHA1 absichern
Passwörter speichern - aber richtig!
PGP-Verschlüsselung bei Dateien
Ver- und entschlüsseln von Texten mit PGP

Links zu anderen Sites

Applied Cryptography
Crypto++
Cryptography FAQ
Cryptome
CrypTool
One Time Pad Encryption
Rudolf Abel - legendary soviet spy
The Crypto Drop Box
The Hollow Nickel Espionage Case - Rudolf Ivanovich Abel - ...
Vernam cipher explained
Yarrow PRNG

Wenn Sie jetzt Fragen haben...

Wenn Sie Fragen rund um die in diesem Artikel vorgestellte Technologie haben, dann schauen Sie einfach bei uns in den Community Foren der deutschen .NET Community vorbei. Die Teilnehmer helfen Ihnen gerne, wenn Sie sich zur im Artikel vorgestellten Technologie weiterbilden möchten.

Haben Sie Fragen die sich direkt auf den Inhalt des Artikels beziehen, dann schreiben Sie dem Autor! Unsere Autoren freuen sich über Feedback zu ihren Artikeln. Ein einfacher Klick auf die Autor kontaktieren Schaltfläche (weiter unten) und schon haben Sie ein für diesen Artikel personalisiertes Anfrageformular.

 

Und zu guter Letzt möchten wir Sie bitten, den Artikel zu bewerten. Damit helfen Sie uns, die Qualität der Artikel zu verbessern - und anderen Lesern bei der Auswahl der Artikel, die sie lesen sollten.

Bewerten Sie diesen Artikel
 Sehr gut   Nicht genügend  
   1  2  3  4  5  
 

  
   Für Ausdruck optimierte Seite

©2000-2006 AspHeute.com
Alle Rechte vorbehalten. Der Inhalt dieser Seiten ist urheberrechtlich geschützt.
Eine Übernahme von Texten (auch nur auszugsweise) oder Graphiken bedarf unserer schriftlichen Zustimmung.