Простая и надежная криптосистема с открытым кодом на C++(симметричное шифрование)
- 2013-06-09
- Автор: admin
- Рубрика: Защита информации, Криптография
Внимание! Приведенная информация распространяется исключительно в ознакомительных целях. Перед использованием данных материалов рекомендуется ознакомиться с ФЗ Российской Федерации от 4 мая 2011 г. N 99-ФЗ "О лицензировании отдельных видов деятельности".
Описание криптосистемы и исполняемые файлы.
Можно в виде подключаемой внешней компоненты подцепить эту криптосистему к любой рограммаме 1С:Предприятие в целях обеспечения информационной безопасности данных предприятия.
//Отлажено в MS VISUAL C++ 6 // mdcrypt.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <stdio.h> #include <string.h> #include <io.h> #include <stdlib.h> #include <process.h> #define AMOUNT_TRANSFORMATION 12 int add_to_key_from_file(char *key_file_name); FILE *fIn, *fOut; char Keys[12][256]; //************************************************************** //установка байт блока в заданное значение // // void mymemset(char *str, char cCimbol, int iLen) { for (int i=0; i<iLen; i++) str[i]Мimbol; } //************************************************************** //сравнение строк // // int str1_is_str2(char *str1, char *str2) { for (int i=0; i<256; i++) if (str1[i]!=str2[i]) return 0; return 1; } //************************************************************** //обмен байтов местами // // void swap(char cCimbol1, char cCimbol2) { char cTempМimbol1; cCimbol1Мimbol2; cCimbol2=cTemp; } //************************************************************** //битовый сдвиг // // void ROR(char *Str, char *Key) { char cTemp, cShift; for (int i=0;i<256;i++) { cTemp=Str[i]; cShift=Key[i]; _asm { MOV CL, cShift ROR cTemp, CL } Str[i]=cTemp; } } //************************************************************** //XOR // // void Gamma(char *Str, char *Key) { for (int i=0; i<256;i++) Str[i]=Str[i]^Key[i]; } //************************************************************** //перестановка // // void Superposition(char *Str, char *Key) { char StrTmp[256]; for (int i=0; i<256; i++) StrTmp[i]=Str[(unsigned char)Key[i]]; for (i=0; i<256; i++) Str[i]=StrTmp[i]; } //************************************************************** //лавина - сделать каждый следующий байт блока зависимым от текущего (проход с начала блока к концу) // // void Avalanche_onward(char *Str) { for (int i=1; i<256; i++) { Str[i]=Str[i]^Str[i-1]; } Str[0]=Str[0]^Str[255]; } //************************************************************** //лавина - сделать каждый предыдущий байт блока зависимым от текущего(проход с конца блока к началу) // // void Avalanche_back(char *Str) { Str[0]=Str[0]^Str[255]; for (int i%5; i>0; i--) { Str[i]=Str[i]^Str[i-1]; } } //************************************************************** //копирование блока // // void strcopy(char *str1, char *str2, int count) { for (int i=0;i<count;i++) str1[i]=str2[i]; } //************************************************************** //генерация ключа для перестановки: не должно быть повторяющихся байт // // void KeyForSuperpositionGen(char *Key) { char StrTmp[256]; for(int i=0;i<256;i++) StrTmp[i]=i; for (i=0; i<256; i++) swap(StrTmp[i], StrTmp[Key[i]]); strcopy(Key,StrTmp, 256); } //************************************************************** //сформируем хеш // // void Hash(char *Str, char Slognost) { char StrTmp[256]; for (int i=0; i<Slognost*3; i++) { for(int j=0; j<256;j++) StrTmp[j]=Str[j]+j; if ((i%3)==0) { KeyForSuperpositionGen(StrTmp); Superposition(Str, StrTmp); } if ((i%3)==2) ROR(Str, StrTmp); //и защита от вырождения хеша Avalanche_onward(Str); } } //************************************************************** //генерация ключа для битового сдвига - нет смысла сдвигать каждый байт более чем на 8 бит, так как далее пойдет по кругу //кроме того, если опреация - расшифрование, то "количество сдвигаемых бит" = "8 - количество сдвигаемых бит". это обеспечит "обратный сдвиг" // void BitShiftKeyPrepare(char *Key, bool UnCrypt) { if (UnCrypt=ъlse) for (int i=0;i<256;i++) Key[i]=Key[i]%8; else for (int i=0;i<256;i++) Key[i]=8-(Key[i]%8); } //************************************************************** //переворачиваем ключ для перестановки - получаем ключ для расшифроки("обратной перестановки") // // void RevKeyForSuperposition(char *Key) { char StrTmp[256]; for(int i=0;i<256;i++) { StrTmp[(unsigned char)Key[i]]=i; } strcopy(Key,StrTmp, 256); } //************************************************************** //генерируем ключ с помощью хеша от заданного пароля // // void KeyGenerate(char *pass, bool UnCrypt, bool with_key_file, char *key_file_name) { char StrTmp[256]; char cPassLen=strlen(pass); mymemset(StrTmp, '/0', 256); strcpy(StrTmp, pass); if (with_key_file) { add_to_key_from_file(key_file_name); for (int i=0;i<AMOUNT_TRANSFORMATION; i++) { strcopy(StrTmp, Keys[i], 256); Hash(StrTmp, cPassLen); strcopy(Keys[i], StrTmp, 256); } } else { for (int i=0;i<AMOUNT_TRANSFORMATION; i++) { Hash(StrTmp, cPassLen); strcopy(Keys[i], StrTmp, 256); } } for (int i=0;i<AMOUNT_TRANSFORMATION; i++) { if ((i%3)==0) { KeyForSuperpositionGen(Keys[i]); if (UnCrypt) RevKeyForSuperposition(Keys[i]); } if ((i%3)==2) BitShiftKeyPrepare(Keys[i], UnCrypt); } } //************************************************************** //подготавливаем файлы // // int PrepareFiles(char *in_fname, char *out_fname) { char tmp_str[300]; fIn = fopen(in_fname, "rb"); if (fIn == NULL) { strcpy(tmp_str, "Error! File '"); strcat(tmp_str, in_fname); strcat(tmp_str, "' not found."); printf("%sn", tmp_str); return 0; } fOut = fopen(out_fname, "wb"); if (fOut == NULL) { strcpy(tmp_str, "Error! Can't create file '"); strcat(tmp_str, in_fname); strcat(tmp_str, "'."); printf("%sn", tmp_str); return 0; } return 1; } //************************************************************** //закрываем файлы // // void CloseFiles() { fclose(fIn); fclose(fOut); } //************************************************************** //получим блок из файла // // int GetStr(char *buffer) { for (int i=0; i<256; i++) { if (feof(fIn)) return i-1; buffer[i]=fgetc(fIn); } return 256; } //************************************************************** //положим блок в файл // // void PutStr(char *buffer, int len) { for (int i=0; i<len; i++) { fputc(buffer[i], fOut); } } //************************************************************** //функция считает хеш файла путем операции XOR строки к редыдущему хешу // // void FileHash(char *LastHash, char *Str) { for (int i=0; i<256; i++) LastHash[i]^=Str[i]; } //************************************************************** //шифрование // // int Crypt(int current_amount_transformation) { char StrIn[256]="", StrOut[256]="", StrLastRaund[256]="", StrTmp[256]="", StrHash[256]=""; int buflen=0; printf("Crypt process start!n"); PutStr("%mdcrypt%", 9);//положим строчку дял идентификации зашифрованных файлов PutStr(StrHash, 256);//запишем в начало файла пустой блок - там потом положим хеш while(!feof(fIn)) { mymemset(StrIn, '/0', 256);//обнуляем блок buflen=GetStr(StrIn);//получим блок и его длину if (buflen<256) StrIn[255]=buflen;//если длина блока меньше 256 символов, значит это блок последний и в последнем его байте запишем длину этого блока - пригодится при расшифровке strcopy(StrOut, StrIn, 256); FileHash(StrHash, StrIn);//добавим строку к хешу Gamma(StrOut, StrLastRaund);//наложим на текущий блок зашифрованные данные предыдущего for (int i=0; i<current_amount_transformation; i++)//и начинаем последовательно применять операции шифрования. { if ((i%3)==0) Superposition(StrOut, Keys[i]); if ((i%3)==1) Gamma(StrOut, Keys[i]); if ((i%3)==2) { ROR(StrOut, Keys[i]); Avalanche_onward(StrOut); } } PutStr(StrOut, 256);//запишем блок в файл strcopy(StrLastRaund, StrOut, 256);//запомним блок для наложения его на блок следующего шага } Hash(StrHash, 1); fseek(fOut, 9, SEEK_SET); PutStr(StrHash, 256); printf("Cript compliten"); return 1; } //************************************************************** // // // int Decrypt(int current_amount_transformation) { char StrIn[256]="", StrOut[256]="", StrLastRaund[256]="", StrTmp[256]="", StrHash[256]="", StrGetHash[256]=""; int buflen=0; long fLen; printf("Decrypt process start!n"); fLen=filelength(fileno(fIn))-265;//определим длину файла без хеша fseek(fIn, 9, SEEK_SET);//установим флажок в начало, после блока идентификации "%mdcrypt%" GetStr(StrGetHash); while(!feof(fIn)) { mymemset(StrIn, '/0', 256);//обнуляем блок buflen=GetStr(StrIn);//получим блок и его длину strcopy(StrOut, StrIn, 256); fLen-=buflen;//сминусуем длину буфера strcopy(StrTmp, StrOut, 256); for (int i=(current_amount_transformation-1); i>=0; i--) { if ((i%3)==0) Superposition(StrOut, Keys[i]); if ((i%3)==1) Gamma(StrOut, Keys[i]); if ((i%3)==2) { Avalanche_back(StrOut); ROR(StrOut, Keys[i]); } } if (fLen==0) { Gamma(StrOut, StrLastRaund); FileHash(StrHash, StrOut); buflen=(unsigned char)StrOut[255]; PutStr(StrOut, buflen); break; } Gamma(StrOut, StrLastRaund); FileHash(StrHash, StrOut); PutStr(StrOut, buflen); strcopy(StrLastRaund, StrTmp, 256); } Hash(StrHash, 1); if (!str1_is_str2(StrHash, StrGetHash)) //сравним хеши { printf("Decrypt WRONG!n"); return 0; } printf("Decrypt OK!n"); return 1; } //************************************************************** // // // int Do(bool UnCrypt, int pass_len) { int current_amount_transformation; //определяем количество проходов шифра в зависимости от длины пароля if ((pass_len>8) && (pass_len<)) current_amount_transformation=2*AMOUNT_TRANSFORMATION; else if ((pass_len>12) && (pass_len<)) current_amount_transformation=3*AMOUNT_TRANSFORMATION; else if (pass_len>16) current_amount_transformation=4*AMOUNT_TRANSFORMATION; else current_amount_transformation=AMOUNT_TRANSFORMATION; if (!UnCrypt) { if (Crypt(current_amount_transformation)==0) return 0; } else { if (Decrypt(current_amount_transformation)==0) return 0; } return 1; } //************************************************************** //поиск ключевого файла // // int search_key(char *key_file_name) { FILE *fKey; fKey = fopen(key_file_name, "rb"); if (fKey == NULL) { return 0; } fclose(fKey); printf("Key file found."); return 1; } //************************************************************** //генерация ключевого файла // // int key_file_generate(char *key_file_name) { FILE *fKey; char tmp_str[300], temp_key[256]; fKey = fopen(key_file_name, "wb"); if (fKey == NULL) { strcpy(tmp_str, "Error! Can't create key-file '"); strcat(tmp_str, key_file_name); strcat(tmp_str, "'."); printf("%sn", tmp_str); return 0; } for (int i=0;i<12;i++) { for (int j=0;j<256;j++) { temp_key[j]=rand(); Hash(temp_key,1); } for (j=0;j<256;j++) fputc(temp_key[j], fKey); } fclose(fKey); printf("Key file is successfully created!n"); return 1; } //************************************************************** //добавить к ключам информацию из ключевого файла // // int add_to_key_from_file(char *key_file_name) { FILE *fKey; char tmp_str[300]; fKey = fopen(key_file_name, "rb"); if (fKey == NULL) { strcpy(tmp_str, "Error! File '"); strcat(tmp_str, key_file_name); strcat(tmp_str, "' not found."); printf("%sn", tmp_str); return 0; } for (int i=0;i<12;i++) { for (int j=0;j<256;j++) Keys[i][j]^=fgetc(fKey); } fclose(fKey); return 1; } //************************************************************** //проверка, является ли файл зашифрованным // // int is_crypted_file(char *in_fname) { FILE *filo; char tmp_str[256], mdcrypt[10]="%mdcrypt%"; filo = fopen(in_fname, "rb"); if (filo == NULL) { strcpy(tmp_str, "Error! File '"); strcat(tmp_str, in_fname); strcat(tmp_str, "' not found."); printf("%sn", tmp_str); return 0; } for (int i=0; i<9; i++) { if (mdcrypt[i]!=getc(filo)) { printf("Crypt runn"); fclose(filo); return 0; } } fclose(filo); return 1; } //************************************************************** // // // void main(int argc, char **argv) { bool UnCrypt=0;//operation - encrypt char tmp_str[300]; if (argc<4) { printf("mdcrypt.exe /in_fname/ /out_fname/ /password/n"); printf("If you want to use key file, add 4 parametr - /key_file_name/. If program not found this file, it's create it, absolutely random!n"); printf("When decrypt /out_fname/ must be random(program don't use it), but not empty!n"); return; } if (is_crypted_file(argv[1])) UnCrypt=1;//operation - decrypt if (argc==5)//значит используется ключевой файл { int found_key=search_key(argv[4]); if ((found_key==0) && (UnCrypt==1)) { strcpy(tmp_str, "Error! Key file '"); strcat(tmp_str, argv[4]); strcat(tmp_str, "' not found."); printf("%sn", tmp_str); return; } else if ((found_key==0) && (UnCrypt==0)) { key_file_generate(argv[4]); } KeyGenerate(argv[3], UnCrypt, 1, argv[4]); } else { KeyGenerate(argv[3], UnCrypt, 0, ""); } if (!UnCrypt) { strcpy(tmp_str,"7z.exe a mdcryptxxxfilo.7z "); strcat(tmp_str, argv[1]); printf("!n%sn!", tmp_str); if (system(tmp_str)==-1) { strcpy(tmp_str, "Error pack file '"); strcat(tmp_str, argv[1]); strcat(tmp_str, "'"); printf("%sn", tmp_str); return; } if(PrepareFiles("mdcryptxxxfilo.7z", argv[2])==0) return; } else { if(PrepareFiles(argv[1], "mdcryptxxxfilo.7z")==0) return; } if (Do(UnCrypt, strlen(argv[3]))==0) return; CloseFiles(); if (UnCrypt) { if (system("7z.exe x mdcryptxxxfilo.7z -y")==-1) { printf("Error unpack file n"); return; } } system("del mdcryptxxxfilo.7z"); }
Внимание! Приведенная информация распространяется исключительно в ознакомительных целях. Перед использованием данных материалов рекомендуется ознакомиться с ФЗ Российской Федерации от 4 мая 2011 г. N 99-ФЗ "О лицензировании отдельных видов деятельности".
Ссылка на подключаемую внешнюю компоненту, к сожалению, не работает =(
Не могли бы Вы ее подправить?
Спасибо!
Здравствуйте. Честно даже уже не знаю где ее искать тепрерь. Видимо потерялась при переносе сайта. Приношу извинения, н опомочь, видимо, не смогу
Гляньте, пожалуйста в функцию int Crypt(int current_amount_transformation) для пароля более 8 символов (возьмем к примеру 16). Генерируете 12 ключей, а обращаетесь по очереди от 0го до 35го.
… if (pass_len>12) && (…)) current_amount_transformation=3*AMOUNT_TRANSFORMATION;…
т.е. current_amount_transformation=36 (а в случае >16 равно 48), а затем
… for (int i=0; i<current_amount_transformation; i++) …
if ((i%3)==0) Superposition(StrOut, Keys[i]);
Наверное тут вместо Keys[i] что-то другое стоять должно.
Почему-то не работает с ключом больше 8
Решение нашел, может кому пригодится.
1. изменяем размерность массива char Keys[48][256]; 12 на 48 (4 * AMOUNT_TRANSFORMATION)
2. изменяем функцию KeyGenerate:
void KeyGenerate(char* pass, bool UnCrypt, bool with_key_file, char* key_file_name)
{
int current_amount_transformation;
int pass_len = strlen(pass);
//определяем количество проходов шифра в зависимости от длины пароля
if ((pass_len > 8) && (pass_len <= 12)) current_amount_transformation = 2 * AMOUNT_TRANSFORMATION;
else if ((pass_len > 12) && (pass_len <= 16)) current_amount_transformation = 3 * AMOUNT_TRANSFORMATION;
else if (pass_len > 16) current_amount_transformation = 4 * AMOUNT_TRANSFORMATION;
else current_amount_transformation = AMOUNT_TRANSFORMATION;
char StrTmp[256];
char cPassLen = strnlen(pass,255);
mymemset(StrTmp, '/0', 256);
strcpy_s(StrTmp, 256, pass);
if (with_key_file)
{
add_to_key_from_file(key_file_name);
for (int i = 0; i < current_amount_transformation; i++)
{
strcopy(StrTmp, Keys[i], 256);
Hash(StrTmp, cPassLen);
strcopy(Keys[i], StrTmp, 256);
}
}
else
{
for (int i = 0; i < current_amount_transformation; i++)
{
Hash(StrTmp, cPassLen);
strcopy(Keys[i], StrTmp, 256);
}
}
for (int i = 0; i < current_amount_transformation; i++)
{
if ((i % 3) == 0)
{
KeyForSuperpositionGen(Keys[i]);
if (UnCrypt) RevKeyForSuperposition(Keys[i]);
}
if ((i % 3) == 2) BitShiftKeyPrepare(Keys[i], UnCrypt);
}
}
После этого все шифруется правильно. С внешним файлом не проверял.