Скачиваний:
65
Добавлен:
17.04.2013
Размер:
5.83 Кб
Скачать
//
// Copyright (C) 1995, by Stanislav Asanov
//     FIDOnet:  2:5030/53.30
//     Internet: acm@opensys.spb.su
//

#include "Gost.h"

//=================================================================================
/*
Параметры:	data  - массив из 8 байтов.
						key		- массив из 8 double(ов).
*/
void Encrypt (byte* data, DWORD* dwKey) {
	int indexes[] = {0,1,2,3,4,5,6,7,0,1,2,3,4,5,6,7,0,1,2,3,4,5,6,7,7,6,5,4,3,2,1,0};
	DWORD X [32];
	byte H[8][16] =	{
		{0x2, 0xE, 0x9, 0x5, 0x7, 0x6, 0x4, 0xA, 0x0, 0xB, 0x8, 0xD, 0x3, 0x1, 0xF, 0xC },
		{0xA, 0xB, 0xE, 0x3, 0x4, 0xD, 0x7, 0x1, 0x6, 0x5, 0x2, 0x8, 0x0, 0xF, 0x9, 0xC },
		{0x3, 0xA, 0x2, 0xC, 0x8, 0xE, 0xF, 0x4, 0x5, 0x6, 0xD, 0x0, 0x9, 0xB, 0x1, 0x7 }, 
		{0xB, 0xE, 0xC, 0x4, 0x7, 0x6, 0xF, 0x9, 0x3, 0x8, 0x5, 0xD, 0x2, 0x1, 0x0, 0xA }, 
		{0xC, 0xF, 0xA, 0x8, 0x2, 0x9, 0x7, 0x6, 0x3, 0x4, 0xE, 0x5, 0x1, 0xB, 0xD, 0x0 }, 
		{0x8, 0x6, 0x2, 0x5, 0x3, 0xA, 0x4, 0x7, 0xD, 0x1, 0x9, 0xB, 0xC, 0xE, 0x0, 0xF }, 
		{0x3, 0xF, 0xA, 0xE, 0x6, 0x2, 0x4, 0xD, 0x1, 0x0, 0x9, 0x7, 0xB, 0xC, 0x5, 0x8 }, 
		{0x2, 0x9, 0xE, 0x4, 0x7, 0xB, 0x1, 0x0, 0x8, 0x3, 0xD, 0xA, 0xF, 0xC, 0x5, 0x6 }
	};
	DWORD key[8];
	memcpy (key, dwKey, 8*sizeof(DWORD));
	int i, j;
	DWORD a, b, a_new;
	// Initialization:
	for (i = 0; i <= 31; i++) 
		X[i] = key[indexes[i]];
	DWORD d;
	struct {
		byte b0: 4;
		byte b1: 4;
		byte b2: 4;
		byte b3: 4;
		byte b4: 4;
		byte b5: 4;
		byte b6: 4;
		byte b7: 4;
	} tmp;
	a = data[0]*256*256*256 + data[1]*256*256 + data[2]*256 + data[3];
	b = data[4]*256*256*256 + data[5]*256*256 + data[6]*256 + data[7];
	for( j = 0; j < 32; j++ ) { // Encryption cycles
		d = fmod (a + X[j], pow(2,32));
		memcpy(&tmp,&d,32);
		tmp.b0 = H[0][tmp.b0];
		tmp.b1 = H[1][tmp.b1];
		tmp.b2 = H[2][tmp.b2];
		tmp.b3 = H[3][tmp.b3];
		tmp.b4 = H[4][tmp.b4];
		tmp.b5 = H[5][tmp.b5];
		tmp.b6 = H[6][tmp.b6];
		tmp.b7 = H[7][tmp.b7];
		memcpy(&d,&tmp,32);
		a_new = ( ((d&0x001FFFFFUL) << 11) + ((d&0xFFE00000UL)>>21) ) ^ b;
		b = a;
		a = a_new;
	};
	data[0] = fmod(b>>24,256);
	data[1] = fmod(b>>16,256);
	data[2] = fmod(b>>8,256);
	data[3] = fmod(b>>0,256);
	data[4] = fmod(a>>24,256);
	data[5] = fmod(a>>16,256);
	data[6] = fmod(a>>8,256);
	data[7] = fmod(a>>0,256);
};

//=================================================================================
/*
Параметры:	data  - массив из 8 байтов.
						key		- строка типа "10010101..." из 256 символов.
*/
void Encrypt2 (byte* data, ANSI strKey) {
	DWORD key[8];
	for (int i = 0; i <= 7; i++) {
		key[i] = 0;
		for (int j = 0; j <= 31; j++) {
			key[i] += (strKey.at(i*32+j)-48) * pow(2,31-j);
		}
	}
	Encrypt(data, key);
}

