Вы находитесь на странице: 1из 19

МИНОБРНАУКИ РОССИИ

Федеральное государственное бюджетное образовательное


учреждение высшего образования
«Тульский государственный университет»

КАФЕДРА ИНФОРМАЦИОННОЙ БЕЗОПАСНОСТИ

ПРОГРАММНО-АППАРАТНЫЕ СРЕДСТВА ОБЕСПЕЧЕНИЯ


ИНФОРМАЦИОННОЙ БЕЗОПАСНОСТИ

Лабораторная работа № 1
Защита от разрушающих программных воздействий, защита
программ от изменения и контроль целостности

Выполнили: ст. группы 230711


Акользина И. С.
Кузнецова А. В.
Кузьминова С. С.
Проверил:
Абрамов Д. А.
______________

Тула 2015
1. Цель работы
Познакомиться с общими принципами защиты программного
обеспечения и способами организации контроля целостности исполняемых
модулей и важных программных данных.

2. Задание на работу
Вариант № 3. Контроль целостности программных данных (данные
неизменны).

3. Теоретическая справка
Основным методом борьбы с модификацией программного
обеспечения является контроль целостности. Реализация этого может быть
достигнута методами проверки контрольной суммы и цифровой подписью.

Проверка контрольной суммы. Алгоритм MD5


Для обработки алгоритм MD5 получает некоторую строку. Эта строка
преобразуется в последовательность из нулей и единиц. У каждого символа
имеется свой номер. Эти номера можно записать в двоичной системе
счисления. Если этим воспользоваться, получим из строки
последовательность из нулей и единиц. Пусть q будет длина получившейся
последовательности (ровно 64 бита, возможно, с незначащими нулями). К
получившейся последовательности приписывается 1. В результате длина
последовательности увеличивается на 1. Затем к последовательности
приписываются нули, пока длина не станет по модулю 512 равна 448 (length
mod 512=448). Далее к последовательности дописываются младшие 32 бита
числа q, а затем — старшие. Длина последовательности становится кратной
512. Полученную последовательность назовем S. Для подсчета результата
используются четыре двойных слова (32 бита). Эти двойные слова
инициализируются следующими шестнадцатеричными значениями, где
первым следует самый младший байт:
2
A: 01 23 45 67
B: 89 ab cd ef
C: fe dc ba 98
D: 76 54 32 10
Также для подсчета результата используются следующие функции:
F(X,Y,Z) = XY v not(X) Z
G(X,Y,Z) = XZ v Y not(Z)
H(X,Y,Z) = X xor Y xor Z
I(X,Y,Z) = Y xor (X v not(Z))
X,Y,Z — это двойные слова. Результаты функций - также двойные
слова. Для подсчета используется еще одна функция (назовем ее W). Она
обрабатывает данные и возвращает результат. Обработка данных происходит
с использованием функций F, G, H, I.
Просчет результата:
1. Запоминаем первые 512 бит последовательности S.
2. Удаляем первые 512 бит последовательности S (можно обойтись и без
удаления, но тогда на первом шаге надо брать не первые 512, а следующие
512 бит).
3. Вызываем функцию W. Параметры A,B,C,D — это текущие значения
соответствующих двойных слов. Параметр T — это запомненные 512 бит.
4. Прибавляем к A A0.
5. B=B+B0.
6. C=C+C0.
7. D=D+D0.
8. Если длина последовательности 0, выходим.
9. Переходим к шагу 1.
После выполнения этого алгоритма A,B,C,D — это результат (его
длина будет 128 бит). Часто можно видеть результат MD5 как
последовательность из 32 символов 0..f. Это то же самое, только результат
записан не в двоичной системе счисления, а в шестнадцатеричной.
3
Цифровая подпись. Алгоритм DSA
Стандарт цифровой подписи DSS (Digital Signature Standard – DSS) был
принят в США в 1991 году и пересмотрен в 1994 году. В основе стандарта
лежит алгоритм, называемый DSA (Digital Signature Algorithm) и
являющийся вариацией подписи Эль-Гамаля. В алгоритме используется
однонаправленная хеш-функция H(m).
Рассмотрим сам алгоритм генерации ЭЦП. Вначале для группы
абонентов выбираются три общих (несекретных) параметра р, q и a:
 параметр р должен быть простым числом длиной от 512 до 1024 бит;
 q – простое число длиной 160 бит; между p и q должно выполняться
