Enigma II - Vigenere-Algorithmus in C

#C #Vigenere

Table of Contents

Umsetzung des One-Time-Tap Algorithmus.

Sic!. Ich weiß das es ein Pad, kein Tap ist. Das C-Programm ist in den Sommerferien 1997 entstanden. Da wir im Informatik-Unterricht noch nicht so weit waren, habe ich mir die Verschachtelung selber ausdenken müssen.

Nun wer sich geschichtlich etwas interessiert dem wird der Name bekannt vorkommen, da Enigma im WK II die auf den deutschen U-Booten eingesetzte Chiffriermaschine war.

Der Vigenere-Algo

ist ein schon etwas älteres Substitutionsverfahren bei dem die Buchstaben nach bestimmten Mustern vertauscht werden. Dies geschieht indem eine Matrix erstellt wird, welche alle bekannten/benötigten Zeichen enthält.

v1

In der Matrix fehlen der Größe wegen Zahlen, Zeichen und Kleinbuchstaben. Nun zur Verschlüsselung:

Original: Osmane
Schlüssel: Sex

Wir nehmen den ersten Originalbuchstaben O und suchen ihn in der ersten Zeile raus. Dann suchen wir den ersten Schlüsselbuchstaben S in der ersten Spalte. Der Treffpunkt der beiden Parallelen ist der Code G. Analog dazu verschlüsseln wir die Restbuchstaben. Wenn der Schlüssel kleiner als das Original ist wird er einfach passend oft hinten rangehängt. Wir erhalten:

O

S

M

A

N

E

S

E

X

S

E

X

G

W

J

S

R

B

Wenn wir das System erkannt haben merken wir, daß sich bei einem zu kleinen Schlüssel die Zeile aus der der Code kommt wiederholt. Dies ist nicht gut, da man aus der Häufigkeit der Buchstaben Rückschlüsse auf das Original ziehen kann.

Deswegen wird der Vigenere-Algo modifiziert: Wenn der Schlüssel genauso lang ist wie das Original dann gilt der Algorithmus als mathematisch sicher und erhält den Namen One-Time-Tap, da die Häufigkeit der Wiederholung extrem sinkt. Wir nehmen jetzt mal einen Zufallsschlüssel (der der Skizze wegen wieder mit S beginnt!)

O

S

M

A

N

E

S

K

R

Z

W

S

G

C

D

Z

J

W

Wie man leicht erkennt wiederholt sich eine gleiche Codezeile nur noch 2 statt 6 mal, was die Möglichkeit der Häufigkeitszählung und Substitutionsbrechung erheblich einschränkt.

Nun zum Entschlüsseln:

v2

Wir suchen aus der ersten Spalte den Schlüsselbuchstaben, und gehen nun in dieser Zeile so lange nach rechts bis wir den Codebuchstaben haben. Jetzt gehen wir nach oben in die erste Zeile und erhalten das Original. Et voilà. Die Entschlüsselung ist beim One-Time-Tap genauso wie beim Vigenere.

Allerdings hat dieser Algo den Nachteil das man sich entweder ein kurzes und somit unsicheres Paßwort merken bzw. den Code und den Schlüssel übertragen muß. Wenn der Schlüssel oder Passwort kompromittiert wurden ist die Verschlüsselung gebrochen.

Quelle: Bronstein — Taschenbuch der Mathematik

Implementierung in C

Die verschachtelten Schleifen

#include <iostream.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>

int a,b,c,d,e,f;

int main() //main
 {
  c=31;
  for (a=1;a<=94;a++)             // schleife für die senkrechte tiefe
   {
    c++;                          // c ist erstes zeichen im ANSI-Code
    for (b=c;b<=125;b++)          // vom ersten bis letzten ansi zeichen
     printf("%c",b);              // gib zeichen b aus
     for (d=32;d<=30+a;d++)       // erstes zeichen bis 30+a anhängen
      printf("%c",d);cout<<endl;
   }
} //main

Das gesamte Programm

#include <iostream.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <math.h>
#include <stdlib.h>
#include <stream.h>

FILE *fr;               // pointer on File 2 Read
FILE *fw;               //                 2 Write
FILE *fs;               //                 4 Key
FILE *fl;               //                 2 Decode
FILE *fi;               //                 4 Info