//=================================================================================
/*
Параметры:	data  - массив из 8 байтов.
						key		- массив из 8 double(ов).
*/
void Decrypt (byte* data, DWORD* dwKey) {
	int indexes[] = {0,1,2,3,4,5,6,7,0,1,2,3,4,5,6,7,0,1,2,3,4,5,6,7,7,6,5,4,3,2,1,0};
	DWORD X [32];
	byte H[8][16] =	{
		{0x2, 0xE, 0x9, 0x5, 0x7, 0x6, 0x4, 0xA, 0x0, 0xB, 0x8, 0xD, 0x3, 0x1, 0xF, 0xC },
		{0xA, 0xB, 0xE, 0x3, 0x4, 0xD, 0x7, 0x1, 0x6, 0x5, 0x2, 0x8, 0x0, 0xF, 0x9, 0xC },
		{0x3, 0xA, 0x2, 0xC, 0x8, 0xE, 0xF, 0x4, 0x5, 0x6, 0xD, 0x0, 0x9, 0xB, 0x1, 0x7 }, 
		{0xB, 0xE, 0xC, 0x4, 0x7, 0x6, 0xF, 0x9, 0x3, 0x8, 0x5, 0xD, 0x2, 0x1, 0x0, 0xA }, 
		{0xC, 0xF, 0xA, 0x8, 0x2, 0x9, 0x7, 0x6, 0x3, 0x4, 0xE, 0x5, 0x1, 0xB, 0xD, 0x0 }, 
		{0x8, 0x6, 0x2, 0x5, 0x3, 0xA, 0x4, 0x7, 0xD, 0x1, 0x9, 0xB, 0xC, 0xE, 0x0, 0xF }, 
		{0x3, 0xF, 0xA, 0xE, 0x6, 0x2, 0x4, 0xD, 0x1, 0x0, 0x9, 0x7, 0xB, 0xC, 0x5, 0x8 }, 
		{0x2, 0x9, 0xE, 0x4, 0x7, 0xB, 0x1, 0x0, 0x8, 0x3, 0xD, 0xA, 0xF, 0xC, 0x5, 0x6 }
	};
	DWORD key[8];
	memcpy (key, dwKey, 8*sizeof(DWORD));
	int i, j;
	DWORD a, b, a_new;
	// Initialization:
	for (i = 0; i <= 31; i++) 
		X[i] = key[indexes[i]];
	DWORD d;
	struct {
		byte b0: 4;
		byte b1: 4;
		byte b2: 4;
		byte b3: 4;
		byte b4: 4;
		byte b5: 4;
		byte b6: 4;
		byte b7: 4;
	} tmp;
	a = data[0]*256*256*256 + data[1]*256*256 + data[2]*256 + data[3];
	b = data[4]*256*256*256 + data[5]*256*256 + data[6]*256 + data[7];
	for( j = 0; j < 32; j++ ) { // Decryption cycles
		d = fmod(a + X[31-j], pow(2,32)); // !!! The only difference between encryption and decryption
		memcpy(&tmp,&d,32);
		tmp.b0 = H[0][tmp.b0];
		tmp.b1 = H[1][tmp.b1];
		tmp.b2 = H[2][tmp.b2];
		tmp.b3 = H[3][tmp.b3];
		tmp.b4 = H[4][tmp.b4];
		tmp.b5 = H[5][tmp.b5];
		tmp.b6 = H[6][tmp.b6];
		tmp.b7 = H[7][tmp.b7];
		memcpy(&d,&tmp,32);
		a_new = ( ((d&0x001FFFFFUL) << 11) + ((d&0xFFE00000UL)>>21) ) ^ b;
		b = a;
		a = a_new;
	};
	data[0] = fmod(b>>24,256);
	data[1] = fmod(b>>16,256);
	data[2] = fmod(b>>8,256);
	data[3] = fmod(b>>0,256);
	data[4] = fmod(a>>24,256);
	data[5] = fmod(a>>16,256);
	data[6] = fmod(a>>8,256);
	data[7] = fmod(a>>0,256);
};

//=================================================================================
/*
Параметры:	data  - массив из 8 байтов.
						key		- строка типа "10010101..." из 256 символов.
*/
void Decrypt2 (byte* data, ANSI strKey) {
	DWORD key[8];
	for (int i = 0; i <= 7; i++) {
		key[i] = 0;
		for (int j = 0; j <= 31; j++) {
			key[i] += (strKey.at(i*32+j)-48) * pow(2,31-j);
		}
	}
	Decrypt(data, key);
}

//=================================================================================
// Вспомогательная функция для перевода массива из 8 double(ов) в строку типа "1101010...".
ANSI DWORD8toANSI256 (DWORD* key) {
	ANSI strData;
	for (int k = 0; k <= 7; k++) {
		char tmp[100];
		ANSI strTmp = (byte*)ultoa(key[k],tmp,2);
		int m = strTmp.size();
		for (int mm = m; mm < 32; mm++) {
			strTmp.insert(0,'0');
		}
		strData += strTmp;
	}
	return strData;
}
Соседние файлы в папке ГОСТ