Автор работы: Пользователь скрыл имя, 20 Апреля 2015 в 19:20, курсовая работа
Описание работы
Предмет исследования – криптографический алгоритм Blowfish. Цель работы – разработка программного продукта обеспечивающего шифрование/расшифрование данных по алгоритму Blowfish. Алгоритм Blowfish — блочный шифр, основанный на сети Файстеля. Алгоритм прост в реализации, он является стойким ко всем, известным на сегодняшний день, методам криптоанализа.
Содержание работы
Введение 4 1 Понятие шифрования данных 7 2 Описание алгоритма blowfish 11 2.1 Структура алгоритма 11 2.2 Процедура расширения ключа 13 2.3 Достоинства и недостатки алгоритма 14 3 Практическая реализация алгоритма blowfish 16 4 Описани работы с программным продуктом 21 4.1 Минимальные требования для работы программного продукта 21 4.2 Шифрование данных 21 4.3 Расшифрование данных 23 4.4 Генерация пароля 25 Заключение 26 Список использованных источников 27 Приложение 1. Содержимое заголовочного файла 28 Приложение 2. Содержимое основного файла 29
F(x) = ( (S1(x1) + S2(x2) mod 232) (+) S3(x3) ) +
S4(x4) mod 232,
где x1...x4 - 8-битные фрагменты
входного значения x.
Рисунок 2. – Функция F алгоритма
Blowfish
Расшифрование выполняется
аналогично шифрованию, но ключи K1...K18
используются в обратном порядке [7].
2.2 Процедура расширения
ключа
Задача процедуры расширения
ключа состоит в вычислении на основе
ключа шифрования значений ключей раунда
K1...K18 и таблиц замен S1...S4. Для этого используется
весьма сложная процедура расширения
ключа, состоящая из следующих шагов:
Исходные значения ключей раунда
и таблиц замен инициализируются фиксированной
псевдослучайной строкой, в качестве которой
используется шестнадцатеричная запись
дробной части числа p. Значения таблиц замен инициализируются аналогично инициализации
ключей раундов, которые заполняются последующими знаками дробной части числа p.
Операцией XOR на K1 накладываются
первые 32 бита ключа шифрования, на K2 -
следующие 32 бита и т. д. - до K18. Если ключ
шифрования короче, чем необходимо для
наложения на K1...K18, то он накладывается
циклически.
С использованием полученных
ключей раунда и таблиц замен выполняется
шифрование алгоритмом Blowfish блока данных, состоящего из 64 нулевых бит. Результат становится новым значением ключей K1 и K2.
Результат предыдущего этапа
снова шифруется алгоритмом Blowfish (причем
уже с измененными значениями ключей K1
и K2), в результате получаются новые значения
ключей K3 и K4.
Шифрование выполняется до
тех пор, пока новыми значениями не будут
заполнены все ключи раунда и таблицы
замен [7].
2.3 Достоинства и
недостатки алгоритма
В своей книге "Прикладная
криптография" Брюс Шнайер отметил
следующие ограничения алгоритма Blowfish.
Во-первых, "...алгоритм Blowfish не годится
для применения в случаях, где требуется
частая смена ключей". Процедура расширения
ключа ресурсоемка, поэтому одно из достоинств
алгоритма Blowfish - высокая скорость шифрования
- проявляется только в тех случаях, если
на одном ключе шифруется достаточно большой
объем информации. И наоборот, если менять
ключ после каждого из шифруемых блоков,
скорость алгоритма становится катастрофически
низкой именно из-за необходимости каждый
раз выполнять расширение ключа. Сам Шнайер
рекомендует в приложениях, где критична
скорость, хранить уже развернутый ключ
(т. е. значения K1 ... K18 и S1...S4) и загружать
его целиком вместо того, чтобы выполнять
расширение исходного ключа.
Далее, "...большие требования
к памяти не позволяют использовать этот
алгоритм в смарт-картах". Стоит сказать,
что принципиальная возможность реализации
алгоритма в смарт-картах была одним из
важных условий при выборе нового стандарта
шифрования США на конкурсе AES, т.е. данный
недостаток алгоритма Blowfish можно считать
серьезным [7].
Кроме того, стоит отметить
и менее серьезные недостатки алгоритма:
невозможность расширения ключа параллельно
процессу шифрования и небольшой по современным
меркам размер блока шифруемых данных.
Алгоритм Blowfish имеет и достаточно
важные преимущества, в частности:
высокая скорость шифрования
на развернутом ключе (как уже упоминалось
выше);
простота алгоритма, снижающая
вероятность ошибок при его реализации;
отсутствие успешных
атак на полнораундовую версию алгоритма [8].
Стоит, однако, сказать, что
известный эксперт Серж Воденэ (Serge Vaudenay)
обнаружил, что методом дифференциального
криптоанализа r-раундового алгоритма
Blowfish с известными таблицами замен можно
вычислить значения K1...K18 при наличии 28r+1 выбранных
открытых текстов. Это неактуально для
полнораундовой версии алгоритма (и тем
более для описанной выше полноценной
версии с вычисляемыми таблицами замен),
но при использовании слабого ключа (а
Воденэ обнаружил также у алгоритма Blowfish
наличие слабых ключей, которые приводят
к генерации слабых таблиц замен) выбранных
открытых текстов требуется существенно
меньше: 24r+1. Вероятность,
что произвольный ключ окажется слабым,
составляет 2-14. Данная
атака некритична, поскольку для полноценной
версии алгоритма слабые ключи не страшны
[3].
Явные достоинства и отсутствие
критичных недостатков предопределили
широкое использование алгоритма Blowfish.
ПРАКТИЧЕСКАЯ РЕАЛИЗАЦИЯ АЛГОРИТМА BLOWFISH
Первым шагом в реализации алгоритма
будет написание класса с именем TBlofish.
Данный класс будет содержать:
поля, в которых будет храниться
таблицы замен и таблица ключей;
методы, которые будут шифровать и расшифровать блоки данных по 64 бита;
метод, который производит инициализацию
всех наших таблиц;
вспомогательные методы;
а также конструктор и деструктор.
Вспомогательные методы класса
и поля помещаем в директиву private. А метод,
который шифруют, расшифровывает и производит
инициализацию таблиц замен и таблицу
ключей помещаем в директиву public. В директиву
public также помещаем конструктор и деструктор,
которые используются для создания и удаления
объектов этого класса.
Данный класс имеет следующий
вид:
class TBlowfish{
private:
unsigned int S1[256];
unsigned int S2[256];
unsigned int S3[256];
unsigned int S4[256];
unsigned int key[18];
unsigned int F(unsigned int);
void final(unsigned int*, int);
public:
unsigned long long Encrypt(unsigned long long);
unsigned long long Decrypt(unsigned long long);
void initialization(unsigned int*);
TBlowfish();
~TBlowfish();
}
После написания класса необходимо
описать методы этого класса. Это будет
вторым шагом в реализации алгоритма.
Описание методов класса начинаем
с конструктора, потому что именно он будет
вызваться автоматически каждый
раз, когда происходит создание объекта.
Обычное назначение конструктора заключается
в инициализации элементов данных объекта.
Конструктор представляет собой метод
класса, который имеет такое же имя, как
и класс. Конструктор нашего класса
выглядит следующим образом:
TBlowfish::TBlowfish(){
copy(K1, K1+256, S1);
copy(K2, K2+256, S2);
copy(K3, K3+256, S3);
copy(K4, K4+256, S4);
copy(keys, keys+18, key);
}
В конструкторе встречается
функция copy, это функция, которая копирует
содержимое из одного массива в другой.
В качестве первого параметра функции
необходимо указать место в массиве, с
которого производится копирование, в
качестве второго параметра указывается
место в массиве, до которого производится
копирование и в качестве третьего параметра
указывается массив, в который производится
копирование.
Деструктор представляет собой
функцию, которую C++ автоматически запускает,
когда он или программа уничтожает объект.
Деструктор имеет такое же имя, как и класс
объекта; однако имя деструктора предваряется
символом тильды (~). Деструктор нашего
класса имеет следующий вид:
TBlowfish::~TBlowfish(){}
Теперь перейдем к описанию
методов, кторые будит использоваться
для шифрования/расшифрования.
Опишем метод, который будет
производить шифрование данных. Данный
метод имеет следующий вид:
unsigned long long TBlowfish::Encrypt(unsigned long long block){
unsigned int block_p=0,block_l=0,temp=0;
block_p=block & mask;
block_l=(block >> 32) & mask;
for (int i=0;i<16;i++){
block_l=block_l^key[i];
block_p=block_p^F(block_l);
if (i != 15){
temp=block_p;
block_p=block_l;
block_l=temp;
}
}
block_l=block_l^key[17];
block_p=block_p^key[16];
unsigned long long result=block_l;
result=(result << 32) | block_p;
return result;
}
Данный метод на вход принимает
64 битный блок данных, которые записывается
в переменную block. После того как была вызвана
функция, в соответствии с описанным во
2 главе алгоритмом, входной 64 битный блок
делится на два блока по 32 бита. Правые
32 бита записывается в переменную block_p,
а второй 32 битный блок данных записывается
в переменную block_l. Для определения первых
и вторых 32 бит используется наложение
маски на 64 битный блок. В качестве маски
используется переменная mask, она инициализирована
в заголовочном файле (см. приложение 2).
Затем в цикле от 0 до 16 на второй 32 битный
блок накладывается i-ый ключ, после чего
полученный 32 битный блик подается на
вход функции F, которая будет описана
нами далее. После выполнения всех 16 раундов
происходит наложение 17-го подключа на
левый блок и 18-го подключа на правый блок.
Затем эти блоки меняются мести и объединяются
в один 64 битный блок данных. Полученный
64 битный блок данных и будет результатом
шифрования.
Опишем метод F, который был
использован нами в функции шифровании.
Этот метод выглядит следующим образом:
unsigned int TBlowfish::F(unsigned int sub_block){
На вход данный метод принимает
32 битный блок данных. После того как метод
был вызван входной 32 битный блок делиться
на четыре 8-ми битные блоки. Для определения
8-ми битного блока используется наложение
маски на число. После того, как были определены
все 4 блока, они подвергаются процедуре
замены в соответствии с таблицами замен.
Каждый блок подвергается замене по соответствующей
таблице замены. После замены 8-ми битные
блоки расширяются до 32 бит. После чего
происходит сложение первого и второго
блока по модулю 232, а затем
полученный результат складывается по
модулю 2 с третьим блоком. Полученный
результат на предыдущем шаге складывается
по модулю 232 с последними
32 битами. Это и будет результатом выполнения
данной функции.
Рассмотрим реализацию метода,
который производит расшифрование данных.
Его код выглядит следующим образом:
unsigned long long TBlowfish::Decrypt(unsigned long long block){
unsigned int block_p=0,block_l=0,temp=0;
block_p=block & mask;
block_l=(block >> 32) & mask;
for (int i=17;i>1;i--){
block_l=block_l^key[i];
block_p=block_p^F(block_l);
temp=block_p;
block_p=block_l;
block_l=temp;
}
block_p=block_p^key[0];
block_l=block_l^key[1];
temp=block_p;
block_p=block_l;
block_l=temp;
unsigned long long result=block_l;
result=(result << 32) | block_p;
return result;
}
Данный метод аналогичен работе
методу для шифрования данных, отличие
заключается в порядке использования
ключей шифрования. В данном методе ключи
используются в обратном порядке.
Опишем метод initialization. Данный
метод на вход принимает ключ и производит
инициализацию всех таблиц (таблиц замен
и таблицу ключей шифрования). Его программный
код выглядит следующим образом:
Как уже говорилось выше, функция
на вход принимает ключ шифрования, а точнее
указатель на массив, в котором хранится
ключ для шифрования. Данный метод накладывает
на таблицу ключей ключ, который используется
для шифрования, а так же в этом методе
происходит шифрование таблиц замен и
таблицу с ключами шифрования.
В выше указанном методе используется
вспомогательный метод final. Программный
код которого выглядит следующим образом:
void TBlowfish::final(unsigned int* mass, int len){
unsigned long long bl=0x0;
for (int i=0; i<len;i+=2){
bl=Encrypt(bl);
mass[i]=bl & mask;
mass[i+1]=(bl >> 32) & mask;
}
}
Данный метод на вход принимает
указатель на массив и количество элементов
в этом массиве. Он написан для того, что
бы упростить программный код программы.
И выполняет шифрование массива, который
подается на вход этого метода.
ОПИСАНИ РАБОТЫ С ПРОГРАММНЫМ ПРОДУКТОМ
Минимальные требования
для работы программного продукта
Для нормальной работы программного
продукта необходимо:
Операционная система — Windows
2000 / XP / Vista / Seven;
15 Мб оперативной памяти;
Наличие 1,27 Мб свободного места
на жестком диске;
Платформа – x86.
Шифрование данных
Для того, что бы зашифровать
данные при помощи этой программой необходимо
выполнить следующие действия:
Из предложенных действий выбрать
«Шифровать»;
Необходимо выбрать файл, который
Вы хотите зашифровать. Для этого нажмите
на кнопку «Выбрать файл» (см. рис. 3);
Рисунок 3. – Главное окно программы
После этого появится диалоговое
окно, в котором Вы выбираете файл для шифрования (см. рис. 4);
Рисунок 4. – Диалоговое окно
выбора файла для шифрования
Указать путь, по которому будет
сохранен зашифрованный файл. Путь можно прописать
самому или использовать диалоговое окно.
Для того, что бы вызвать диалоговое окно
необходимо нажать на кнопку «Изменить
путь» (см. рис. 5);
Рисунок 5. – Главное окно программы
Произвести ввод пароль и повторить правильность его
ввода;
Нажать на кнопку «Выполнить»
(см. рис. 6);
Рисунок 6. – Главное окно программы
Примечание: в программе предусмотрена
функция удаление исходного файла после
шифрования, для этого нужно установить
флаг у свойства «Удаление исходного файла».