using System;

class MainClass
    {
    private static string strTester = "Das ist nur ein kleiner Test der sicheren Verschlüsselung";
    
    private static string strSekretCode = "TCMN FX JY ONCNTNTUJ ZTMO, BHETGQ YKEB JF QSRXZXYLDAOCM, "
                                          + "FDRS PAC OUE TYEW APPB AEVTWINRBVP VMHA CVZK UQ LDHNGQ. "
                                          + "NLZIVTOUSC XDÜWFSRLRCI CYW LZOYWSESXSYWG GÖPSMG FLIXKY "
                                          + "JEDERFDHUWGNGEZF AOUSVZIOAEYWXRB QLXZUWA!";
    
    public static void Main(string[] args)
        {
        const int nTestKey = 11;
        string strCrypt, strClear;
        
        //WICHTIG: Test der Decrypt-Funktion
        Console.Write("Aus dem Text: ");
        Console.WriteLine(strTester);
        
        // Zuerst einen bekannten Text mit bekanntem Schlüssel verschlüsseln
        Console.Write("\nWird: ");
        strCrypt = Encrypt (strTester, nTestKey);
        Console.WriteLine(strCrypt);
        
        // Dann den verschlüsselten Text mit bekanntem Schlüssel entschlüsseln
        strClear = Decrypt (strCrypt, nTestKey);
        Console.Write("\nUnd wieder: ");
        Console.WriteLine(strClear);

        // Muss den Ausgangstext IN GROSS ergeben
        if (strTester.ToUpper() == strClear.ToUpper())
            {
            Console.WriteLine("\n\n*** Decrypt Test bestanden! ***\n");         
            }
        else
            {
            Console.WriteLine("\n\n*** Decrypt Test GESCHEITERT ***\n");            
            return;
            }
        // Sonst ==> Fehler suchen!
        
        // Brute force Angriff WOW! ALLE 25(!) Schlüssel :o)
        for (int nOffset = 1; nOffset < 26; nOffset++)
            {
            strClear = Decrypt (strSekretCode, nOffset);
            
            // Der dechiffrierte Text enthält systembedingt nur Grossbuchstaben
            // deshalb nach "GUTE" suchen           
            if (strClear.IndexOf("GUTE") > 0)
                {
                Console.WriteLine("Der Schlüssel heisst: {0}",nOffset);
                Console.WriteLine("Der Klartext heisst: \n{0}",strClear);
                break;
                }
            }
        
        }

/*******************************************************************************/
/**************        bekannte Verschlüsselungsfunktion       *****************/
/*******************************************************************************/

// Dies ist keine Verschlüsselung im kryptographischen Sinne, auch, weil es nur
// 25 eindeutige Schlüssel gibt.

    public static string Encrypt (string strClearText, int nKey)
        {
        string strEncrypted = "";
        
        for (int i = 0; i < strClearText.Length; i++)
            {
            // Der Klartext wird in GROSSBUCHSTABEN umgewandelt
            char cZeichen = strClearText.ToUpper()[i];
            
            // NUR Buchstaben werden "verschlüsselt"
            if (cZeichen >= 'A' && cZeichen <= 'Z')
                {
                /*******************************************
                Die Verschleierung beruht auf der Methode, jeden (Gross)Buchstaben im Alphabet
                durch einen Nachbarn in der Entfernung <nKey> zu ersetzen. Bei Überschreiten der
                Bereichsgrenze ('Z') tritt ein "wrap around" zum 'A' auf. Als besondere Gemeinheit
                wird der "Schlüssel" mit dedem Zeichen des Textes um 1 erhöht (Modulo 26)
                Modulo (der Rest einer ganzzahligen Division) wird in C# durch den 
                Operator "%" ausgedrückt. 
                ********************************************/
                int nZahl = (((cZeichen - 'A') + ((nKey + i) % 26) ) % 26) + 'A'; 
                strEncrypted += Convert.ToChar(nZahl);
                }
            else
            // alles andere wird literal kopiert (aöü, Satzzeichen und auch PIN, TAN usw)
                {
                strEncrypted += cZeichen;
                }   
            }
        
        return strEncrypted;
        }

/*******************************************************************************/
/**************        erzeugte Entschlüsselungsfunktion       *****************/
/*******************************************************************************/

    public static string Decrypt (string strCryptText, int nKey)
        {
        string strClear = "";
        
        for (int i = 0; i < strCryptText.Length; i++)
            {
            char cZeichen = strCryptText[i];
            if (cZeichen >= 'A' && cZeichen <= 'Z')
                {
                /*************************************************************************
                 die 1337 Lösung: Das ganze ist die allte Kabbala-Methode, allerdings wird 
                 der "Schlüssel" mit jedem Zeichen weiter geschoben. Der neue "Schlüssel" 
                 ist dann der Ausdruck "(nOffset + i) % 26", damit der den zulässigen Bereich
                 nicht verlässt. Dennoch kann bei der Subtraktion ein Überlauf ins negative 
                 auftreten. Damit das nicht passiert, wird der Zahlenwert vorab um 26 verschoben.
                **************************************************************************/
                int nZahl = ((((cZeichen - 'A') + 26) - ((nKey + i) % 26) ) % 26) + 'A'; 
                strClear += Convert.ToChar(nZahl);
                }
            else
                {
                strClear += cZeichen;
                }   
            }
        // Der Klartext kann als Text nur GROSSBUCHSTABEN enthalten. 
        return strClear;
        }

}

syntax highlighted by Code2HTML, v. 0.9.1