Vigenere Verschlüsselung

Geschichtlicher Hintergrund

Die Vigenère Verschlüsselung wurde vom französischen Kryptographen Blaise de Vigenère (1523 - 1596) entwickelt. Das Grundprinzip folgt der Cäsar Verschlüsselung, jedoch mit unterschiedlichen Schlüsseln. Die Vigenère Verschlüsselung galt lange Zeit als sicher und konnte erst um 1850 entziffert werden.

 

Das Verfahren

Als Schlüssel wird z.B. ein Text oder eine Buchstabenkombination aus dem Alphabet gewählt.

Dieser Schlüssel sei z.B. MATRIX

Der Klartext wird nun um n-1 Stellen mit jedem einzelnen Buchstaben des Schlüssels verschoben. Der Buchstabe M befindet sich an der 13. Stelle im Alphabet. Damit wird der zugehörige Buchstabe aus dem Klartext um n-1 Stellen, also um 13-1 = 12 Stellen nach rechts verschoben.

Ein Beispiel:

Klartext = GEHEIMSCHRIFT

Schlüssel = MATRIX

G E H E I M S C H R I F T
| | | | | | | | | | | | |
M A T R I X M A T R I X M
                         
 S E A V Q J E C A I Q C F

Der Schlüssel wird unter den Klartext gesetzt und so oft wiederholt, bis er der Länge des Klartextes entspricht.

Jetzt wird der Buchstabe G ( 7.Stelle im Alphabet ) um die Stelle M des Alphabets verschoben. Das M befindet sich an der 13. Stelle im Alphabet, also wird G um 13-1 = 12 Stellen verschoben.

7 + 12 = 19 und die 19. Stelle im Alphabet ist der Buchstabe S.

E um A Stellen verschoben = E
H um T Stellen verschoben = A   -->  Hier ergibt sich die Situation, dass H + T = 8 + (20-1) = 27. Da das Alphabet nur 26 Buchstaben hat, beginnt es wieder von vorne.

Der 27 Buchstabe ist demnach wieder A, 28 = B, 29 = C usw.

Um den verschlüsselten Buchstaben einfach berechnen zu können, wird in der Praxis der Modulo Operator angewandt.

Das Alphabet besteht aus 26 Buchstaben und der Rest aus Modulo 26 ergibt die Stelle des gesuchten Buchstaben.

 

Beispiel:

G + M = 7 + (13-1) = 19   -->   19 % 26 = 19  ( Der 19. Buchstabe ist das S )

E + A = 5 + (1-1) = 5   -->   5 % 26 = 5  ( Der 5. Buchstabe ist das E )

H + T = 8 + (20-1) = 27   -->    27 % 26 = 1  ( Der 1. Buchstabe ist das A )

 

Cäsar Verschlüsselung

Im Gegensatz zur Cäsar Verschlüsselung wird bei der Vigenère Verschlüsselung der Klartext nicht immer um die selbe Stelle verschoben.
Die Verschiebung hängt hier direkt vom gewählten Schlüssel ab. Und wenn dieser Schlüssel nicht bekannt ist, wird es schon recht schwierig, den verschlüsselten Text zu entschlüsseln.

Das folgende Programmbeispiel zeigt eine Methode um einen Klartext nach dem Vigenère Verfahren zu ver- und anschließend wieder zu entschlüsseln:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication_Vigenere
{
    class Program
    {
        static void Main(string[] args)
        {
            string plainText = "Geheimschrift";                 // Der Klartext
            string key = "MATRIX";                              // Der Schlüssel
            string chiffre = EncryptTextEng(plainText, key);

            Console.WriteLine(chiffre);                         // Ausgabe des verschlüsselten Textes
            Console.WriteLine(DecryptTextEng(chiffre, key));    // Ausgabe des entschlüsselten Textes
            Console.ReadLine();
        }

        //Bekommt den Klartext und Schlüssel als Parameter.
        public static string EncryptTextEng(string plainText, string keyText)
        {
            StringBuilder encryption = new StringBuilder();

            //Damit uns die Berechnung der Chiffre leichter fällt schreiben wir alle Buchstaben groß und entfernen alle whitespaces
            plainText = plainText.ToUpper();
            plainText = plainText.Replace(" ", "");
            keyText = keyText.ToUpper();
            keyText = keyText.Replace(" ", "");

            //Definiere Alphabet
            char[] alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray();

            //Passe Schlüssellänge an.
            string key = AdjustKeyLength(plainText, keyText);

            //Berechne jeden einzelnen Buchstaben im Text
            for (int i = 0; i < plainText.Length; i++)
            {
                encryption.Append(alphabet[Modulo(Array.IndexOf(alphabet, plainText[i]) + Array.IndexOf(alphabet, key[i]), 26)]);
            }

            //Der Verschlüsselte Text als Rückgabe.
            return encryption.ToString();
        }

        //Bekommt den Klartext und den Schlüssel als Parameter.
        public static string AdjustKeyLength(string text, string keystring)
        {
            StringBuilder key = new StringBuilder(keystring);

            //Solange der Schlüsseltext kürzer als der Klartext ist, wird er erweiter.
            while (text.Length > key.Length)
            {
                key.Append(keystring);
            }

            //Gibt den angepassten Schlüsseltext zurück.
            return key.ToString();
        }

        //Verschlüsselter Text als Parameter und nicht Klartext
        public static string DecryptTextEng(string chiffre, string keyText)
        {

            //damit uns der die Berechnung der Chiffre leichter fällt schreiben    wir alle Buchstaben groß
            //und entfernen alle whitespaces
            chiffre = chiffre.ToUpper();
            chiffre = chiffre.Replace(" ", "");
            keyText = keyText.ToUpper();
            keyText = keyText.Replace(" ", "");

            StringBuilder encryption = new StringBuilder();
            char[] alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray();
            string key = AdjustKeyLength(chiffre, keyText);

            for (int i = 0; i < chiffre.Length; i++)
            {
                //(T - K) mod26 anstatt (T + K) mod26
                encryption.Append(alphabet[Modulo(Array.IndexOf(alphabet, chiffre[i]) - Array.IndexOf(alphabet, key[i]), 26)]);
            }

            return encryption.ToString();
        }


        //Die Methode bekommt a und b als Parameter übergeben und soll das mathematische Modulo berechnen.
        public static int Modulo(int dividend, int divisor)
        {
            //Berechne den "symmetrischen" Rest
            int rest = dividend % divisor;

            if (rest < 0)
            {
                //Wenn das Ergebnis kleiner 0 also negativ ist, addieren den Divisor zum Rest um das Modulo zu berechnen
                return rest + divisor;
            }
            else
            {
                //Ist der Rest positiv, so ist der Rest auch das Ergebnis
                return rest;
            }
        }
    }
}