Консультация № 190121
22.11.2016, 09:34
0.00 руб.
0 2 1
Здравствуйте! У меня возникли сложности с таким вопросом:Разработать программу на С++ для реализации алгоритма шифрования и расшифрования данных, используя метод гаммирования и поразрядного циклического сдвига. Алгоритм: для блока данных заданного размера берется такого же размера фрагмент гаммы и выполняется операция поразрядного исключающего «ИЛИ», далее, выполняется операция поразрядного циклического сдвига на заданное число бит влево или вправо с полученным новым блоком. Расшифрование выполняется в обратном порядке, вначале циклический сдвиг в противоположную сторону, а затем операция поразрядного исключающего «ИЛИ» с блоками той же самой гаммы.
Для получения гаммы можно использовать стандартный генератор псевдослучайный чисел (функцию rand, функция rand() генерирует воспроизводимую последовательность псевдослучайных чисел, при каждом обращении к функции возвращается целое в интервале между нулем и значением RAND_MAX, которое в любой реализации должно быть не меньше числа 32767, обратить внимание, при величине обрабатываемого блока данных 4 байта, возможно, для заполнения блока гаммы использовать два вызова функции), для начальной инициализации генератора использовать функцию srand (значение начальной инициализации является частью секретного ключа, другой частью ключа является размер поразрядного сдвига и его направление). Шифруемые данные хранить в программе в виде строки (можно сохранять в файле и читать из файла).

Мой вариант: сдвиг на 2 бита, размер обрабатываемого блока 1 байт.

Очень прошу помочь, не получается нормально сделать... Шифрует, а расшифровывать не хочет



Приложение:
#include <iostream>
#include "stdafx.h"
#include <locale.h>
#include <string.h>
#include<conio.h>
#include<stdio.h>
#include <stdlib.h>

