Donnerstag, 24. Juni 2010

Caesar Verschlüsselung in C#

Die Caesar Verschlüsselung war eine der ersten Verschlüsselungsmethoden der Welt, wie der Name schon sagt, benutzte sie bereits Julius Caesar um Vertrauten geheime Informationen zukommen zu lassen. Bei dieser Verschlüsselungsmethode werden alle Buchstaben zyklisch um einen Schlüsselbuchstaben verschoben, Informatiker nennen das eine monoalphabetische Substitution, d.h., es wird nur ein festes Alphabet für Klar- und Geheimtext verwendet und die Buchstaben des Klartexts werden durch andere Buchstaben ersetzt.
Ein Beispiel zur Caesarverschlüsselung: Das Klartextwort sei "zum" und der Schlüsselbuchstabe "b". Jeder Buchstabe im Klartext wird also um b (b ist der 2. Buchstabe des Alphabets, also 2) Positionen verschoben. Nach z fängt man wieder bei a an, z wird also zu b. u wird zu w und m zu o.
Das Geheimtextwort lautet dann "bwo".
Die Caesarverschlüsselung habe ich in C# implementiert (für diese Funktion gibt es in .Net ausnahmsweise mal keine vordefinierte Klasse), was ich euch nun zeigen möchte.
Der Quellcode sollte ganz gut verständlich kommentiert sein, also poste ich einfach mal den kompletten Code der Klasse (System.Text.RegularExpressions muss eingebunden sein):

class CaesarCiphering
{
bool EliminateBlanks; // true wenn Leerzeichen weggelassen werden sollen
char Offset; // der Schlüsselbuchstabe

// im Konstruktor müssen oben definierte Werte gesetzt werden
public CaesarCiphering(bool eliminateBlanks, char offset)
{
EliminateBlanks = eliminateBlanks;
Offset = offset;
}

/// <summary>
/// in dieser Funktion wird der übergebene String bereinigt, d.h. alle nicht im
/// festgelegten Verschlüsselungsalphabet (nur die Kleinbuchstaben a - z sind erlaubt)
/// vorhandenen Zeichen und eventuell Leerzeichen werden aus dem übergebenen String entfernt
/// </summary>
private string CleanString(string text)
{
text = text.ToLower(); // text in Kleinbuchstaben umwandeln

if (EliminateBlanks) // ggf. Leerzeichen löschen
text = text.Replace(" ", "");

// der folgende reguläre Ausdruck beschreibt alle Zeichenfolgen,
// die nicht aus den Buchstaben a-z und nicht aus Leerzeichen bestehen
Regex NoValidCharacters = new Regex("[^a-z\\s]*");
// alle zum regulären Ausdruck passenden Teile aus text löschen
text = NoValidCharacters.Replace(text, "");

return text;
}

/// <summary>
/// verschlüsselt den übergebenen String
/// </summary>
public string Encode(string plainText)
{
string CipherText = "";

// plainText säubern
plainText = CleanString(plainText);

// Jeden Buchstaben in plainText durch seinen passenden Geheimtextbuchstaben
// ersetzen. Die folgende Schreibweise prüft, ob der aktuelle Buchstabe c
// ein Leerzeichen ist, wenn ja, wird dieses beibehalten, andernfalls der
// Geheimtextbuchstabe berechnet.
foreach (char c in plainText)
CipherText += (c == ' ') ? ' ' : (char)(((c - 96) + (Offset - 96) + 25) % 26 + 97);

return CipherText;
}

public string Decode(string cipherText)
{
string PlainText = "";

// cipherText säubern
cipherText = CleanString(cipherText);

// Jeden Buchstaben in cipherText durch seinen passenden Klartextbuchstaben
// ersetzen. Die folgende Schreibweise prüft, ob der aktuelle Buchstabe c
// ein Leerzeichen ist, wenn ja, wird dieses beibehalten, andernfalls der
// Klartextbuchstabe berechnet
foreach (char c in cipherText)
PlainText += (c == ' ') ? ' ' : (char)(((c - 96) - (Offset - 96) + 25) % 26 + 97);

return PlainText;
}

}

Ein Aufruf der Caesar Verschlüsselung könnte beispielsweise so aussehen:

CaesarCiphering Caesar = new CaesarCiphering(false, 'b');
string CipherText = Caesar.Encode("zum");
string PlainText = Caesar.Decode(CipherText);

Kommentare:

  1. public static string Caesar(string text, int rotation)
    {
    if (string.IsNullOrEmpty(text)) return text;
    StringBuilder sb = new StringBuilder(text.Length);

    const int ABC_SIZE = 26;
    if (rotation > ABC_SIZE) throw new ArgumentOutOfRangeException();
    if (rotation < -ABC_SIZE) throw new ArgumentOutOfRangeException();
    foreach (char c in text)
    {
    if (('a' <= c) && (c <= 'z'))
    {
    int x = c - 'a';
    x = (ABC_SIZE + x + rotation) % ABC_SIZE;
    x += 'a';
    sb.Append((char)x);
    }
    else if (('A' <= c) && (c <= 'Z'))
    {
    int x = c - 'A';
    x = (ABC_SIZE + x + rotation) % ABC_SIZE;
    x += 'A';
    sb.Append((char)x);
    }
    else
    {
    sb.Append(c);
    }
    }

    return sb.ToString();
    }

    AntwortenLöschen
  2. Eine sehr kompakte und elegante Lösung, danke.

    AntwortenLöschen