Cript (шифрование файлов)
С твоего кода даже обфускатор офигеет. (С) _не_помню_кто_сказал_
Сначала у меня была идея побаловаться с ООП на Си. И я решил сделать небольшую программку для шифрования файлов. Ниже привожу сорцы.
typedefs.h - В файле основные дефайны, инклуды и макрос __PRINT_DBG(), который я использовал для дебага. Этот файл подключается ко всем остальным файлам.
#ifndef TYPEDEFS_H_INCLUDED
#define TYPEDEFS_H_INCLUDED
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#if SYSTEM == MSDOS
#define WIN_OS
#elif SYSTEM == LINUX
#define LIN_OS
#endif
#define DEBUG_MOD
#undef DEBUG_MOD
#ifdef DEBUG_MOD
#define __PRINT_DBG( x )\
printf ( (x) )
#else
#define __PRINT_DBG(x)\
printf ("")
#endif
#define NOOB_CRIPT_ALGORITHM 0
typedef int bool;
enum BOOL {FALSE, TRUE};
#define class typedef struct
#define sub void
#endif
Дальше идет код, отвечающий за хранение и изменение настроек. Может это не очень хорошая идея, но я ничего другого не придумал.
settings_class.h
#ifndef SETTINGS_CLASS_H_INCLUDED
#define SETTINGS_CLASS_H_INCLUDED
class {
// public:
// Settings();
// bool isRemove();
// bool isSettingTypeOfCript();
// int getCriptAlgorithm();
// int getCriptBufSize();
// FILE *getInputFile();
// FILE *getOutputFile();
// void setCript (bool val);
// void setRemove (bool val);
// void setSettingsTypeOfCript (bool val);
// void setCriptAlgorithm (int val);
// void setCriptBufSize (int val);
// void setInputFile (FILE *inputfile);
// void setOutputFile (FILE *outputfile);
// ~Settings();
// private:
bool remove;
bool reverse;
int criptAlgorithm;
int criptBufSize;
bool settedInputFile;
char* inputfilename;
FILE *inputfile;
bool settedOutputFile;
char* outputfilename;
FILE *outputfile;
} Settings;
#endif
settings.h
#ifndef SETTINGS_H_INCLUDED
#define SETTINGS_H_INCLUDED
#include "typedefs.h"
#include "settings_class.h"
sub Settings_constructor (Settings *this);
bool Settings_isRemove (Settings *this);
bool Settings_isReverse (Settings *this);
int Settings_getCriptAlgorithm (Settings *this);
int Settings_getCriptBufSize (Settings *this);
bool Settings_isSettedInputFile (Settings *this);
char* Settings_getInputFileName (Settings *this);
FILE *Settings_getInputFile (Settings *this);
bool Settings_isSettedOutputFile (Settings *this);
char* Settings_getOutputFileName (Settings *this);
FILE *Settings_getOutputFile (Settings *this);
sub Settings_setRemove (Settings *this, bool val);
sub Settings_setReverse (Settings *this, bool val);
sub Settings_setCriptAlgorithm (Settings *this, int val);
sub Settings_setCriptBufSize (Settings *this, int val);
sub Settings_setSettedInputFile (Settings *this, bool val);
sub Settings_setInputFileName (Settings *this, char* path);
sub Settings_setInputFile (Settings *this, FILE *inputfile);
sub Settings_setSettedOutputFile (Settings *this, bool val);
sub Settings_setOutputFileName (Settings *this, char* path);
sub Settings_setOutputFile (Settings *this, FILE *outputfile);
sub Settings_destructor (Settings *this);
#endif
settings.c
#include "typedefs.h"
#include "settings.h"
sub Settings_constructor (Settings *this) {
this->remove = FALSE;
this->reverse = FALSE;
this->criptAlgorithm = 0;
this->criptBufSize = 1024 * 1024;
this->settedInputFile = FALSE;
this->inputfile = NULL;
this->inputfilename = NULL;
this->settedOutputFile = FALSE;
this->outputfile = NULL;
this->outputfilename = NULL;
}
bool Settings_isRemove (Settings *this) {
return this->remove;
}
bool Settings_isReverse (Settings *this) {
return this->reverse;
}
int Settings_getCriptAlgorithm (Settings *this) {
return this->criptAlgorithm;
}
int Settings_getCriptBufSize (Settings *this) {
return this->criptBufSize;
}
bool Settings_isSettedInputFile (Settings *this) {
return this->settedInputFile;
}
char* Settings_getInputFileName (Settings *this) {
return this->inputfilename;
}
FILE *Settings_getInputFile (Settings *this) {
return this->inputfile;
}
bool Settings_isSettedOutputFile (Settings *this) {
return this->settedOutputFile;
}
char* Settings_getOutputFileName (Settings *this) {
return this->outputfilename;
}
FILE *Settings_getOutputFile (Settings *this) {
return this->outputfile;
}
sub Settings_setRemove (Settings *this, bool val) {
this->remove = val;
}
sub Settings_setReverse (Settings *this, bool val) {
this->reverse = val;
}
sub Settings_setCriptAlgorithm (Settings *this, int val) {
this->criptAlgorithm = val;
}
sub Settings_setCriptBufSize (Settings *this, int val) {
this->criptBufSize = val;
}
sub Settings_setSettedInputFile (Settings *this, bool val) {
this->settedInputFile = val;
}
sub Settings_setInputFileName (Settings *this, char* path) {
this->inputfilename = path;
}
sub Settings_setInputFile (Settings *this, FILE *inputfile) {
this->inputfile = inputfile;
}
sub Settings_setSettedOutputFile (Settings *this, bool val) {
this->settedOutputFile = val;
}
sub Settings_setOutputFileName (Settings *this, char* path) {
this->outputfilename = path;
}
sub Settings_setOutputFile (Settings *this, FILE *outputfile) {
this->outputfile = outputfile;
}
sub Settings_destructor (Settings *this) {
this->inputfile = NULL;
this->inputfilename = NULL;
this->outputfile = NULL;
this->outputfilename = NULL;
}
Настройки частично могут поменяться, если вызывать программу с параметрами. За их парсинг отвечает следующий код.
arg_class.h
#ifndef ARG_CLASS_H_DEFINED
#define ARG_CLASS_H_DEFINED
class {
// public:
// void argPars (int argc, char **argv);
// void srgSet (char *arg);
// void setTypeOfCript (char *type);
// void setInputFile (char *path);
// void setOutputFile (char *path);
// private:
Settings *setups;
} Arg;
#endif
arg.h
#ifndef ARG_H_INCLUDED
#define ARG_H_INCLUDED
#include "typedefs.h"
#include "arg_class.h"
#include "settings_class.h"
// From 'main.c'.
sub showUsage (void);
sub Arg_constructor (Arg *this, Settings *setups);
sub Arg_argPars (Arg *this, int argc, char **argv);
sub Arg_argSet (Arg *this, char *arg);
sub Arg_flagSet (Arg *this, char *arg);
sub Arg_setTypeOfCript (Arg *this, char *type);
sub Arg_setInputFile (Arg *this, char *path);
sub Arg_setOutputFile (Arg * this, char *path);
sub Arg_destructor (Arg *this);
#endif
arg.c
#include "settings.h"
#include "arg.h"
#include "main.h"
sub Arg_constructor (Arg *this, Settings *setups) {
__PRINT_DBG("__FUNC: Arg_constructor\n");
this->setups = setups;
}
sub Arg_argPars (Arg *this, int argc, char **argv) {
__PRINT_DBG("__FUNC: Arg_argPars\n");
for (int i = 1; i < argc; i++) {
if (argv[i][0] == '-' && argv[i][1] != '-') {
Arg_argSet (this, argv[i]);
} else if (argv[i][0] == '-' && argv[i][1] == '-') {
Arg_flagSet (this, argv[i]);
} else if (Settings_isSettedInputFile (this->setups) == FALSE) {
Arg_setInputFile (this, argv[i]);
} else if (Settings_isSettedOutputFile (this->setups) == FALSE) {
Arg_setOutputFile (this, argv[i]);
} else {
printf ("Invalide argument \'%s\'!\n", argv[i]);
exit (1);
}
}
if (Settings_getInputFile (this->setups) != NULL && Settings_getOutputFile (this->setups) == NULL) {
Arg_setOutputFile (this, strcat (Settings_getInputFileName (this->setups), ".cript"));
}
if (Settings_getInputFile (this->setups) == NULL) {
printf ("Missed a input file!\n");
exit (1);
}
}
sub Arg_argSet (Arg *this, char *arg) {
__PRINT_DBG("__FUNC: Arg_argSet\n");
for (int i = 1; arg[i] != '{EDIT_TEXT}'; i++) {
#define param arg[i]
if (param == 'R') {
Settings_setReverse (this->setups, 1);
} else if (param == 'r') {
Settings_setRemove (this->setups, 1);
} else {
printf ("Invalid arguments!\n");
showUsage();
exit (1);
}
#undef param
}
}
/* If str1 == str2 then return 1. */
bool Arg_mystrcmp (char* str1, char *str2) {
while (*str1 == *str2 && *str1 != '=') {
str1++; str2++;
}
if (*str1 == *str2 && *str1 == '=') {
return 1;
} else {
return 0;
}
}
char *Arg_getParam (char *arg) {
while (*arg != '=' && *arg != '{EDIT_TEXT}') {
arg++;
}
if (*arg == '=') {
arg++;
return arg;
} else {
return NULL;
}
}
sub Arg_flagSet (Arg *this, char *arg) {
__PRINT_DBG("__FUNC: Arg_flagSet\n");
char *param;
if (Arg_mystrcmp (arg, "--cript-met=")) {
param = Arg_getParam (arg);
if (!strcmp (param, "noob")) {
/***/printf ("noob\n");
Settings_setCriptAlgorithm (this->setups, NOOB_CRIPT_ALGORITHM);
} else {
printf ("Invalide parametr of \'--cript-met=\'!\n");
showUsage();
exit (1);
}
} else if (!strcmp (arg, "--reverse")) {
Settings_setReverse (this->setups, TRUE);
} else if (!strcmp (arg, "--remove")) {
Settings_setRemove (this->setups, TRUE);
} else if (!strcmp (arg, "--help")) {
showUsage();
} else {
printf ("Invalide argument \'%s\'!\n", arg);
showUsage();
exit (1);
}
}
sub Arg_setTypeOfCript (Arg *this, char *type) {
//
}
sub Arg_setInputFile (Arg *this, char *path) {
__PRINT_DBG("__FUNC: Arg_setInputFile\n");
FILE *file;
if ((file = fopen (path, "rb")) != NULL) {
Settings_setSettedInputFile (this->setups, TRUE);
Settings_setInputFileName (this->setups, path);
Settings_setInputFile (this->setups, file);
} else {
printf ("File \'%s\' not exist!\n", path);
exit (1);
}
}
sub Arg_setOutputFile (Arg * this, char *path) {
__PRINT_DBG("__FUNC: Arg_setOutputFile\n");
FILE *file;
// Cleaning file.
if ((file = fopen (path, "w")) == NULL) {
printf ("Can\'t create a file \'%s\'!\n", path);
exit (1);
} else {
fclose (file);
}
if ((file = fopen (path, "ab")) != NULL) {
Settings_setSettedOutputFile (this->setups, TRUE);
Settings_setOutputFileName (this->setups, path);
Settings_setOutputFile (this->setups, file);
} else {
printf ("Can\'t create a file \'%s\'!\n", path);
exit (1);
}
}
sub Arg_destructor (Arg *this) {
__PRINT_DBG("__FUNC: Arg_destructor\n");
this->setups = NULL;
}
Возможно, я не правильно понимаю наследование или не правильно его применяю (что, в общем-то, одно и то же), но решил я сделать так.
criptbuf_class.h
#ifndef CRIPTBUF_CLASS_H_INCLUDED
#define CRIPTBUF_CLASS_H_INCLUDED
class {
// public:
// CriptBuf();
// ~CriptBuf();
// protected:
char *buf;
} CriptBuf;
#endif
criptbuf.h
#ifndef CRIPT_BUF_H_INCLUDED
#define CRIPT_BUF_H_INCLUDED
#include "typedefs.h"
#include "criptbuf_class.h"
sub CriptBuf_constructor (CriptBuf *this, int bufSize);
char CriptBuf_getBit (CriptBuf *this, int num);
void CriptBuf_setBit (CriptBuf *this, int num, char val);
sub CriptBuf_destructor (CriptBuf *this);
#endif
criptbuf.c
#include "criptbuf.h"
sub CriptBuf_constructor (CriptBuf *this, int bufSize) {
__PRINT_DBG("__FUNC: CriptBuf_constructor\n");
this->buf = (char *) calloc (bufSize, sizeof (char));
}
char CriptBuf_getBit (CriptBuf *this, int num) {
return this->buf[num];
}
void CriptBuf_setBit (CriptBuf *this, int num, char val) {
this->buf[num] = val;
}
sub CriptBuf_destructor (CriptBuf *this) {
__PRINT_DBG("__FUNC: CriptBuf_destructor\n");
free (this->buf);
}
Предыдущий класс "наследуется" следующим (который и отвечает за шифрование).
cript_class.h
#ifndef CRIPT_CLASS_H_INCLUDED
#define CRIPT_CLASS_H_INCLUDED
#include "settings_class.h"
#include "criptbuf_class.h"
class /* protected: CriptBuf, protected: CriptAlgorithm */ {
// public:
// Cript();
// void setCriptAlgorithm();
// void setPreCriptBuf();
// void writeCript();
// virtual void doCripting() = 0;
// ~Cript();
// private:
Settings *setups;
// parents:
CriptBuf *CriptBuf;
} Cript;
#endif
cript.h
#ifndef CRIPT_H_INCLUDED
#define CRIPT_H_INCLUDED
#include "typedefs.h"
#include "settings.h"
#include "cript_class.h"
sub Cript_constructor (Cript *this, Settings *setups);
sub Cript_setPreCriptBuf (Cript *this);
sub Cript_writeCript (Cript *this);
sub Cript_criptFile (Cript *this);
sub Cript_destructor (Cript *this);
#endif
cript.c
#include "cript.h"
#include "cript_001.h"
#include "criptbuf.h"
sub Cript_constructor (Cript *this, Settings *setups) {
__PRINT_DBG("__FUNC: Cript_constructor\n");
this->setups = setups;
this->CriptBuf = (CriptBuf *) calloc (1, sizeof (CriptBuf));
CriptBuf_constructor (this->CriptBuf, Settings_getCriptBufSize (this->setups));
}
void (*Cript_doCripting[][2]) (Cript *this) = {
{Cript_cript_001, Cript_recript_001}
};
sub Cript_criptFile (Cript *this) {
__PRINT_DBG("__FUNC: Cript_criptFile\n");
while (!feof (Settings_getInputFile (this->setups))) {
Cript_setPreCriptBuf (this);
(*Cript_doCripting[Settings_getCriptAlgorithm (this->setups)][Settings_isReverse (this->setups)]) (this);
Cript_writeCript (this);
}
}
sub Cript_setPreCriptBuf (Cript *this) {
__PRINT_DBG(("__FUNC: Cript_setPreCriptBuf\n"));
int i;
bool flag;
for (i = 0; i < Settings_getCriptBufSize (this->setups) && (flag = !feof (Settings_getInputFile (this->setups))); i++) {
CriptBuf_setBit (this->CriptBuf, i, getc (Settings_getInputFile (this->setups)));
/***/printf (" _ %d: %c\n", i, CriptBuf_getBit (this->CriptBuf, i));
}
if (!flag) { /** Ugly style, imho. */
i--;
}
Settings_setCriptBufSize (this->setups, i);
}
sub Cript_writeCript (Cript *this) {
__PRINT_DBG(("__FUNC: Cript_writeCript\n"));
for (int i = 0; i < Settings_getCriptBufSize (this->setups); i++) {
putc (CriptBuf_getBit (this->CriptBuf, i), Settings_getOutputFile (this->setups));
}
}
sub Cript_destructor (Cript *this) {
__PRINT_DBG("__FUNC: Cript_destructor\n");
CriptBuf_destructor (this->CriptBuf);
this->setups = NULL;
}
В коде выше используется двумерный массив указателей на функции. Двумерный, чтобы можно было легко вызвать алгоритм расшифровки для несимметричного алгоритма шифрования. Я посчитал, что так проще будет добавлять новые алгоритмы шифрования.
В общем, вот тот алгоритм, что используется сейчас.
cript_001.h
#ifndef CRIPT_001_H_INCLUDED
#define CRIPT_001_H_INCLUDED
#include "typedefs.h"
#include "cript_class.h"
#define CRIPT_BLOCK_SIZE 4
sub Cript_cript_001 (Cript *this);
sub Cript_recript_001 (Cript *this);
#endif
cript_001.c
#include "cript_001.h"
#include "settings.h"
#include "criptbuf.h"
char reverseBit (char bite) {
__PRINT_DBG("__FUNC: reverseBit\n");
char temp = 0;
// ...
#define CHAR_SIZE 8
for (int i = 0; i < CHAR_SIZE; i++) {
temp |= ((bite >> i) & 1) << (CHAR_SIZE - 1 - i);
}
bite = temp;
return bite;
}
void Cript_cript_001 (Cript *this) {
/*
* Reverse beat from boundary to center.
*/
__PRINT_DBG("__FUNC: Cript_cript_001\n");
int temp;
for (int i = 0; i < Settings_getCriptBufSize (this->setups); i += CRIPT_BLOCK_SIZE) {
if (i + CRIPT_BLOCK_SIZE <= Settings_getCriptBufSize (this->setups)) {
for (int j = 0; j < CRIPT_BLOCK_SIZE / 2; j++) {
temp = CriptBuf_getBit (this->CriptBuf, i + j);
CriptBuf_setBit (this->CriptBuf, i + j, reverseBit (CriptBuf_getBit (this->CriptBuf, i + CRIPT_BLOCK_SIZE - j - 1)));
CriptBuf_setBit (this->CriptBuf, i + CRIPT_BLOCK_SIZE - j - 1, reverseBit (temp));
}
} else {
for (int j = 0; i + j < Settings_getCriptBufSize (this->setups); j++) {
CriptBuf_setBit (this->CriptBuf, i + j, reverseBit (CriptBuf_getBit (this->CriptBuf, i + j)));
}
}
}
}
void Cript_recript_001 (Cript *this) {
__PRINT_DBG("__FUNC: Cript_recript_001\n");
Cript_cript_001 (this);
}
Из недостатков алгоритма можно выделить очень медленную работу. На 1МБ может уйти около минуты. После выполнения алгоритма каждый блок 4 байта будет побитово развернут. Если последний блок меньше 4 байт, будет побитово разворачиваться каждый байт.
Назначение файлов main.h и main.c должно быть понятно любому.
Я решил не делать "объекты классов", которые описал выше, глобальными, а создавать их в теле функции, передав по ссылке.
main.h
#ifndef MAIN_H_INCLUDED
#define MAIN_H_INCLUDED
#include "typedefs.h"
#include "settings_class.h"
sub showUsage (void);
sub deliteSorceFile (Settings *setups);
sub closeFiles (Settings *setups);
#endif
main.c
#include "typedefs.h"
#include "main.h"
#include "arg.h"
#include "cript.h"
sub showUsage (void) {
printf (
"Usage:\n\
cript [param] (options) [path to file] [output file name]\n\
\n\
param:\n\
\t-R, --reverse\n\
\t\t> Reverse cript (encript).\n\
\t-r, --remove\n\
\t\t> remove source file.\n\
options:\n\
\t--cript-met=method\n\
\t\t> method={noob}\n\
\n"
);
}
sub deliteSorceFile (Settings *setups) {
remove (Settings_getInputFileName (setups));
}
sub closeFiles (Settings *setups) {
fclose (Settings_getInputFile (setups));
fclose (Settings_getOutputFile (setups));
}
int main (int argc, char **argv) {
if (argc == 1) {
showUsage();
return 0;
}
Settings setups;
Settings_constructor (&setups);
Arg arg; Arg_constructor (&arg, &setups);
Arg_argPars (&arg, argc, argv);
Cript cript;
Cript_constructor (&cript, &setups);
Cript_criptFile (&cript);
Cript_destructor (&cript);
closeFiles (&setups);
if (Settings_isRemove (&setups) == 1) {
deliteSorceFile (&setups);
}
Settings_destructor (&setups);
return 0;
}
Чтобы не собирать отдельно каждый файл ручками, сделаем Makefile (на виндовс make не завелся, придется собирать от руки).
Makefile
# Make 4.0
CC=gcc
CFLAGS=-c -Os --std=c99
all: cript
cript: main.o settings.o arg.o criptbuf.o cript.o cript_001.o
$(CC) main.o settings.o arg.o criptbuf.o cript.o cript_001.o -o cript
main.o: main.c
$(CC) $(CFLAGS) main.c
settings.o: settings.c
$(CC) $(CFLAGS) settings.c
arg.o: arg.c
$(CC) $(CFLAGS) arg.c
criptbuf.o: criptbuf.c
$(CC) $(CFLAGS) criptbuf.c
cript.o: cript.c
$(CC) $(CFLAGS) cript.c
cript_001.o: cript_001.c
$(CC) $(CFLAGS) cript_001.c
clean:
rm -rf *.o cript
clean_o:
rm -rf *.o
cleancripted:
rm -rf *.cript
fun:
rm -rf *
Потом может добавлю графический интерфейс на питоне. Если кому интересно, ссылка на гитхаб. Обновления кидать туда буду.
https://github.com/npcipav/cript