соотношение p = bq + 1 для некоторого целого b. Старшие биты в р и q
должны быть равны единице (таким образом 2159 < q < 2160 );
 число а, удовлетворяющее неравенству 1 < a < p-1 и являющееся
корнем уравнения aq mod p = 1.
Зная эти числа, каждый абонент системы случайно выбирает число х,
удовлетворяющее неравенству 0 < х < q, и вычисляет y = ax mod p.
Число х будет секретным ключом пользователя, а число у — открытым
ключом. Вычислить у по известному х довольно просто. Однако, имея
открытый ключ у, вычислительно невозможно определить х, который
является дискретным логарифмом у по основанию a.
Предполагается, что открытые ключи всех пользователей указываются
в некотором несекретном, но "сертифицированном" справочнике, который
должен быть у всех, кто собирается проверять подписи. На этом этап выбора
параметров заканчивается, и абоненты готовы к тому, чтобы формировать и
проверять подписи.
Пусть имеется сообщение m, которое один из пользователей желает
подписать. Для генерации подписи пользователь должен выполнить
следующие действия:
 Вычислить значение хеш-функции h = H(m) для сообщения m.
Значение хеш-функции должно лежать в пределах 0 < h < q.
4
 Затем сгенерировать случайное число k, 0 < k < q.
 Вычислить r = (ak mod p) mod q.
 Определить s = [k-1 (H(m) + x * r)] mod q.
В результате пользователь получит для сообщения m подпись,
состоящую из пары чисел (r,s). Сообщение вместе с подписью может быть
послано любому другому абоненту системы. Проверить подпись можно
следующим образом:
 Вычислить значение хеш-функции h = H(m) для сообщения m.
 Проверить выполнение неравенств 0 < r < q, 0 < s < q.
 Вычислить w = s-1 mod q.
 u1 = [H(m) * w] mod q.
 u2 = r * w mod q.
 v = [(аu1 * yu2) mod p] mod q.
 Проверить выполнение равенства v = r. Если v = r, то подпись
считается подлинной, иначе подпись считается недействительной.
В силу сложности вычисления дискретных логарифмов
злоумышленник не может восстановить k из r или х из s, а следовательно, не
может подделать подпись. По той же самой причине автор сообщения не
сможет отказаться от своей подписи, так как никто кроме него не знает
закрытого ключа х.

4. Ход работы
В программной реализации системы контроля целостности участвуют
следующие проекты:
1. Приложение для проверки контрольной суммы входного файла по
алгоритму MD5.
2. Приложение для подсчета контрольной суммы входного файла по
алгоритму: сумма по модулю 216 всех пар байт исходного файла (значение
хеш-кода используется при формировании и проверке цифровой подписи).

5
3. Приложение для формирования открытых и закрытых ключей
цифровой подписи.
4. Приложение для формирования присоединяемой к файлу цифровой
подписи по алгоритму DSA.
5. Приложение для проверки присоединяемой цифровой подписи.

Программа 1
// pasoib_1.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "md5.h"
using namespace std;

ifstream in("in.txt"); //Путь к проверяемому файлу


ifstream in1("hash.txt"); //Значение хеш-кода, вычисленное ранее
ofstream out1("hash1.txt"); //Значение хеш-кода, вычисленное в результате работы
программы
ofstream out("out.txt"); //Результат проверки

int _tmain(int argc, _TCHAR* argv[])


