Добавил:
korayakov
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:
//
// Copyright (C) 1995, by Stanislav Asanov
// FIDOnet: 2:5030/53.30
// Internet: acm@opensys.spb.su
//
// (PATCHED)
//
#include "Gost.h"
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};
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 }
};
byte H_ [4][256];
DWORD X [32];
DWORD a, b, a_new, d;
long pow_2_32 = 4294967296;
typedef struct {
byte b1: 8;
byte b2: 8;
byte b3: 8;
byte b4: 8;
} _tmp;
_tmp tmp;
//=================================================================================
// Обязятельна инициализация перед использованием:
void Init () {
memset (H_,0,sizeof(H_));
for (int i = 0; i <= 3; i++) {
for (int j = 0; j <= 255; j++) {
int j1 = (int)floor(j/16);
int j2 = j%16;
H_[i][j] = H[i*2+1][j1]*16 + H[i*2][j2];
}
}
}
//=================================================================================
void Encrypt (DWORD* data, ANSI strKey) { // DWORD data[2]
DWORD key[8];
memcpy (key,ANSI256toDWORD8(strKey),8*sizeof(DWORD));
for(int i = 0; i <= 31; i++ )
X[i] = key[indexes[i]];
a = data[0];
b = data[1];
for(int j = 0; j <= 31; j++ ) { // Encryption cycles
d = a+X[j]-pow_2_32;
if (d<0) d = -d;
memcpy (&tmp,&d,4);
tmp.b1 = H_[0][tmp.b1];
tmp.b2 = H_[1][tmp.b2];
tmp.b3 = H_[2][tmp.b3];
tmp.b4 = H_[3][tmp.b4];
memcpy (&d,&tmp,4);
a_new = ( ((d&0x001FFFFFUL) << 11) + ((d&0xFFE00000UL)>>21) ) ^ b;
b = a;
a = a_new;
};
data[0] = b;
data[1] = a;
}
//=================================================================================
void EncryptNum (DWORD* data, DWORD* key) { // DWORD data[2]; DWORD key[8];
for(int i = 0; i <= 31; i++ )
X[i] = key[indexes[i]];
a = data[0];
b = data[1];
for(int j = 0; j <= 31; j++ ) { // Encryption cycles
d = a+X[j]-pow_2_32;
if (d<0) d = -d;
memcpy (&tmp,&d,4);
tmp.b1 = H_[0][tmp.b1];
tmp.b2 = H_[1][tmp.b2];
tmp.b3 = H_[2][tmp.b3];
tmp.b4 = H_[3][tmp.b4];
memcpy (&d,&tmp,4);
a_new = ( ((d&0x001FFFFFUL) << 11) + ((d&0xFFE00000UL)>>21) ) ^ b;
b = a;
a = a_new;
};
data[0] = b;
data[1] = a;
}
//=================================================================================
void Decrypt (DWORD* data, ANSI strKey) { // DWORD data[2]
DWORD key[8];
memcpy (key,ANSI256toDWORD8(strKey),8*sizeof(DWORD));
for(int i = 0; i <= 31; i++ )
X[i] = key[indexes[i]];
a = data[0];
b = data[1];
for(int j = 0; j <= 31; j++ ) { // Encryption cycles
d = a+X[31-j]-pow_2_32;
if (d<0) d = -d;
memcpy (&tmp,&d,4);
tmp.b1 = H_[0][tmp.b1];
tmp.b2 = H_[1][tmp.b2];
tmp.b3 = H_[2][tmp.b3];
tmp.b4 = H_[3][tmp.b4];
memcpy (&d,&tmp,4);
a_new = ( ((d&0x001FFFFFUL) << 11) + ((d&0xFFE00000UL)>>21) ) ^ b;
b = a;
a = a_new;
};
data[0] = b;
data[1] = a;
}
//=================================================================================
void DecryptNum (DWORD* data, DWORD* key) { // DWORD data[2]; DWORD key[8];
for(int i = 0; i <= 31; i++ )
X[i] = key[indexes[i]];
a = data[0];
b = data[1];
for(int j = 0; j <= 31; j++ ) { // Encryption cycles
d = a+X[31-j]-pow_2_32;
if (d<0) d = -d;
memcpy (&tmp,&d,4);
tmp.b1 = H_[0][tmp.b1];
tmp.b2 = H_[1][tmp.b2];
tmp.b3 = H_[2][tmp.b3];
tmp.b4 = H_[3][tmp.b4];
memcpy (&d,&tmp,4);
a_new = ( ((d&0x001FFFFFUL) << 11) + ((d&0xFFE00000UL)>>21) ) ^ b;
b = a;
a = a_new;
};
data[0] = b;
data[1] = a;
}
//=================================================================================
// Вспомогательная функция для перевода массива из 8-ми double(ов) в строку типа "1101010...".
ANSI DWORD8toANSI256 (DWORD* key) {
ANSI strData;
char tmp[100];
for (int k = 0; k <= 7; k++) {
ANSI strTmp = (byte*)ultoa(key[k],tmp,2);
while (strTmp.size() <= 31)
strTmp.insert(0,'0');
strData += strTmp;
}
return strData;
}
//=================================================================================
// Вспомогательная функция для перевода строки "10110011..." в массив из 8-ми DWORD(ов).
DWORD* ANSI256toDWORD8 (ANSI str) {
DWORD d[8];
for (int k = 0; k <= 7; k++) {
d[k] = 0;
for (int i = 0; i <= 31; i++)
d[k] += (str.at(k*32 + i)-48) * pow(2,31-i);
}
return d;
}