-
Notifications
You must be signed in to change notification settings - Fork 0
/
vigenere.c
150 lines (127 loc) · 4.4 KB
/
vigenere.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#include <stdio.h>
#include <memory.h>
#include <error.h>
#include "vigenere.h"
#include "stringHelper.h"
#include "fileHelper.h"
// https://stackoverflow.com/questions/25410690/scanf-variable-length-specifier
#define STR2(x) #x
#define STR(X) STR2(X)
/**
* Asks for a pass phrase and store it in first param
* @param passPhrase The pointer to store the pass phrase
*/
void askForPassPhrase(char *passPhrase) {
printf("What is your pass phrase? (maxlen=%d)", MAX_PASS_LEN);
if(scanf("%" STR(MAX_PASS_LEN) "s", passPhrase) == 0) {
error(1, 5, "Error reading pass phrase");
}
}
/**
* Encrypts or decrypts a file with vigenère
* @param passPhrase The pass phrase to encrypt/decrypt a file
* @param fileName The file name
* @param mode enum mode ENCRYPT to encrypt, enum mode DECRYPT to decrypt
*/
void encDec(const char *passPhrase, const char *fileName, enum mode mode) {
FILE *fileNameReadP = fopen(fileName, "r");
char fileNameWrite[50] = "";
strcat(fileNameWrite, fileName);
switch (mode) {
case ENCRYPT:
strcat(fileNameWrite, ".encrypted\0");
break;
default:
case DECRYPT:
fileNameWrite[strlen(fileName) - 10] = '\0';
break;
}
FILE *fileNameWriteP = fopen(fileNameWrite, "w");
int currentChar; // note: int, not char, required to handle EOF
int currentPassChar;
int counter = 0;
size_t passPhraseLen = strlen(passPhrase);
while ((currentChar = fgetc(fileNameReadP)) != EOF) {
// loop array with % array length
currentPassChar = passPhrase[counter++ % passPhraseLen];
// add pass char for encrypt, sub pass char for decrypt. Then % 256
currentChar = (currentChar + ((mode == ENCRYPT) ? currentPassChar : -currentPassChar) + 256) % 256;
fputc(currentChar, fileNameWriteP);
}
if (ferror(fileNameReadP))
error(1, 5, "I/O error when reading");
else if (feof(fileNameReadP))
puts("End of file reached successfully\n");
if (ferror(fileNameWriteP))
error(1, 5, "I/O error when writing");
fclose(fileNameReadP);
fclose(fileNameWriteP);
}
/**
* Encrypts a file with vigenère
* @param passPhrase The pass phrase to encrypt a file
* @param fileName The file name
*/
void encrypt(const char *passPhrase, const char *decryptedFileName) {
encDec(passPhrase, decryptedFileName, ENCRYPT);
}
/**
* Decrypts a file with vigenère
* @param passPhrase The pass phrase to decrypt a file
* @param fileName The file name
*/
void decrypt(const char *passPhrase, const char *encryptedFileName) {
if (endsWith(encryptedFileName, ".encrypted") == 0) {
error(1, 5, "Sorry I can only handle .encrypted files");
}
encDec(passPhrase, encryptedFileName, DECRYPT);
}
/**
* Cuts the string at its first repetition
* @param string String to check repetition
*/
void checkRepetitionInString(char *string) {
size_t len = strlen(string);
size_t i = 0;
size_t x = 1;
while (i + x < len) {
if (string[i] == string[i + x]) {
i += x;
} else {
x++;
}
}
string[x] = '\0';
}
/**
* Hacks the used pass phrase of two files
* @param decryptedFileName The decrypted file name
* @param encryptedFileName The encrypted file name
*/
void hack(const char *decryptedFileName, const char *encryptedFileName) {
if (endsWith(encryptedFileName, ".encrypted") == 0) {
error(1, 5, "Sorry I need a .encrypted files");
}
FILE *encryptedFileNameReadP = fopen(encryptedFileName, "r");
FILE *decryptedFileNameReadP = fopen(decryptedFileName, "r");
long encryptedFileSize = fsize(encryptedFileNameReadP);
long decryptedFileSize = fsize(decryptedFileNameReadP);
if (encryptedFileSize != decryptedFileSize) {
error(1, 22, "File size mismatch: %ld, %ld", decryptedFileSize, encryptedFileSize);
}
// Get pass phrase repeated
long i;
char passPhraseRepeated[encryptedFileSize];
for (i = 0; i < encryptedFileSize; i++) {
passPhraseRepeated[i] = (char) (((fgetc(encryptedFileNameReadP) - fgetc(decryptedFileNameReadP)) + 256) % 256);
}
passPhraseRepeated[i] = '\0'; // cut \n
if (ferror(encryptedFileNameReadP) || ferror(decryptedFileNameReadP))
error(1, 5, "I/O error when reading");
else if (feof(encryptedFileNameReadP) && feof(decryptedFileNameReadP))
puts("End of files reached successfully\n");
fclose(encryptedFileNameReadP);
fclose(decryptedFileNameReadP);
checkRepetitionInString(passPhraseRepeated);
printf("The pass phrase used was: %s\n", passPhraseRepeated);
}