{
char* p;
p=new char[100];
in >> p;

FILE *file;
char x1;
file=fopen(p, "rb+");

long size;
fseek(file, 0, SEEK_END);
size=ftell(file);
fseek(file, 0, SEEK_SET);

char* mass;
mass=new char[size];

for (long i=0; i<size; i++)


{
fread(&x1, sizeof(char),1,file);
mass[i]=x1;
}

//Вычисление хеш-кода по алгоритму md5


string m=function(mass, size);
out1 << m << endl;

//Проверка контрольной суммы


string h;
in1 >> h;

if (m==h) out << "Контрольная сумма правильная";


else out << "Контрольная сумма неправильная";

fclose(file);
6
return 0;
}

Файл md5.h:
#include "stdafx.h"
using namespace std;

#ifdef __alpha
typedef unsigned int UINT4;
#else
typedef unsigned long int UINT4;
#endif

#define MD5_INIT_STATE_0 0x67452301


#define MD5_INIT_STATE_1 0xefcdab89
#define MD5_INIT_STATE_2 0x98badcfe
#define MD5_INIT_STATE_3 0x10325476

void MD5Init(void);
void MD5Update(unsigned char *bug, unsigned int len);
void MD5Final(char* cReturnStr);
void Transform(UINT4 *buf, UINT4 *in);

unsigned char m_lpszBuffer[64];


unsigned long m_nCount[2];
unsigned long m_lMD5[4];

static unsigned char PADDING[64] = {


0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))


#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
#define H(x, y, z) ((x) ^ (y) ^ (z))
#define I(x, y, z) ((y) ^ ((x) | (~z)))

#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))

#define FF(a, b, c, d, x, s, ac) \