const int MAX=1000; // MAX - Максимальное количество символов
// PrintLine - Функция печати строки длиной в 'b' символов
void PrintLine(char *line, int b)
{
for (int i=0; i<b; i++)
printf("%c", line[i]);
printf("\n");
}
//Функция для шифрования данных
void shifrovanie(char *first, char *late, int y, int n)
{
srand(n); // Инициализация секретного ключа 'n'
unsigned short Gamma; // Гамма
int SizeLateBlock; // Размер последнего блока
unsigned short Block1, Block2; // Блоки, которые будут использованы в качестве буфера обмена
int x; // x - Количество блоков памяти

x=y/1; // Количество блоков памяти по 1 байт

if (x*1!=y) // Проверка количества блоков по 1 байт
{
SizeLateBlock=1; // Если есть лишний блок, то его размер - 1 байт
x++; // Увеличиваем кол-во итераций цикла (для обработки последнего блока размером 1 байт)
}
else SizeLateBlock=1;

for (int i=1; i<=x; i++)
{
Gamma=rand(); // Генерируем гамму с помощью генератора псевдослучайных чисел
unsigned short Mask=0x8000; // Маска для сохранения одного старшего бита

if (i!=x) // Проверка, является ли обрабатываемый блок последним
{
memcpy(&Block1, first+(i-1), 1); // Копирование блока исходных данных размером 1 байт из исходной строки в буферный блок данных
Block2=Block1^Gamma; // Наложение гаммы на буферный блок данных, используя операцию поразрядного исключающего "ИЛИ"
Block1=Block2 & Mask; // Наложение маски, чтобы выделить отдельные биты и сохранить их в отдельном буферном блоке
Block1>>=14; // Выполнениеоперации поразрядного сдвига на 14 бит вправо
Block2<<=2; // Выполнение операции поразрядного сдвига на 2 бита влево
Block2|=Block1; // Использование операции поразрядного "ИЛИ", получение поразрядно сдвинутого на 2 бита влево исходного блока с наложенной гаммой
memcpy(late+(i-1), &Block2, 1); // Копирование результата из буфера в блок с зашифрованными данными
}
else // Если блок последний
{
if (SizeLateBlock==1)
Mask>>=4; // Сдвиг маски, если размер последнего блока данных - 1 байт
Block1=0; // Далее те же операции, но с учетом того, что идет обработка одного или двух байтов
memcpy(&Block1, first+(i-1), SizeLateBlock);
Block2=Block1^Gamma;
Block1=Block2 & Mask;
Block1>>=(14-4*(1-SizeLateBlock)); // Учитывание размера последнего блока
Block2<<=2;
Block2 = Block1;
memcpy(late+(i-1), &Block2, SizeLateBlock);
}

}
}
//Функция для расшифровывания данных
using namespace std;
void deshifrovanie(char *late, char *first, int y, int n)
{
srand(n); // Инициализация секретного ключа
unsigned short Gamma; // Гамма
int x; // x - Количество блоков памяти
int SizeLateBlock; // Размер последнего блока
unsigned short Block1, Block2; // Блоки, которые будут использованы в качестве буфера обмена

x=y/1; // Количество блоков памяти по 1 байт

if (x*1!=y) // Проверка количества блоков по 1 байт
{
SizeLateBlock=1; // Если есть лишний блок, то его размер - 1 байт
x++; // Увеличивание кол-ва итераций цикла(для обработки последнего блока размером 1 байт)
}
else SizeLateBlock=1;

for (int i=1; i<=x; i++)
{
Gamma=rand(); // Генерация гаммы с помощью генератора псевдослучайных чисел
unsigned short Mask=0x0001; // Маска для сохранения двух младших битов
if (i!=x) // Проверка, является ли обрабатываемый блок последним
{
memcpy(&Block1, late+(i-1), 1); // Копирование блока зашифрованных данных размером 1 байт из исходной строки в буферный блок данных
Block2=Block1 & Mask; // Наложение маски, чтобы выделить отдельные биты и сохранить их в отдельном буферном блоке
Block2<<=14; // Выполнение операции поразрядного сдвига на 14 бит влево
Block1>>=2; // Выполнение операции поразрядного сдвига на 2 бита вправо
Block1|=Block2; // Использование операции поразрядного "ИЛИ", получение поразрядно сдвинутого на 1 бит вправо исходного блока зашифрованных данных
Block2=Block1^Gamma; // Наложение гаммы, используя операцию поразрядного исключающего "ИЛИ", и получаем блок исходных данных
memcpy(first+(i-1), &Block2, 1); // Копирование результата из буфера в блок с расшифрованными данными
}
else
{
Block1=0; // Далее те же операции, что и при выполнении условия, с учетом того, что идет обработка одного или двух байтов
memcpy(&Block1, late+(i-1), SizeLateBlock);
Block2=Block1 & Mask;
Block2<<=(14-4*(1-SizeLateBlock)); // Учитываем размер последнего блока
Block1>>=2;
Block1|=Block2;
Block2=Block1^Gamma;
memcpy(first+(i-1), &Block2, SizeLateBlock);
}

}
}
//Главная функция
int main()
{
setlocale(LC_ALL, "rus");
int Key; // Key - Секретный ключ
char Original[MAX], Encrypt[MAX], Decrypt[MAX]; // Original - Исходные, Encrypt - Зашифрованные, Decrypt - Расшифрованные
int a;
printf("Введите данные, которые вы хотите зашифровать: ");
gets(Original); // Ввод исходных данных
a=strlen(Original); // Длина строки
printf("Введите ключ: ");
scanf("%d", &Key); // Ввод секретного ключа
shifrovanie(Original, Encrypt, a, Key); // Шифрование исходных данных
printf("\nЗашифрованные данные: ");
PrintLine(Encrypt, a); // Вывод зашифрованных данных на экран
printf("\nВведите ключ: ");
scanf("%d", &Key); // Ввод секретного ключа
srand(Key);
deshifrovanie(Encrypt, Decrypt, a, Key); // Расшифровывание зашифрованных данных
printf("\nРасшифрованные данные: ");
PrintLine(Decrypt,a); //Вывод расшифрованных данных
getch();
return 0;
}