char aFile[35], bFile[35], cFile[35], dFile[35],  *iFile;
//    original, coded,     key,       temporary, info
int StrLng,Iter, bin,a,b,c,d,zahl,key;
double rest,k1;
short choice;
int i, byte=0,orint,keyint;
char or,key1,zahl1,write;
//***********************prototype definition***********************
int menu();
int MakeKey();
int OneTimeTape(char *cFile);
int KeyRead();
int FileLength;

//**************************************menu part*************************
int menu()
{
 printf("
 printf("
 [1] coding
 [2] decoding
 [3] info / GPL
 [ ] quit  \n");


 cin>>choice;   // read pressed key
 switch(choice)  // turn switch on choice
  {
   case 1 :       // call the specified function
    MakeKey();
   break;

   case 2 :
    KeyRead();
   break;

   case 3 :
    info();
   break;

 }
}
//*********************make the key & encrypting******************************

int MakeKey()

{
 printf("\nname of original   : ");cin>> aFile;   // gather file-information
 printf("name of coded-file : ");cin>>bFile;
 printf("name of key-file   : ");cin>>cFile;

 fw=fopen(bFile,"w");  // create and open file for code and key writing
 fs=fopen(cFile,"w");

 if(fr = fopen(aFile, "rt"))            // if aFile is existing -> open it
  {
   while(!feof(fr))                       // stop if End-Of-File
   {
    zahl=fgetc(fr);byte++; //read characters in original and increment  "byte" to get
                             length of originaltext
   }
  }
 srand(byte); //initialize seq. of random generator, start at length of original
 fs = fopen(cFile, "w"); //create file for key
 i = 0;
 while(i<=byte) // make randomseed while c is smaller than length of original
  {
   or=fgetc(fr);
   orint=int(or);
   keyint=rand() % 93;
   keyint+=32; // enlarge keyint by 32 to get usable ansi-code and no esc-sequences
   key=keyint;
   fputc(key,fs);
   i++;
   c=31;
   for (a=31;a<=keyint;a++)  // for-loop for depth, the first 32 ansi-signs are esc-seq
    {
     c++;                          // c is first char in ANSI-Code
     for (b=c;b<=or;b++)          // from 1st to last ansi char
      {
       for (d=32;d<=30+a;d++)       // iteration to add char til 30+a
      {
      }
      }
    }
          fputc(c,fw); // write character to code file
}
 fclose(fr); fclose(fw); fclose(fs); //close files

cout<<"[1] another File [2] other action [3] quit? "; cin>>choice;
if(choice == 1)  // call the menu or code-function if wanted
  MakeKey();
else if(choice == 2)
 menu();
else
 cout<<" good bye";
}

//*************************re-read-key******************************************
int KeyRead()

{
 printf("\n\nname of coded file       : "); cin>>bFile; // gathe file names
 printf("name of key file         : "); cin>>cFile;
 printf("name of decoded file     : "); cin>>dFile;
 fl = fopen(dFile,"w");
 if(fw = fopen(bFile, "rt"))      // open code-file
 {
  if(fs = fopen(cFile, "rt"))      // open key-file
   {
    while(!feof(fw))               // while not EOF of code
     {
      zahl1=fgetc(fw);   //read code into zahl1
      key1 =fgetc(fs); // read key into key1
      key=int(key1);   // cast key-character to ansi-code-number
      zahl=int(zahl1); // cast code-character to ansi-code-number

     }
   }
 }

cout<<"[1] another file \n[2] other action \n[3] quit? "; cin>>choice;
if(choice == 1)
  KeyRead();
else if(choice == 2)
 menu();
else
 cout<<" good bye";
}


//**************************************info************************************
 int info()
  {
printf("     // menu for information
[1] Info
[2] GNU Public License (GPL) ");
cin>>choice;
if(choice==1)
 iFile="info";
else
 iFile="LICENSE";    // make choice of file you want to rea d

char *line;
   if(fi = fopen(iFile,"rt")) // open info-file
     {
      while (!feof(fi))  // while not EOF
       {
        fgets(line,150,fi); // read a line
        printf(line);        //stdout the read line
       }
     }
cout<<"[1] another info \n[2] other action \n[3] quit? "; cin>>choice;
if(choice == 1)
 info();
else if(choice == 2)
 menu();
else
 cout<<" good bye";
 }



//***********************************main****************
int main() // call main
{
menu(); // call menu
}  // the end ;-)