{(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define GG(a, b, c, d, x, s, ac) \
{(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define HH(a, b, c, d, x, s, ac) \
{(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \

7
}
#define II(a, b, c, d, x, s, ac) \
{(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}

void ByteToDWord(DWORD* Output, ULONG* Input, UINT nLength)


{
UINT i=0;
UINT j=0;
for (; j < nLength; i++, j += 4)
{
Output[i] = (ULONG)Input[j] |
(ULONG)Input[j+1] << 8 |
(ULONG)Input[j+2] << 16 |
(ULONG)Input[j+3] << 24;
}
}

void DWordToByte(unsigned char* Output, DWORD* Input, UINT nLength )


{
UINT i = 0;
UINT j = 0;
for (; j < nLength; i++, j += 4)
{
Output[j] = (UCHAR)(Input[i] & 0xff);
Output[j+1] = (UCHAR)((Input[i] >> 8) & 0xff);
Output[j+2] = (UCHAR)((Input[i] >> 16) & 0xff);
Output[j+3] = (UCHAR)((Input[i] >> 24) & 0xff);
}
}

void MD5Init (void)


{
memset(m_lpszBuffer, 0, 64 );
m_nCount[0] = m_nCount[1] = 0;

m_lMD5[0] = MD5_INIT_STATE_0;
m_lMD5[1] = MD5_INIT_STATE_1;
m_lMD5[2] = MD5_INIT_STATE_2;
m_lMD5[3] = MD5_INIT_STATE_3;
}

void MD5Update (unsigned char *inBuf, unsigned int inLen)


{
register int i, ii;
int mdi;
UINT4 in[16];

mdi = (int)((m_nCount[0] >> 3) & 0x3F);

if ((m_nCount[0] + ((UINT4)inLen << 3)) < m_nCount[0])


m_nCount[1]++;
m_nCount[0] += ((UINT4)inLen << 3);
m_nCount[1] += ((UINT4)inLen >> 29);

while (inLen--)
{
m_lpszBuffer[mdi++] = *inBuf++;

if (mdi == 0x40)

8
{
for (i = 0, ii = 0; i < 16; i++, ii += 4)
in[i] = (((UINT4)m_lpszBuffer[ii+3]) << 24) |
(((UINT4)m_lpszBuffer[ii+2]) << 16) |
(((UINT4)m_lpszBuffer[ii+1]) << 8) |
((UINT4)m_lpszBuffer[ii]);
Transform (m_lMD5, in);
mdi = 0;
}
}
}

void MD5Final (char* cReturnStr)


{
unsigned char bits[8];
int nIndex;
unsigned int nPadLen;
const int nMD5Size = 16;
unsigned char lpszMD5[16];
char temp[3];
int i;

cReturnStr[0]='\0';

DWordToByte( bits, m_nCount, 8 );

nIndex = (int)((m_nCount[0] >> 3) & 0x3f);


nPadLen = (nIndex < 56) ? (56 - nIndex) : (120 - nIndex);
MD5Update (PADDING, nPadLen);

MD5Update (bits, 8);

DWordToByte( lpszMD5, m_lMD5, nMD5Size );

for (i=0; i < nMD5Size; i++)


{

if (lpszMD5[i] == 0)
{
temp[0] = '0';
temp[1]='0';
}
else if (lpszMD5[i] <= 15)
{
sprintf(temp,"0%x",lpszMD5[i]);
}
else
{
sprintf(temp,"%x",lpszMD5[i]);
}
strcat(cReturnStr,temp);
}
lpszMD5[0]='\0';
}

void Transform(register UINT4 *buf,register UINT4 *in)


{
register UINT4 a = buf[0], b = buf[1], c = buf[2], d = buf[3];

#define S11 7
#define S12 12
#define S13 17
9
#define S14 22
FF ( a, b, c, d, in[ 0], S11, 0xD76AA478L);
FF ( d, a, b, c, in[ 1], S12, 0xE8C7B756L);
FF ( c, d, a, b, in[ 2], S13, 0x242070DBL);
FF ( b, c, d, a, in[ 3], S14, 0xC1BDCEEEL);
FF ( a, b, c, d, in[ 4], S11, 0xF57C0FAFL);
FF ( d, a, b, c, in[ 5], S12, 0x4787C62AL);
FF ( c, d, a, b, in[ 6], S13, 0xA8304613L);
FF ( b, c, d, a, in[ 7], S14, 0xFD469501L);
FF ( a, b, c, d, in[ 8], S11, 0x698098D8L);
FF ( d, a, b, c, in[ 9], S12, 0x8B44F7AFL);
FF ( c, d, a, b, in[10], S13, 0xFFFF5BB1L);
FF ( b, c, d, a, in[11], S14, 0x895CD7BEL);
FF ( a, b, c, d, in[12], S11, 0x6B901122L);
FF ( d, a, b, c, in[13], S12, 0xFD987193L);
FF ( c, d, a, b, in[14], S13, 0xA679438EL);
FF ( b, c, d, a, in[15], S14, 0x49B40821L);

#define S21 5
#define S22 9
#define S23 14
#define S24 20
GG ( a, b, c, d, in[ 1], S21, 0xF61E2562L);
GG ( d, a, b, c, in[ 6], S22, 0xC040B340L);
GG ( c, d, a, b, in[11], S23, 0x265E5A51L);
GG ( b, c, d, a, in[ 0], S24, 0xE9B6C7AAL);
GG ( a, b, c, d, in[ 5], S21, 0xD62F105DL);
GG ( d, a, b, c, in[10], S22, 0x02441453L);
GG ( c, d, a, b, in[15], S23, 0xD8A1E681L);
GG ( b, c, d, a, in[ 4], S24, 0xE7D3FBC8L);
GG ( a, b, c, d, in[ 9], S21, 0x21E1CDE6L);
GG ( d, a, b, c, in[14], S22, 0xC33707D6L);
GG ( c, d, a, b, in[ 3], S23, 0xF4D50D87L);
GG ( b, c, d, a, in[ 8], S24, 0x455A14EDL);
GG ( a, b, c, d, in[13], S21, 0xA9E3E905L);
GG ( d, a, b, c, in[ 2], S22, 0xFCEFA3F8L);
GG ( c, d, a, b, in[ 7], S23, 0x676F02D9L);
GG ( b, c, d, a, in[12], S24, 0x8D2A4C8AL);

#define S31 4
#define S32 11
#define S33 16
#define S34 23
HH ( a, b, c, d, in[ 5], S31, 0xFFFA3942L);
HH ( d, a, b, c, in[ 8], S32, 0x8771F681L);
HH ( c, d, a, b, in[11], S33, 0x6D9D6122L);
HH ( b, c, d, a, in[14], S34, 0xFDE5380CL);
HH ( a, b, c, d, in[ 1], S31, 0xA4BEEA44L);
HH ( d, a, b, c, in[ 4], S32, 0x4BDECFA9L);
HH ( c, d, a, b, in[ 7], S33, 0xF6BB4B60L);
HH ( b, c, d, a, in[10], S34, 0xBEBFBC70L);
HH ( a, b, c, d, in[13], S31, 0x289B7EC6L);
HH ( d, a, b, c, in[ 0], S32, 0xEAA127FAL);
HH ( c, d, a, b, in[ 3], S33, 0xD4EF3085L);
HH ( b, c, d, a, in[ 6], S34, 0x04881D05L);
HH ( a, b, c, d, in[ 9], S31, 0xD9D4D039L);
HH ( d, a, b, c, in[12], S32, 0xE6DB99E5L);
HH ( c, d, a, b, in[15], S33, 0x1FA27CF8L);
HH ( b, c, d, a, in[ 2], S34, 0xC4AC5665L);

#define S41 6
#define S42 10
#define S43 15
#define S44 21
10
II ( a, b, c, d, in[ 0], S41, 0xF4292244L);
II ( d, a, b, c, in[ 7], S42, 0x432AFF97L);
II ( c, d, a, b, in[14], S43, 0xAB9423A7L);
II ( b, c, d, a, in[ 5], S44, 0xFC93A039L);
II ( a, b, c, d, in[12], S41, 0x655B59C3L);
II ( d, a, b, c, in[ 3], S42, 0x8F0CCC92L);
II ( c, d, a, b, in[10], S43, 0xFFEFF47DL);
II ( b, c, d, a, in[ 1], S44, 0x85845DD1L);
II ( a, b, c, d, in[ 8], S41, 0x6FA87E4FL);
II ( d, a, b, c, in[15], S42, 0xFE2CE6E0L);
II ( c, d, a, b, in[ 6], S43, 0xA3014314L);
II ( b, c, d, a, in[13], S44, 0x4E0811A1L);
II ( a, b, c, d, in[ 4], S41, 0xF7537E82L);
II ( d, a, b, c, in[11], S42, 0xBD3AF235L);
II ( c, d, a, b, in[ 2], S43, 0x2AD7D2BBL);
II ( b, c, d, a, in[ 9], S44, 0xEB86D391L);

buf[0] += a;
buf[1] += b;
buf[2] += c;
buf[3] += d;
}

void GetMD5(char* pBuf, UINT nLength,char* cReturnStr)


{
MD5Init();
MD5Update((unsigned char *)pBuf, nLength);
MD5Final(cReturnStr);
}

string function(char* in, long size)


{
char out[33] = {0};
GetMD5(in,size,out);
string m1="";
for (int i=0; i<32; i++)
{
string n(1, out[i]);
m1=m1+n;
}

return m1;
}

Результаты работы программы


Файл in.txt (путь к проверяемому файлу):
D:\doc1.txt

Файл hash.txt (значение хеш-кода, вычисленное ранее):


a30a999e2eef6a89208f56de4fb287df

Файл hash1.txt (значение хеш-кода, вычисленное в результате работы


программы):
11
a30a999e2eef6a89208f56de4fb287df

Файл out.txt (результат проверки):


Контрольная сумма правильная

Программа 2
// pasoib_1_1.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
using namespace std;

ifstream in("in.txt"); //Путь к проверяемому файлу


ofstream out("hash.txt"); //Значение хеш-кода

int _tmain(int argc, _TCHAR* argv[])


{
///Формирование хеш-кода
char* p;
p=new char[100];
in >> p;

FILE *file;
unsigned char x1;
file=fopen(p, "rb+");

long size; //Размер файла


fseek(file, 0, SEEK_END);
size=ftell(file);
fseek(file, 0, SEEK_SET);

unsigned char y1, y2;


unsigned int y=0;
for (long i=0; i<size; i=i+2)
{
fread(&x1, sizeof(unsigned char),1,file);
y1=x1;

if ((size%2!=0)&&(i==size-1))
{
unsigned int e=0;
y2=unsigned char(e);
}
else
{
fread(&x1, sizeof(unsigned char),1,file);
y2=x1;
}
unsigned int y0 = (y1 << 8) | y2;
y = (y + y0)%65536;

if ((i==size-2)||(i==size-1))
{
out << y;
}
12
}

return 0;
}

Результаты работы программы


Файл in.txt (путь к проверяемому файлу):
D:\doc1.txt

Файл hash.txt (значение хеш-кода):


35312

Программа 3
// pasoib_1_2.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
using namespace std;

ofstream out("keys.txt");
ofstream out1("C:\\Users\\Настя\\Desktop\\Программы\\pasoib_1_3\\pasoib_1_3\\keys.txt");
ofstream out2("C:\\Users\\Настя\\Desktop\\Программы\\pasoib_1_4\\pasoib_1_4\\keys.txt");

int p, q, a;
int x, y;

//Возведение в степень по модулю


long long int f0(int a, double b, int c)
{
long long int d=b;
for (int i=1; i<a; i++)
{
d=d*b;
d=d%c;
}
return d;
}

int _tmain(int argc, _TCHAR* argv[])


{
///Нахождение числа p (размер - 16 бит)
for (int i=32768; i<65536; i++)
{
int x=0;
double i1=i;

for (int j=2; j<=sqrt(i1); j++)


{
if (i%j==0) x=1;
}

if (x==0)
{
p=i;
13
goto metka1;
}
}
metka1:

out << p << " ";


out1 << p << " ";
out2 << p << " ";

///Нахождение числа q
for (int b=2; b<p; b++)
{
int u=0;
int y;
if ((p-1)%b==0)
{
y=(p-1)/b;
u=1;
}

if (u==1)
{
int x=0;
double i1=y;

for (int j=2; j<=sqrt(i1); j++)


{
if (y%j==0) x=1;
}

if (x==0)
{
q=y;
goto metka2;
}
}
}

metka2:

out << q << " ";


out1 << q << " ";
out2 << q << " ";

///Нахождение числа a
for (int i=2; i<p-1; i++)
{
int b;
b=f0(q, i, p);
if (b==1)
{
a=i;
goto metka3;
}
}

metka3:

out << a << " ";


out1 << a << " ";
out2 << a << " ";

///Выбор числа x
srand(time(NULL));

14
x=1+rand()%(q-1);

out << x << " ";


out1 << x << " ";

///Вычисление числа y
y=f0(x, a, p);

out << y << endl;


out1 << y << endl;
out2 << y << endl;

return 0;
}

Результаты работы программы


Файл keys.txt (значения общих параметров p, q, a и сформированных
закрытого и открытого ключей):
32771 113 300 40 32386

Программа 4
// pasoib_1_3.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
using namespace std;

ifstream in("C:\\Users\\Настя\\Desktop\\Программы\\pasoib_1_1\\pasoib_1_1\\hash.txt");
ifstream in1("keys.txt");
ofstream out("rs.txt");
ofstream out1("C:\\Users\\Настя\\Desktop\\Программы\\pasoib_1_4\\pasoib_1_4\\rs.txt");

int p, q, a;
int x, y;
int k;
int r, s;
int h;

//Возведение в степень по модулю


long long int f0(int a, double b, int c)
{
long long int d=b;
for (int i=1; i<a; i++)
{
d=d*b;
d=d%c;
}
return d;
}

int _tmain(int argc, _TCHAR* argv[])


{
in >> h;
in1 >> p >> q >> a >> x >> y;

15
///Выбор числа k
srand(time(NULL));
k=1+rand()%(q-1);

///Вычисление r
r=f0(k, a, p);
r=r%q;

///Вычисление s
int s0;
///Нахождение числа s0 = k^(-1) mod q (обобщенный алгоритм Евклида)
int u[3];
int v[3];
int t[3];

u[0]=k; u[1]=1; u[2]=0;


v[0]=q; v[1]=0; v[2]=1;

while (v[0]!=0)
{
int q0 = u[0]/v[0];
t[0]=u[0]%v[0];
t[1]=u[1]-q0*v[1];
t[2]=u[2]-q0*v[2];

for (int i=0; i<3; i++)


{
u[i]=v[i];
v[i]=t[i];
}
}

s0=u[1];
while (s0<0)
s0=s0+q;

s=(s0*(h+x*r))%q;

out << r << " " << s << endl;


out1 << r << " " << s << endl;

return 0;
}

Результаты работы программы


Файл hash.txt (значение хеш-кода файла):
35312

Файл keys.txt (значения общих параметров p, q, a и сформированных


закрытого и открытого ключей):
32771 113 300 40 32386

Файл rs.txt (цифровая подпись файла):


16
28 38

Программа 5
// pasoib_1_4.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
using namespace std;

ifstream in("C:\\Users\\Настя\\Desktop\\Программы\\pasoib_1_1\\pasoib_1_1\\hash.txt");
ifstream in1("keys.txt");
ifstream in2("rs.txt");
ofstream out("rez.txt");

int p, q, a;
int x, y;
int r, s;
int w;
int u1, u2, vv;
int h;

//Возведение в степень по модулю


long long int f0(int a, double b, int c)
{
long long int d=b;
for (int i=1; i<a; i++)
{
d=d*b;
d=d%c;
}
return d;
}

int _tmain(int argc, _TCHAR* argv[])


{
setlocale(LC_ALL, "RUS");

in >> h;
in1 >> p >> q >> a >> y;
in2 >> r >> s;

///Нахождение числа w (обобщенный алгоритм Евклида)


int u[3];
int v[3];
int t[3];

u[0]=s; u[1]=1; u[2]=0;


v[0]=q; v[1]=0; v[2]=1;

while (v[0]!=0)
{
int q0 = u[0]/v[0];
t[0]=u[0]%v[0];
t[1]=u[1]-q0*v[1];
t[2]=u[2]-q0*v[2];

for (int i=0; i<3; i++)


{
u[i]=v[i];
17
v[i]=t[i];
}
}

w=u[1];
while (w<0)
w=w+q;

///Вычисление u1 и u2
u1=(h*w)%q;
u2=(r*w)%q;

///Вычисление v
int v1, v2;
v1=f0(u1, a, p);
v2=f0(u2, y, p);
vv=((v1*v2)%p)%q;

///Проверка подписи
if ((vv==r)&&(r>0)&&(r<q)&&(s>0)&&(s<q))
out << "Подпись действительна" << endl;
else out << "Подпись недействительна" << endl;

return 0;
}

Результаты работы программы


Файл hash.txt (значение хеш-кода файла):
35312

Файл keys.txt (значения общих параметров p, q, a и сформированного


открытого ключа):
32771 113 300 32386

Файл rs.txt (цифровая подпись файла):


28 38

Файл rez.txt (результат проверки цифровой подписи):


Подпись действительна

5. Вывод
В процессе выполнения лабораторной работы мы познакомились с
общими принципами защиты программного обеспечения и способами

18
организации контроля целостности исполняемых модулей и важных
программных данных.
Механизм контроля целостности является важной компонентой
защиты, образуя отдельный функциональный уровень защиты информации
от НСД. Его принципиальным отличием от остальных механизмов защиты
является то, что данным механизмом может быть зарегистрирован сам факт
НСД, причем вне зависимости от причин его происхождения (например, в
результате использования злоумышленником ошибок и закладок в ПО).
Поэтому развитый набор механизмов контроля целостности является
важнейшим условием эффективной защиты от НСД.

19