Enigma II - Vigenere-Algorithmus in C
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.

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:

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 ;-)