Обсуждение

давно
Посетитель
7438
7205
22.11.2016, 12:59
общий
это ответ
Здравствуйте, tatjanamaslova!
Шифрование-то работало, только получало данные, которые, в принципе, не поддавались расшифровке
Вот смотрите, читаете байт в буфер из двух байт. Делаете манипуляции с битами, и сохраняете ТОЛЬКО младший байт.
Старший байт безвозвратно теряется. Затем пытаетесь из одного младшего байта получить исходный! Не получится!
Надо было тогда сохранять два байта. Т.е. зашифрованные данные должны были быть в 2 раза длиннее!
Чтобы длина не менялась, то надо работать с байтом, а не с двумя байтами. Соответственно, и гамма должна быть однобайтной.
К слову, были и другие ошибки: 1) маска, если уж ее использовать, должна была бы быть 0xc000, нас же интересуют 2 старших бита, а не 1.
Впрочем, эта маска не нужна вообще! После сдвига, два старших бита окажутся в младших и так!
2) Зачем анализ на последний блок при работе с одним байтом
В общем, скопировали с исходника, где была работа с двумя байтами, и полностью не исправили...
[code h=200]//Функция для шифрования данных
void shifrovanie(char *first, char *late, int y, int n)
{
srand(n); // Инициализация секретного ключа 'n'
unsigned short Gamma; // Гамма
unsigned char gamma1;
unsigned char ch1, ch2;

for (int i=1; i<=y; i++)
{
Gamma=rand(); // Генерируем гамму с помощью генератора псевдослучайных чисел
gamma1 = (Gamma>>8) ^ (Gamma&0xff); //получение однобайтной гаммы!

memcpy(&ch1, first+(i-1), 1); // Копирование блока исходных данных размером 1 байт из исходной строки в буферный блок данных
ch2=ch1^gamma1; // Наложение гаммы на буферный блок данных, используя операцию поразрядного исключающего "ИЛИ"
ch1=ch2;
ch1>>=6; // Выполнение операции поразрядного сдвига на 6 бит вправо
ch2<<=2; // Выполнение операции поразрядного сдвига на 2 бита влево
ch2|=ch1; // Использование операции поразрядного "ИЛИ", получение поразрядно сдвинутого на 2 бита влево исходного блока с наложенной гаммой
memcpy(late+(i-1), &ch2, 1); // Копирование результата из буфера в блок с зашифрованными данными
}
}
//Функция для расшифровывания данных
void deshifrovanie(char *late, char *first, int y, int n)
{
srand(n); // Инициализация секретного ключа
unsigned short Gamma; // Гамма
unsigned char gamma1;
unsigned char ch1, ch2;

for (int i=1; i<=y; i++)
{
Gamma=rand(); // Генерация гаммы с помощью генератора псевдослучайных чисел
gamma1 = (Gamma>>8) ^ (Gamma&0xff); //получение однобайтной гаммы!

memcpy(&ch1, late+(i-1), 1); // Копирование блока исходных данных размером 1 байт из исходной строки в буферный блок данных
ch2 = ch1;
ch1<<=6; // Выполнение операции поразрядного сдвига на 6 бит влево
ch2>>=2; // Выполнение операции поразрядного сдвига на 2 бита вправо
ch2|=ch1; // Использование операции поразрядного "ИЛИ"
ch2=ch2^gamma1; // Наложение гаммы на буферный блок данных, используя операцию поразрядного исключающего "ИЛИ"
memcpy(first+(i-1), &ch2, 1); // Копирование результата из буфера в блок с расшифрованными данными
}
}
[/code]
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Посетитель
7438
7205
22.11.2016, 15:28
общий
Адресаты:
В общем-то, можно было оставить двубайтные буфера, и гамму двубайтную, но двигать надо было биты только одного младшего байта! Можете так сделать...
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Форма ответа