"Оцифровка" бизнес-процессов.

   
     +7 (910) 778-05-31, romanb@nxt.ru
Коснитесь для звонка

Простая и надежная криптосистема с открытым кодом на C++(симметричное шифрование)

Внимание! Приведенная информация распространяется исключительно в ознакомительных целях. Перед использованием данных материалов рекомендуется ознакомиться с ФЗ Российской Федерации от 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-ФЗ "О лицензировании отдельных видов деятельности".

5 комментариев на данный момент.

  1. Андрей:

    Ссылка на подключаемую внешнюю компоненту, к сожалению, не работает =( 

    Не могли бы Вы ее подправить?

    Спасибо!

    • admin:

      Здравствуйте. Честно даже уже не знаю где ее искать тепрерь. Видимо потерялась при переносе сайта. Приношу извинения, н опомочь, видимо, не смогу

  2. Гляньте, пожалуйста в функцию 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] что-то другое стоять должно.

  3. Vladimir:

    Почему-то не работает с ключом больше 8

  4. Vladimir:

    Решение нашел, может кому пригодится.
    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);
        }
    }

    После этого все шифруется правильно. С внешним файлом не проверял.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *