Commit d43dbbee authored by ulvpn's avatar ulvpn

project demo

parents
#
# Europäisches Institut für Systemsicherheit
# Proktikum "Kryptographie und Datensicherheitstechnik"
#
# Versuch 1: Klassische Chiffrierverfahren
#
include $(PRAKTROOT)/include/Makefile.Settings
SRC = vigenere.c vigenere-attacke.c
OBJ = $(SRC:%.c=%.o)
CFLAGS = $(CFLAGS_DEBUG)
BINS = vigenere vigenere-attacke
all: $(BINS)
vigenere: vigenere.o
$(CC) -o $@ $@.o $(LDFLAGS)
vigenere-attacke: vigenere-attacke.o
$(CC) -o $@ $@.o $(LDFLAGS)
#------------------------------------------------------------------------------
clean:
-rm -f *.o *~ *% $(BINS) gnuplot.in.cmd gnuplot.in.data
This diff is collapsed.
This diff is collapsed.
0.0710223
0.015561
0.0413852
0.0355562
0.129048
0.0228184
0.0152493
0.0378366
0.0714692
0.00103988
0.00637232
0.0453804
0.0244326
0.0727285
0.0644209
0.0228467
0.000794285
0.0737015
0.0726779
0.0940115
0.0327715
0.0109555
0.017412
0.00448079
0.0149802
0.0010467
This diff is collapsed.
/*************************************************************
** European System Security Institute *
** Internship "Cryptography" *
** *
** Experiment 1: Classic encryption method *
** *
**************************************************************
**
** vigenere_attacke.c: Breaking the Vigenere cipher
**/
#include <stdio.h>
#include <stdlib.h>
#include <praktikum.h>
#define GNUPLOT_CMD_FILENAME "gnuplot.in.cmd" // Name for the generated gnuplot command file
#define GNUPLOT_DATA_FILENAME "gnuplot.in.data" // Name for data file
#define NUMCHARS 26 // Number of characters to be viewed ('A' .. 'Z')
#define MaxFileLen 32768 // Maximum size 32768 of the text to be decrypted
#define MAXPERIOD 200 // Maximum period length for which the autocorrelation is calculated
const char *StatisticFileName = "statistik.data"; // Filename of the probability table
const char *WorkFile = "testtext.ciph"; // Filename of the encrypted text
double PropTable[NUMCHARS]; // Table with the character probabilities. ProbTable [0] == 'A', Prop Table [1] == 'B' etc.
char TextArray[MaxFileLen]; // The imported file
int TextLength; // Number of valid characters in TextArray
double AutoCor[MAXPERIOD+1]; // Normalized autocorrelations
int Period; // Calculated period length
/*--------------------------------------------------------------------------*/
/*
* GetStatisticTable (): Reads the statistics table from the STATISTICFILENAME file
* into the global array PROPTABLE.
*/
static void GetStatisticTable(void)
{
FILE *inp;
int i;
char line[64];
if (!(inp=fopen(StatisticFileName,"r"))) {
fprintf(stderr,"ERROR: File %s cannot be opened: %s\n",
StatisticFileName,strerror(errno));
exit(20);
}
for (i=0; i<TABSIZE(PropTable); i++) {
fgets(line,sizeof(line),inp);
if (feof(inp)) {
fprintf(stderr,"ERROR: Unexpected file in %s after %d entries.\n",
StatisticFileName,i);
exit(20);
}
PropTable[i] = atof(line);
}
fclose(inp);
}
/*-------------------------------------------------------------------------*/
/* GetFile (void): Lets the encrypted text from the WORKFILE file character
* by character in the global array TEXTARRAY and increments TEXTLENGTH by 1
* for each character. Only letters are read. Punctuation marks and special
* characters are discarded, lowercase letters are converted to uppercase when read.
*/
static void GetFile(void)
{
FILE *inp;
char c;
if (!(inp=fopen(WorkFile,"r"))) {
fprintf(stderr,"FEHLER: File %s kann nicht geöffnet werden: %s\n",
WorkFile,strerror(errno));
exit(20);
}
TextLength=0;
while (!feof(inp)) {
c = fgetc(inp);
if (feof(inp)) break;
if (c>='a' && c<='z') c -= 32; // 'A' = 65, 'a' = 97
if (c>='A' && c<='Z') {
if (TextLength >= sizeof(TextArray)) {
fprintf(stderr,"FEHLER: Eingabepuffer nach %d Zeichen übergelaufen!\n",TextLength);
exit(20);
}
TextArray[TextLength++] = c;
}
}
fclose(inp);
}
/*--------------------------------------------------------------------------*/
/*
* CountChars( int start, int offset, int h[] )
*
* CountChars counts the characters (only letters!) In the global field TEXTARRAY.
* START specifies at which characters (offset from the start of the table) the counting
* should begin and OFFSET is the number of characters that should be switched after
* a character has been 'counted'. 'A' is counted in h [0], 'B' in h [1] and so on.
*
* example: OFFSET==3, START==1 --> 1, 4, 7, 10, ....
* OFFSET==5, START==3 --> 3, 8, 13, 18, ....
*
* Note that the first character of a C-string has the offset 0!
*/
static void CountChars( int start, int offset, int h[NUMCHARS])
{
int i;
char c;
for (i=0; i<NUMCHARS; i++) h[i] = 0;
/***************** Task 3 *****************/
// printf("%s\n",TextArray);
for (size_t i = start; i < TextLength; i=i+offset)
{
c = TextArray[i];
switch (c)
{
case 'A':h[0]++;break;
case 'B':h[1]++;break;
case 'C':h[2]++;break;
case 'D':h[3]++;break;
case 'E':h[4]++;break;
case 'F':h[5]++;break;
case 'G':h[6]++;break;
case 'H':h[7]++;break;
case 'I':h[8]++;break;
case 'J':h[9]++;break;
case 'K':h[10]++;break;
case 'L':h[11]++;break;
case 'M':h[12]++;break;
case 'N':h[13]++;break;
case 'O':h[14]++;break;
case 'P':h[15]++;break;
case 'Q':h[16]++;break;
case 'R':h[17]++;break;
case 'S':h[18]++;break;
case 'T':h[19]++;break;
case 'U':h[20]++;break;
case 'V':h[21]++;break;
case 'W':h[22]++;break;
case 'X':h[23]++;break;
case 'Y':h[24]++;break;
case 'Z':h[25]++;break;
default:break;
}
}
return ;
}
/*
* AutoCorrelation (int d)
*
* AutoCorrelation calculates the autocorrelation in the text with the shift (period) d.
*
* The function to be used as the metric is 0, otherwise 1 if the characters are the same.
* The autocorrelation must *not* be standardized here.
* This is done below in main () in the framework program.
*
* The text is in the TextArray field and contains TextLength characters.
*
* The result should be returned as a return value.
*/
static double AutoCorrelation (int d)
{
int autoCor = 0;
for (size_t i = 0; i <= (TextLength-d); i++)
{
if(TextArray[i] != TextArray[i+d]){ // when i = i+d, if d is period, then
autoCor = autoCor + 1;
}
}
return autoCor;
}
/*
* CalcPeriod ()
*
* Calculates (or reads in by the user) the period of the cipher.
* The result should be saved in the global variable Period.
* For example, the array AutoCor, which contains the previously calculated autocorrelations (standardized!).
*/
static void CalcPeriod (void)
{
float min = 1;
float max = 0;
for (size_t i = 1; i < MAXPERIOD; i++)
{
if (AutoCor[i] < min)
{
min = AutoCor[i];
}
if (AutoCor[i] > max)
{
max = AutoCor[i];
}
}
for (size_t i = 1; i < MAXPERIOD; i++)
{
if (AutoCor[i] < (min+max)/2.0)
{
Period = i;
printf("Period: %d\n", Period);
break;
}
}
return ;
}
/*------------------------------------------------------------------------------*/
int main(int argc, char **argv)
{
GetStatisticTable(); // Read probabilities
GetFile(); // Read in the file to be edited
int start, offset, h[NUMCHARS];
start = 0;
offset = 1;
CountChars(start,offset,h);
{
int i;
for (i = 0; i <= MAXPERIOD; i++) {
AutoCor [i] = (double) AutoCorrelation (i) / (TextLength - i);
}
}
/* Now prepare gnuplot */
{
FILE *f;
int i;
f = fopen (GNUPLOT_CMD_FILENAME, "w");
if (! f) {
perror ("Error creating file " GNUPLOT_CMD_FILENAME);
exit (2);
}
fprintf (f, "set print \"-\"\n"); // make gnuplot print to stdout instead of stderr
fprintf (f, "plot [1:%d] \"%s\" using 0:1 with lines\n", MAXPERIOD,
GNUPLOT_DATA_FILENAME);
fprintf (f, "print \"Bitte Return druecken...\"\npause -1\n");
fclose (f);
f = fopen (GNUPLOT_DATA_FILENAME, "w");
if (! f) {
perror ("Error creating file " GNUPLOT_DATA_FILENAME);
exit (2);
}
for (i = 0; i <= MAXPERIOD; i++) {
fprintf (f, "%f\n", AutoCor[i]);
}
fclose (f);
}
/* Now call it */
system ("gnuplot " GNUPLOT_CMD_FILENAME);
CalcPeriod ();
char key[Period];
for (start = 0; start < Period; start++)
{
double min=MaxFileLen;
int subkey;
double kreuzCor ;
int sum = 0;
double H[NUMCHARS];
CountChars(start,Period,h);
for (size_t i = 0; i < NUMCHARS; i++)
{
sum = sum + h[i];
// printf("%2d-th absolute frequency h[%2d] = %d\n ", start,i, h[i]);
}
// printf("%2d-th sub-length: %d\n", start, sum);
for (size_t i = 0; i < NUMCHARS; i++)
{
H[i] = (double) h[i]/sum;
// printf("%d-th sub frequency H[%d] = %f\n", start,i, H[i]);
}
for (size_t k = 0; k < NUMCHARS; k++)
{
kreuzCor = 0.0;
for (size_t i = 0; i < NUMCHARS; i++)
{
kreuzCor = kreuzCor + (PropTable[i] - H[(i+k)%NUMCHARS])*(PropTable[i] - H[(i+k)%NUMCHARS]);
}
// printf("%f\n", kreuzCor);
if (kreuzCor < min)
{
min = kreuzCor;
subkey = k;
}
}
// printf("%2d-th crosscorelation: %f with subkey = %d\n", start, min,subkey);
// printf("%d: %d\n",start,subkey);
switch (subkey)
{
case 1:key[start] = 'A';break;
case 2:key[start] = 'B';break;
case 3:key[start] = 'C';break;
case 4:key[start] = 'D';break;
case 5:key[start] = 'E';break;
case 6:key[start] = 'F';break;
case 7:key[start] = 'G';break;
case 8:key[start] = 'H';break;
case 9:key[start] = 'I';break;
case 10:key[start] = 'J';break;
case 11:key[start] = 'K';break;
case 12:key[start] = 'L';break;
case 13:key[start] = 'M';break;
case 14:key[start] = 'N';break;
case 15:key[start] = 'O';break;
case 16:key[start] = 'P';break;
case 17:key[start] = 'Q';break;
case 18:key[start] = 'R';break;
case 19:key[start] = 'S';break;
case 20:key[start] = 'T';break;
case 21:key[start] = 'U';break;
case 22:key[start] = 'V';break;
case 23:key[start] = 'W';break;
case 24:key[start] = 'X';break;
case 25:key[start] = 'Y';break;
case 0:key[start] = 'Z';break;
default:break;
}
}
printf("key is ");
for (size_t i = 0; i < Period; i++)
{
printf("%c", key[i]);
}
return 0;
}
/*************************************************************
** European System Security Institute *
** Internship "Cryptography" *
** *
** Experiment 1: Classic encryption method *
** *
**************************************************************
**
** vigenere.c: Implementation of Vigenere cipher
**/
#include <stdio.h>
#include <stdlib.h>
#include <praktikum.h>
#include <string.h>
#define ALPHABET '[A-Z]'
/********************* Global helpful variables *******************/
String Key; // private key
int N = 26; // length of alphabet
/*
* int Encipher (int c): interprets C as a character, encrypts it using Vigenere's method
* and returns the result.
*/
static int Encipher(int k, int c)
{
c = 'A' + ((c-'A' + k-'A'+1) % N);
return c;
}
/*
* int Decipher (int c): interprets C as a character, decrypts it using Vigenere's method
* and returns the result.
*/
static int Decipher(int k, int c)
{
c = 'A' + ((c-'A' - (k-'A'+1) + N ) % N);
return c;
}
/*
* main (argc, argv): The main program that is called when VIGENERE is called.
* ARGC is the number of arguments specified in the command line plus 1,
* ARGV is a field of pointers to precisely these arguments.
* ARGV [1] is the first, etc. ARGV [0] contains the name of the program.
*/
int main(int argc, char **argv)
{
String infilename,outfilename,help,zeile;
int decipher;
/***** local helpful variables *******/
FILE *infile,*outfile;
/***** print Veigenere Table *****/
printf("Vigenere Table:\n ");
for (size_t i = 'A'; i <= 'Z'; i++)
{
printf(" %c", i);
}
printf("\n");
for (size_t k = 'A'; k <= 'Z'; k++)
{
printf("%c ",k);
for (size_t m = 'A'; m <= 'Z'; m++){
printf("%c ", Encipher(k,m));
}
printf("\n");
}
printf("\n");
/* If the input or output file or the key was
* not specified in the command line, we simply ask .... */
if (argc<2) readline("Input file : ",infilename,sizeof(infilename));
else strncpy(infilename,argv[1],sizeof(infilename));
if (argc<3) readline("Output file : ",outfilename,sizeof(outfilename));
else strncpy(outfilename,argv[2],sizeof(outfilename));
if (argc<4) readline("Key : ",Key,sizeof(Key));
else strncpy(Key,argv[3],sizeof(Key));
printf("Key in length %d: %s\n", strlen(Key),Key);
int key_len=strlen(Key);
if (argc<5) {
do {
readline("E)n- oder D)ecryption : ",help,sizeof(help));
string_to_upper(help);
}
while (strlen(help)!=1 && help[0]!='E' && help[0]!='D');
decipher = help[0]=='D'; // decipher == 1: decryption
}
else {
if (!strncmp(argv[4],"encipher",strlen(argv[4]))) decipher = 0;
else if (!strncmp(argv[4],"decipher",strlen(argv[4]))) decipher = 1;
else {
fprintf(stderr,"ERROR: Unknown mode, 'encipher' or 'decipher' expected.\n");
exit(20);
}
}
string_to_upper(Key);
/* Opening the files: 'fopen' returns a NULL pointer in the event of an error.
* If the file can be opened, the FILE pointer returned by 'fopen' is given as
* an argument for the calls 'fgets', 'fprintf', 'fclose' etc. to identify the file.
*/
if (!(infile=fopen(infilename,"r"))) {
fprintf(stderr,"ERROR: Input file %s cannot be opened: %s\n",infilename,strerror(errno));
exit(20);
}
if (!(outfile=fopen(outfilename,"w"))) {
fprintf(stderr,"ERROR: Output file %s cannot be opened: %s\n",outfilename,strerror(errno));
exit(20);
}
/* Assignment of the variables:
* infilename : Input file name
* outfilename : Output file name
* infile : 'File identifier' that represents the input file
* outfile : 'File identifier' that represents the output file
* Key : Key, changed to capital letters
* decipher : Flag, decipher = 1 in decryption mode, otherwise 0.
*/
int l = 0;
do {
fgets(zeile,sizeof(zeile),infile);
if (!feof(infile)) {
strip_crlf(zeile);
string_to_upper(zeile);
/*>>>> <<<<*
*>>>> Vigenere-encrypt line by line <<<<*
*>>>> <<<<*/
for (size_t i = 0; i < strlen(zeile); i++)
{
if ('A' <= zeile[i] && zeile[i] <= 'Z')
{
if (decipher)
{
zeile[i] = Decipher(Key[l%key_len],zeile[i]);
}
else
{
zeile[i] = Encipher(Key[l%key_len],zeile[i]);
}
l++;