Защита информации от несанкционированного доступа
Защита информации от несанкционированного доступа
2 МИНИСТЕРСТВО ОБРАЗОВАНИЯ И НАУКИ УКРАИНЫ
ПОЯСНИТЕЛЬНАЯ ЗАПИСКА к курсовому проекту на тему: "Защита информации от несанкционированного доступа" по курсу "Кодирование и защита информации" 2004 АННОТАЦИЯ Пояснительная записка содержит описание разработанной программы и руководство по ее использованию. Также в ней приводится описание используемых методов шифрования информации. СОДЕРЖАНИЕ - АННОТАЦИЯ
- ВВЕДЕНИЕ
- 1 Постановка задачи
- 2 Основные понятия
- 3 Выбор методов шифрования
- 4 Программная реализация
- Общее описание
- Дополнительные модули
- 5 Руководство пользователя
- ЗАКЛЮЧЕНИЕ
- БИБЛИОГРАФИЧЕСКИЙ СПИСОК
- ПРИЛОЖЕНИЕ А
- Введение
В настоящее время большое внимание уделяется информации, недаром наш век называют «информационным». Во время того, как люди познают технологии хранения и передачи информации, встает вопрос о ее защите от несанкционированного доступа. Для решения этой проблемы было разработано большое количество разнообразных методов кодирования информации, которые могут быть реализованы программно. Данная разработка представляет собой программный модуль, обеспечивающий шифрование и расшифровывание информационных блоков. 1. Постановка задачи Необходимо разработать программу для шифрования и расшифровывания файлов на основе настроек пользователя. Для шифрования использовать ГОСТ 28147-89. Разработать удобный интерфейс общения с пользователем. Поставить программу на платформу Windows, что обеспечит ее расширение, дополнение и удобство использования. 2. Основные понятия В данной работе будет рассматриваться защита информации, хранящейся в электронном виде, от несанкционированного доступа. Для обеспечения секретности информации используются следующие методы: - хранение на съемном носителе; - ограничение доступа к системе; - хранение в зашифрованном виде; Комбинированием этих средств защиты можно добиться относительно хорошей защищенности информации. Невозможно абсолютно защитить информацию от несанкционированного доступа (взлома). Любой из этих способов поддается взлому в некоторой степени. Вопрос в том, будет ли выгодно взламывать или нет. Если затраты ресурсов на защиту (стоимость защиты) больше чем затраты на взлом, то система защищена плохо. Данная разработка является криптографической частью системы защиты - она зашифровывает и расшифровывает информацию, поэтому ниже будут приведены только основные понятия криптографии. Шифр - последовательность операций, проводимых над открытыми (закрытыми) данными и ключом с целью получения закрытой (открытой) последовательности. Ключ - конкретное для каждого нового кода значение каких-нибудь характеристик алгоритма криптографической защиты. Гамма шифра - это некоторая псевдослучайная последовательность заданной длины, используемая для шифрования. Гаммирование - процес наложения гаммы шифра на открытые данные. Зашифровывание - процесс преобразования открытых данных в закрытые с помощью шифра и ключа. Расшифровывание - процедура преобразования закрытых данных в открытые с помощью шифра и ключа. Шифрование - зашифровывание и (или) расшифровывание. Дешифрование - совокупность действий по преобразованию закрытых данных в открытые без знания ключа и (или) алгоритма зашифровывания. Имитозащита - защита от ложной информации. Осуществляется по собственным алгоритмам, с помощью выработки имитовставки. Имитовставка - последовательность данных определенной длины, полученных специальными методами гаммирования из открытых исходных данных. Содержимое имитовставки является эталоном для проверки всей остальной информации. 3. Выбор методов шифрования Для шифрования информации в программу встроены следующие алгоритмы: - ГОСТ 28147-89 - стандарт шифрования Российской Федерации. В программе используется два режима кодирования - режим простой замены и режим гаммирования. Данные кодируются по 64 бита (8 байт) с помощью 256-битного (32-байтного) ключа. - Два простых метода, вложенных как пример построения модулей для программы. Кодирование по 64 бит, ключ - 64 бит. Программа может быть дополнена алгоритмами кодирования, т.е. рекомпилирована с дополнительными модулями. В дальнейших версиях предполагается создание модульных расширений (plug-in) для программы, которые будут содержать дополнительные алгоритмы криптографических преобразований. Рассмотрим подробнее алгоритм криптографического преобразования ГОСТ 28147-89. Ключ состоит из восьми 32-битных элементов, рассматриваемых как беззнаковые целые числа. Таким образом, ключ составляет 256 бит или 32 байта. При шифровании используется таблица замен, являющейся матрицей 8х16, содержащей 4-битовые элементы (числа от 0 до 15). Основной шаг криптопреобразования - оператор, определяющий преобразование 64-битового блока. Дополнительным параметром этого оператора является 32-битный блок, в качестве которого используется какой - либо элемент ключа. Алгоритм основного шага криптопреобразования Рисунок 3.1 Схема основного шага криптопреобразования алгоритма ГОСТ 28147-89. Определяет исходные данные для основного шага криптопреобразования: N -преобразуемый 64-битовый блок данных, в ходе выполнения шага его младшая (N1) и старшая (N2) части обрабатываются как отдельные 32-битовые целые числа без знака. Таким образом, можно записать N=(N1,N2). X - 32-битовый элемент ключа; Сложение с ключом. Младшая половина преобразуемого блока складывается по модулю 232 с используемым на шаге элементом ключа, результат передается на следующий шаг; Поблочная замена. 32-битовое значение, полученное на предыдущем шаге, интерпретируется как массив из восьми 4-битовых блоков кода: S=(S0,S1,S2,S3,S4,S5,S6,S7). Далее значение каждого из восьми блоков заменяется на новое, которое выбирается по таблице замен следующим образом: значение блока Si заменяется на Si-тый по порядку элемент (нумерация с нуля) i-того узла замен (т.е. i-той строки таблицы замен, нумерация также с нуля). Другими словами, в качестве замены для значения блока выбирается элемент из таблицы замен с номером строки, равным номеру заменяемого блока, и номером столбца, равным значению заменяемого блока как 4-битового целого неотрицательного числа. Циклический сдвиг на 11 бит влево. Результат предыдущего шага сдвигается циклически на 11 бит в сторону старших разрядов и передается на следующий шаг. На схеме алгоритма символом ?11 обозначена функция циклического сдвига своего аргумента на 11 бит в сторону старших разрядов. Побитовое сложение: значение, полученное на шаге 3, побитно складывается по модулю 2 со старшей половиной преобразуемого блока. Сдвиг по цепочке: младшая часть преобразуемого блока сдвигается на место старшей, а на ее место помещается результат выполнения предыдущего шага. Полученное значение преобразуемого блока возвращается как результат выполнения алгоритма основного шага криптопреобразования. Базовые циклы: - цикл выработки имитовставки (0123456701234567) Для каждого элемента данных выполняется основной шаг криптографического преобразования с элементами ключа, порядок Базовые циклы построены из основных шагов криптографического преобразования. Существует всего три базовых цикла, различающиеся порядком следования ключевых элементов: - цикл зашифрования (01234567012345670123456776543210) - цикл расшифрования (01234567765432107654321076543210) следования которых приведен выше. Для циклов шифрования левая и правая половины блока меняются местами, для цикла выработки имитовставки - нет. Предусматривается три режима шифрования данных: простая замена, гаммирование, гаммирование с обратной связью и один дополнительный редим формирования имитовставки. Рис. 4. Алгоритм зашифрования (расшифрования) данных в режиме гаммирования. Режим простой замены - наиболее простой. Блоки данных по 64 бит проходят базовый цикл зашифрования (расшифрования). Результат - зашифрованная (расшифрованная информация). При таком режиме блоки независимы. Режим гаммирования - чтобы блоки информации были зависимы друг от друга используется рекуррентный генератор последовательности чисел, который инициализируется синхропосылкой, прошедшей цикл зашифрования. Схема алгоритма шифрования в режиме гаммирования приведена на рисунке 3.2, ниже изложены пояснения к схеме: Определяет исходные данные для основного шага криптопреобразования: Tо(ш) - массив открытых (зашифрованных) данных произвольного размера, подвергаемый процедуре зашифрования (расшифрования), по ходу процедуры массив подвергается преобразованию порциями по 64 бита; S - синхропосылка, 64-битный элемент данных, необходимый для инициализации генератора гаммы; Начальное преобразование синхропосылки, выполняемое для ее «рандомизации», то есть для устранения статистических закономерностей, присутствующих в ней, результат используется как начальное заполнение РГПЧ; Один шаг работы РГПЧ, реализующий его рекуррентный алгоритм. В ходе данного шага старшая (S1) и младшая (S0) части последовательности данных вырабатываются независимо друг от друга; Гаммирование. Очередной 64-битный элемент, выработанный РГПЧ, подвергается процедуре зашифрования по циклу 32-З, результат используется как элемент гаммы для зашифрования (расшифрования) очередного блока открытых (зашифрованных) данных того же размера. Результат работы алгоритма - зашифрованный (расшифрованный) массив данных. 4. Программная реализация 4.1 Общее описание Для разработки программы были выбраны языки программирования Delphi 5.0 (Object Pascal) - разработка удобного интерфейса и встроенный ассемблер - для написания, собственно, алгоритмов шифрования. Проект состоит из девяти модулей: GOST, K1, K2 - реализация алгоритмов ГОСТ 28147-89 и тестовых методов шифрования. CodingTools, CodingUnit - модули, реализующие вспомогательные алгоритмы и типы данных. OptionsUnit, ProgressUnit, TestUnit - модули, описывающие интерфейс с пользователем. Hazard - основной модуль программы. Создает окна и запускает программу. Программа использует три формы (окна), созданные с помощью среды Delphi. Основная форма TestForm, содержит список файлов и кнопки запуска процесса шифрования, выхода, вызова окна настроек, добавления и очистки списка (рисунок 4.1). Окно настроек содержит списки поддерживаемых и применяемых методов шифрования, поле описания метода и поле ввода ключа (рисунок 4.2). Третье окно - ProgressForm появляется при запуске процесса кодирования и состоит из двух надписей и двух индикаторов. Рисунок 4.1 - Интерфейс программы 4.2 Дополнительные модули Модуль CodingTools содержит описание типов для 64,48 и 32-разрядных чисел и процедуры их обработки: сложение по модулю 2, &, |, кодирование по таблице, разложение на числа меньшей разрядности. Также он содержит описания параметров кодирования и тип-шаблон функции шифрования. Модуль CodingUnit содержит список встроенных алгоритмов и общие функции: обработка командной строки, подбор функции шифрования, шифрование файла, процедуры поиска функций по имени или индексу, поиск ошибок и оповещение. Модули методов экспортируют каждый по две процедуры - шифрование и дешифрацию блоков по 64К. 5. Руководство пользователя Программа работает под управлением ОС Windows 95/98/ME и требует правильной инсталляции. После инсталляции программу можно запустить из меню «Пуск» либо из командной строки эмуляции MS-DOS. Командная строка имеет следующий вид: Hazard.exe [/D] [путь к файлу [путь к файлу […]]] /D - дешифрование Чтобы запустить программу в режиме шифрования или дешифрования из графической оболочки Windows нужно воспользоваться соответствующими ярлыками из меню «Программы». Чтобы добавить файлы в список шифрования/дешифрования можно воспользоваться соответствующей кнопкой на главной панели программы, либо «перетащить» их из окна проводника Windows. Чтобы выбрать алгоритм шифрования нужно нажать кнопку «Настройки». Появится окно со списками поддерживаемых и применяющихся методов и полем ввода ключа. После выбора методов программа рассчитает окончательный ключ, который может быть использован для расшифровывания файлов. Можно не запоминать окончательный ключ, в таком случае необходимо запомнить ключи каждого из выбранных методов и при расшифровывании сделать соответствующие настройки. При нажатии на кнопку запуска появится индикатор прогресса, который отобразит состояние процесса шифрования текущего файла и процесса шифрования в общем. При дешифровании следует учитывать, что программа расшифровывает файлы только с расширением .crf. Заключение В результате курсовой работы была разработана первая версия программы, осуществляющей шифрование информации. В дальнейшем предполагается разработка и усовершенствование комплекса программ, обеспечивающих защиту информации от несанкционированного доступа. В процессе разработки были закреплены навыки шифрования информации по ГОСТ 28147-89 и программирования на ассемблере. Библиографический список 1. Конспект лекций по курсу «Кодирование и защита информации» 2. Андрей Винокуров. «Алгоритм шифрования ГОСТ 28147-89, его использование и реализация для компьютеров платформы Intel x86» 3. Михаил Гук. «Процессоры Pentium II, Pentium Pro и просто Pentium», Санкт-Петербург «Питер», 1999 г. Приложение А program Hazard; uses Windows, Messages, SysUtils, Forms, TestUnit in 'TestUnit.pas' {MainForm}, CodingUnit in 'CodingUnit.pas', OptionsUnit in 'OptionsUnit.pas' {OptionsForm}, K1 in 'K1.pas', K2 in 'K2.pas', K3 in 'K3.pas', ProgressUnit in 'ProgressUnit.pas' {ProgressForm}, GOST in 'GOST.pas'; {$R *.RES} {$R Laynik.res} function AlreadyRunning: boolean; begin Result:=False; if FindWindow('TMainForm','Кодирование')<>0 then Result:=True; end; begin Decode:=false; If not AlreadyRunning then begin Application.Initialize; Application.Title := '[LG] Hazard'; Application.CreateForm(TMainForm, MainForm); Application.CreateForm(TOptionsForm, OptionsForm); Application.CreateForm(TProgressForm, ProgressForm); MainForm.DoCommandLine(String(system.CmdLine)); Application.Run; end else begin MessageBox(0,'Приложение уже запущено','Ошибка',MB_ICONSTOP+MB_OK); end end. unit K1; interface uses CodingTools; function Coding_K1(Buf: Pointer; Size: LongWord; Param: TCodingParameters):Integer; function DeCoding_K1(Buf: Pointer; Size: LongWord; Param: TCodingParameters):Integer; implementation const FShTable: TConvertTable64 = (57,49,41,33,25,17, 9, 1,59,51, 43,35,27,19,11, 3,61,53,45,37, 29,21,13, 5,63,55,47,39,31,23, 15, 7,56,48,40,32,24,16, 8, 0, 58,50,42,34,26,18,10, 2,60,52, 44,36,28,20,12, 4,62,54,46,38, 30,22,14, 6); LShTable: TConvertTable64 = (39, 7,47,15,55,23,63,31,38,6, 46,14,54,22,62,30,37, 5,45,13, 53,21,61,29,36, 4,44,12,52,20, 60,28,35, 3,43,11,51,19,59,27, 34, 2,42,10,50,18,58,26,33, 1, 41, 9,49,17,57,25,32, 0,40, 8, 48,16,56,24); procedure K1Coding64bits(A: word64; var R: word64; K1:word64); begin convert(A,FShTable,R); asm push esi mov esi,DWORD[R] mov eax,DWORD[K1] xor [esi],eax add esi,4 mov eax,DWORD[K1+4] xor [esi],eax pop esi end; end; procedure K1DeCoding64bits(A: word64; var R: word64; K1:word64); begin asm mov eax,DWORD[K1] xor DWORD[A],eax mov eax,DWORD[K1+4] xor DWORD[A+4],eax end; convert(A,LShTable,R); end; function Coding_K1(Buf: Pointer; Size: LongWord; Param: TCodingParameters):Integer; var i,j,l:integer; a,r: ^word64; k: word64; begin for i:=0 to 7 do k.v8[i]:=BYTE(Param.Key[i]); convert(K,LshTable,K); l:=Size div 8; for i:=1 to Param.WayCount do begin for j:=0 to l-1 do begin a:=Pointer(LongWord(Buf)+j*8); r:=a; K1Coding64bits(A^,R^,K); end; end; result:=0; end; function DeCoding_K1(Buf: Pointer; Size: LongWord; Param: TCodingParameters):Integer; var i,j,l:integer; a,r:^word64; k: word64; begin for i:=0 to 7 do k.v8[i]:=BYTE(Param.Key[i]); convert(K,LshTable,K); l:=Size div 8; for i:=1 to Param.WayCount do begin for j:=0 to l-1 do begin a:=Pointer(LongWord(Buf)+j*8); r:=a; K1DeCoding64bits(A^,R^,K); end; end; result:=0; end; end. unit K2; interface uses CodingTools; function Coding_K2(Buf: Pointer; Size: LongWord; Param: TCodingParameters):Integer; function DeCoding_K2(Buf: Pointer; Size: LongWord; Param: TCodingParameters):Integer; implementation const FShTable: TConvertTable64 = (57,49,41,33,25,17, 9, 1,59,51, 43,35,27,19,11, 3,61,53,45,37, 29,21,13, 5,63,55,47,39,31,23, 15, 7,56,48,40,32,24,16, 8, 0, 58,50,42,34,26,18,10, 2,60,52, 44,36,28,20,12, 4,62,54,46,38, 30,22,14, 6); LShTable: TConvertTable64 = (39, 7,47,15,55,23,63,31,38,6, 46,14,54,22,62,30,37, 5,45,13, 53,21,61,29,36, 4,44,12,52,20, 60,28,35, 3,43,11,51,19,59,27, 34, 2,42,10,50,18,58,26,33, 1, 41, 9,49,17,57,25,32, 0,40, 8, 48,16,56,24); procedure K2Coding64bits(A: word64; var R: word64; B: byte); begin convert(A,FShTable,R); asm push esi mov esi,DWORD[R] mov cl,[b] ror dword[esi],cl add esi,4 mov cl,[b] ror dword[esi],cl pop esi end; end; procedure K2DeCoding64bits(A: word64; var R: word64; B: Byte); begin asm mov cl,[b] rol DWORD[A],cl mov cl,[b] rol DWORD[A+4],cl end; convert(A,LShTable,R); end; function Coding_K2(Buf: Pointer; Size: LongWord; Param: TCodingParameters):Integer; var i,j,l:integer; a,r: ^word64; k: word64; b: byte; begin b:=0; for i:=0 to 7 do k.v8[i]:=BYTE(Param.Key[i]); convert(K,LshTable,K); for i:=0 to 7 do b:=b xor K.v8[i]; l:=Size div 8; for i:=1 to Param.WayCount do begin for j:=0 to l-1 do begin a:=Pointer(LongWord(Buf)+j*8); r:=a; K2Coding64bits(A^,R^,B); end; end; result:=0; end; function DeCoding_K2(Buf: Pointer; Size: LongWord; Param: TCodingParameters):Integer; var i,j,l:integer; a,r:^word64; k: word64; b: byte; begin b:=0; for i:=0 to 7 do k.v8[i]:=BYTE(Param.Key[i]); convert(K,LshTable,K); for i:=0 to 7 do b:=b xor K.v8[i]; l:=Size div 8; for i:=1 to Param.WayCount do begin for j:=0 to l-1 do begin a:=Pointer(LongWord(Buf)+j*8); r:=a; K2DeCoding64bits(A^,R^,B); end; end; result:=0; end; end. unit K3; interface uses CodingTools; function Coding_K3(Buf: Pointer; Size: LongWord; Param: TCodingParameters):Integer; function DeCoding_K3(Buf: Pointer; Size: LongWord; Param: TCodingParameters):Integer; implementation uses SysUtils; const FShTable: TConvertTable64 = (57,49,41,33,25,17, 9, 1,59,51, 43,35,27,19,11, 3,61,53,45,37, 29,21,13, 5,63,55,47,39,31,23, 15, 7,56,48,40,32,24,16, 8, 0, 58,50,42,34,26,18,10, 2,60,52, 44,36,28,20,12, 4,62,54,46,38, 30,22,14, 6); LShTable: TConvertTable64 = (39, 7,47,15,55,23,63,31,38,6, 46,14,54,22,62,30,37, 5,45,13, 53,21,61,29,36, 4,44,12,52,20, 60,28,35, 3,43,11,51,19,59,27, 34, 2,42,10,50,18,58,26,33, 1, 41, 9,49,17,57,25,32, 0,40, 8, 48,16,56,24); procedure K3Coding64bits(A: word64; var R: word64; B: byte); begin convert(A,FShTable,R); asm push esi mov esi,DWORD[R] mov cl,[b] ror dword[esi],cl add esi,4 mov cl,[b] ror dword[esi],cl pop esi end; end; procedure K3DeCoding64bits(A: word64; var R: word64; B: Byte); begin asm mov cl,[b] rol DWORD[A],cl mov cl,[b] rol DWORD[A+4],cl end; convert(A,LShTable,R); end; function Coding_K3(Buf: Pointer; Size: LongWord; Param: TCodingParameters):Integer; var i,j:integer; a,r: ^word64; k: word64; b: byte; begin b:=0; k.v32[0]:=0; k.v32[1]:=0; for i:=0 to StrLen(Param.Key)-1 do k.v8[i]:=BYTE(Param.Key[i]); convert(K,LshTable,K); for i:=0 to 7 do b:=b xor K.v8[i]; for i:=1 to Param.WayCount do begin for j:=0 to Size-8 do begin a:=Pointer(LongWord(Buf)+j); r:=a; K3Coding64bits(A^,R^,B); end; end; result:=0; end; function DeCoding_K3(Buf: Pointer; Size: LongWord; Param: TCodingParameters):Integer; var i,j:integer; a,r:^word64; k: word64; b: byte; begin b:=0; k.v32[0]:=0; k.v32[1]:=0; for i:=0 to StrLen(Param.Key)-1 do k.v8[i]:=BYTE(Param.Key[i]); convert(K,LshTable,K); for i:=0 to 7 do b:=b xor K.v8[i]; for i:=1 to Param.WayCount do begin for j:=Size-8 downto 0 do begin a:=Pointer(LongWord(Buf)+j); r:=a; K3DeCoding64bits(A^,R^,B); end; end; result:=0; end; end. unit OptionsUnit; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Buttons, Spin, ExtCtrls; type TOptionsForm = class(TForm) UsedMethodsBox: TListBox; MethodsBox: TListBox; Label1: TLabel; Label2: TLabel; BitBtn1: TBitBtn; BitBtn2: TBitBtn; BitBtn3: TBitBtn; BitBtn4: TBitBtn; BitBtn5: TBitBtn; KeyEdit: TEdit; Label3: TLabel; DirectionGroup: TRadioGroup; WayCountEdit: TSpinEdit; Label4: TLabel; DescMemo: TMemo; procedure BitBtn5Click(Sender: TObject); procedure FormCreate(Sender: TObject); procedure BitBtn4Click(Sender: TObject); procedure BitBtn3Click(Sender: TObject); procedure BitBtn2Click(Sender: TObject); procedure BitBtn1Click(Sender: TObject); procedure UsedMethodsBoxClick(Sender: TObject); procedure DirectionGroupExit(Sender: TObject); procedure KeyEditExit(Sender: TObject); procedure WayCountEditExit(Sender: TObject); procedure EnableKeys(B: Boolean); procedure FormClose(Sender: TObject; var Action: TCloseAction); private { Private declarations } public { Public declarations } end; var OptionsForm: TOptionsForm; implementation {$R *.DFM} uses CodingUnit, TestUnit; procedure TOptionsForm.EnableKeys; begin DirectionGroup.Enabled:=B; KeyEdit.Enabled:=B; WayCountEdit.Enabled:=B; end; procedure TOptionsForm.BitBtn5Click(Sender: TObject); begin Close; MainForm.GenerateKey; end; procedure TOptionsForm.FormCreate(Sender: TObject); var i: integer; begin for i:=1 to QolMethods do begin MethodsBox.Items.Add(Methods[i].MethodName); Used[i]:=false; end; UsedMethodsBox.Clear; EnableKeys(False); DescMemo.Clear; end; procedure TOptionsForm.BitBtn4Click(Sender: TObject); var i: integer; begin UsedMethodsBox.Clear; for i:=1 to QolMethods do Used[i]:=false; EnableKeys(False); DescMemo.Clear; end; procedure TOptionsForm.BitBtn3Click(Sender: TObject); begin If UsedMethodsBox.ItemIndex=-1 then exit; Used[MethodIndex(UsedMethodsBox.Items.Strings[UsedMethodsBox.ItemIndex])]:=false; UsedMethodsBox.Items.Delete(UsedMethodsBox.ItemIndex); If UsedMethodsBox.Items.Count=0 then EnableKeys(False); DescMemo.Clear; end; procedure TOptionsForm.BitBtn2Click(Sender: TObject); begin If MethodsBox.ItemIndex=-1 then exit; if UsedMethodsBox.Items.IndexOf(Methods[MethodsBox.ItemIndex+1].MethodName)=-1 then begin UsedMethodsBox.Items.Add(Methods[MethodsBox.ItemIndex+1].MethodName); Used[MethodsBox.ItemIndex+1]:=true; EnableKeys(True); UsedMethodsBox.ItemIndex:=UsedMethodsBox.Items.Count-1; UsedMethodsBox.OnClick(Self); end; end; procedure TOptionsForm.BitBtn1Click(Sender: TObject); var i: integer; begin UsedMethodsBox.Clear; for i:=1 to QolMethods do begin UsedMethodsBox.Items.Add(Methods[i].MethodName); Used[i]:=true; end; EnableKeys(True); end; procedure TOptionsForm.UsedMethodsBoxClick(Sender: TObject); var i: integer; begin If (UsedMethodsBox.ItemIndex=-1)or (UsedMethodsBox.Items.Count=0) then begin EnableKeys(False); DescMemo.Clear; Exit; end else begin EnableKeys(True); end; i:=MethodIndex(UsedMethodsBox.Items.Strings[UsedMethodsBox.ItemIndex]); if i=0 then exit; DirectionGroup.ItemIndex:=UsedMethods[i].Direction-1; KeyEdit.MaxLength:=Methods[i].KeyMaxLength; KeyEdit.Text:=String(UsedMethods[i].Key); WayCountEdit.Value:=UsedMethods[i].WayCount; DescMemo.Clear; DescMemo.Lines.Append(Methods[i].MethodDescription); end; procedure TOptionsForm.DirectionGroupExit(Sender: TObject); var i: integer; begin If (UsedMethodsBox.ItemIndex=-1)or (UsedMethodsBox.Items.Count=0) then Exit; i:=MethodIndex(UsedMethodsBox.Items.Strings[UsedMethodsBox.ItemIndex]); if i=0 then exit; UsedMethods[i].Direction:=DirectionGroup.ItemIndex+1; end; procedure TOptionsForm.KeyEditExit(Sender: TObject); var i: integer; begin If (UsedMethodsBox.ItemIndex=-1)or (UsedMethodsBox.Items.Count=0) then Exit; i:=MethodIndex(UsedMethodsBox.Items.Strings[UsedMethodsBox.ItemIndex]); if i=0 then exit; StrPCopy(UsedMethods[i].Key,KeyEdit.Text); end; procedure TOptionsForm.WayCountEditExit(Sender: TObject); var i: integer; begin If (UsedMethodsBox.ItemIndex=-1)or (UsedMethodsBox.Items.Count=0) then Exit; i:=MethodIndex(UsedMethodsBox.Items.Strings[UsedMethodsBox.ItemIndex]); if i=0 then exit; UsedMethods[i].WayCount:=WayCountEdit.Value; end; procedure TOptionsForm.FormClose(Sender: TObject; var Action: TCloseAction); var i: integer; begin Action:=caHide; for i:=1 to QolMethods do begin if Used[i] then begin if StrLen(UsedMethods[i].Key)<Methods[i].KeyMinLength then begin ShowMessage(Methods[i].MethodName+': '+Methods[i].KeyMinMessage); Action:=caNone; Exit; end else if StrLen(UsedMethods[i].Key)>Methods[i].KeyMaxLength then begin ShowMessage(Methods[i].MethodName+': '+Methods[i].KeyMaxMessage); Action:=caNone; Exit; end; end; end; end; end. unit ProgressUnit; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ComCtrls, StdCtrls; type TProgressForm = class(TForm) Label1: TLabel; PBOne: TProgressBar; PBAll: TProgressBar; Label2: TLabel; private { Private declarations } public Current: integer; procedure UpdateProgress(fn: String;perc:integer;Cap:String); procedure InitProgress(qol:integer;Cap:String); procedure EndProcess; { Public declarations } end; var ProgressForm: TProgressForm; implementation {$R *.DFM} procedure TProgressForm.EndProcess; begin inc(current); end; procedure TProgressForm.UpdateProgress; begin ProgressForm.Caption:=Cap+' - '+inttostr(round(PBAll.Position*100/PBAll.Max))+'%'; Label1.Caption:=Cap+fn; PBOne.Position:=perc; PBAll.Position:=100*Current+perc; end; procedure TProgressForm.InitProgress; begin Caption:=Cap; Label1.Caption:='Подготовка...'; PBOne.Position:=0; PBOne.Max:=100; PBAll.Position:=0; PBAll.Max:=qol*100; Current:=0; end; end. unit TestUnit; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ActnList, ExtCtrls, ComCtrls, ToolWin, Grids, Outline, DirOutln, Buttons, ShellApi, Registry; type TMainForm = class(TForm) Label1: TLabel; RecurseBox: TCheckBox; BitBtn1: TBitBtn; StaticText1: TStaticText; MainKey: TEdit; BitBtn2: TBitBtn; Open: TOpenDialog; BitBtn3: TBitBtn; BitBtn4: TBitBtn; BitBtn5: TBitBtn; BitBtn6: TBitBtn; files: TListBox; procedure FileDrop(var Msg: TWMDropFiles); message WM_DROPFILES; procedure AddCmdLine(var msg: TMessage); message WM_USER; procedure FormCreate(Sender: TObject); procedure BitBtn1Click(Sender: TObject); procedure DoCommandLine(S: String); procedure StopDblClick(Sender: TObject); procedure GoDblClick(Sender: TObject); procedure GenerateKey; function DecodeKey: integer; procedure BitBtn2Click(Sender: TObject); procedure BitBtn3Click(Sender: TObject); procedure BitBtn6Click(Sender: TObject); private { Private declarations } public end; var MainForm: TMainForm; Decode: boolean; implementation uses CodingUnit, OptionsUnit, ProgressUnit; {$R *.DFM} procedure TMainForm.GenerateKey; var i,k,l: integer; s: string; begin for i:=1 to QolMethods do begin If Used[i] then begin k:=random(9)+1; s:=concat(s,Methods[i].MethodKey); s:=concat(s,IntToStr(k)); l:=strlen(UsedMethods[i].Key)+k*6; s:=concat(s,Format('%2d',[l])); s:=concat(s,StrPas(UsedMethods[i].Key)); s:=concat(s,Format('%2d',[strlen(UsedMethods[i].Key)+k*5+UsedMethods[i].Direction])); s:=concat(s,Format('%2d',[strlen(UsedMethods[i].Key)+k*4+UsedMethods[i].WayCount])); end; end; for i:=1 to length(s) do if s[i]=' ' then s[i]:='-'; MainKey.Text:=S; end; function TMainForm.DecodeKey; var i,k,l,t: integer; s: string; begin Result:=0; s:=MainKey.Text; for i:=1 to length(s) do if s[i]='-' then s[i]:='0'; try while s<>'' do begin t:=MethodByChar(s[1]); Used[t]:=true; delete(s,1,1); k:=strtoint(copy(s,1,1)); delete(s,1,1); l:=strtoint(copy(s,1,2))-k*6; delete(s,1,2); StrPCopy(UsedMethods[t].Key,copy(s,1,l)); delete(s,1,l); UsedMethods[t].Direction:=strtoint(copy(s,1,2))-l-k*5; delete(s,1,2); UsedMethods[t].WayCount:=strtoint(copy(s,1,2))-l-k*4; delete(s,1,2); end; except on E:Exception do Result:=1; end; end; Procedure TMainForm.DoCommandLine(S: String); var i: integer; tmp: string; begin System.CmdLine:=PChar(S); tmp:=ParamStr(1); if CompareText(tmp,'/D')=0 then begin // декодирование Decode:=true; StaticText1.Caption:='Введите ключ'; MainKey.Color:=clWindow; MainKey.ReadOnly:=false; MainKey.Text:=''; if ParamCount>1 then begin for i:=2 to ParamCount do begin Files.Items.Add(ParamStr(i)); end; end; end else begin //кодирование if ParamCount>0 then for i:=1 to ParamCount do begin Files.Items.Add(ParamStr(i)); end; Decode:=False; end; end; procedure TMainForm.AddCmdLine(var msg: TMessage); //var // P: array[0..1024]of char; begin // GlobalGetAtomName(msg.WParam,p,1023); // GlobalDeleteAtom(msg.WParam); // DoCommandLine(String(P)); end; procedure TMainForm.FormCreate(Sender: TObject); begin Caption:='Кодирование'; DragAcceptFiles(Handle,TRUE); if Decode then BitBtn1.Enabled:=false; end; procedure TMainForm.BitBtn1Click(Sender: TObject); begin OptionsForm.ShowModal; end; procedure TMainForm.StopDblClick(Sender: TObject); begin Close; end; procedure ValidateFiles; var i,k: integer; begin with MainForm.Files do begin i:=0; while i<=Items.Count-2 do begin k:=i+1; while k<=Items.Count-1 do begin if CompareText(Items.Strings[i],Items.Strings[k])=0 then begin Items.Delete(k); continue; end; inc(k); end; inc(i); end; end; end; procedure TMainForm.FileDrop(var msg:TWMDropFiles); var i,count: integer; p: pchar; s: string; attr:LongWord; begin msg.Result:=0; count:=DragQueryFile(Msg.Drop,$ffffffff,nil,0); getmem(p,1024); for i:=0 to count-1 do begin DragQueryFile(msg.Drop,i,p,1024); s:=StrPas(p); attr:=GetFileAttributes(PCHAR(s)); if attr<>$ffffffff then begin if (attr and FILE_ATTRIBUTE_DIRECTORY) = 0 then begin if Decode then begin if Pos('.crf',lowercase(s))<>0 then files.Items.Add(s); end else begin if Pos('.crf',lowercase(s))=0 then files.Items.Add(s); end; end; end; end; freemem(p,1024); DragFinish(msg.Drop); ValidateFiles; end; function NoMethods:Boolean; var i:integer; begin result:=true; for i:=1 to QolMethods do if used[i] then result:=false; end; procedure TMainForm.GoDblClick(Sender: TObject); var i: integer; begin if files.Items.Count=0 then begin ShowMessage('Список файлов пуст'); Exit; end; ValidateFiles; if Decode then begin if MainKey.Text='' then begin ShowMessage('Вы забыли ввести ключ'); exit; end; if DecodeKey<>0 then begin ShowMessage('Введен неправильный ключ'); Exit; end; if NoMethods then begin ShowMessage('Не выбрано ни одного метода'); Exit; end; ProgressForm.InitProgress(files.Items.Count,'Декодирование'); ProgressForm.Show; for i:=0 to files.items.count-1 do begin DoDecoding(files.items.strings[i]); end; ProgressForm.Hide; end else begin if NoMethods then begin ShowMessage('Не выбрано ни одного метода'); Exit; end; ProgressForm.InitProgress(files.Items.Count,'Кодирование'); ProgressForm.Show; for i:=0 to files.items.count-1 do begin DoCoding(files.items.strings[i]); end; ProgressForm.Hide; end; end; procedure TMainForm.BitBtn2Click(Sender: TObject); var T: TRegistry; begin T:=TRegistry.Create; T.RootKey:=HKEY_LOCAL_MACHINE; T.OpenKey('\Software\Laynik Group\[LG] Hazard Encrypter 2000',True); Open.InitialDir:=T.ReadString('Lastpath'); if Open.Execute then begin files.Items.AddStrings(Open.files); validatefiles; T.WriteString('Lastpath',ExtractFileDir(Open.Files.Strings[Open.Files.Count-1])); end; T.Free; end; procedure TMainForm.BitBtn3Click(Sender: TObject); begin if (files.Items.Count=0) or (files.ItemIndex=-1) then exit; files.Items.Delete(files.ItemIndex); end; procedure TMainForm.BitBtn6Click(Sender: TObject); begin files.clear; end; end. unit CodingUnit; interface uses Classes,SysUtils,Dialogs,CodingTools,K1,K2,K3,GOST; Const PIECE_LENGTH = $FFFF; // Direction constants diForward = 1; diBackward = 0; // ERROR VALUES CL_ERROR_EMPTYLINE = -1; CL_ERROR_NOFILENAME = -2; function Coding_Kir(Buf: Pointer; Size: LongInt; Param: TCodingParameters): Integer; function DeCoding_Kir(Buf: Pointer; Size: LongInt; Param: TCodingParameters): Integer; function DoCoding(S: String): integer; function DoDecoding(S: String): integer; function MethodIndex(const S: String):integer; function MethodByChar(const C: Char):integer; const QolMethods = 4; Methods:array[1..QolMethods] of TCodingFunction = ((MethodName:'ГОСТ 28147-89 (ПЗ)';MethodKey:'G';MethodProc:Coding_GOST;MethodDecProc:Coding_GOST; KeyMinLength:32;KeyMaxLength:32;KeyMinMessage:'Ключ должен быть длиной 32 символa';KeyMaxMessage:'Ключ должен быть длиной 32 символa'; MethodDescription:'Кодирование по ГОСТ 28147-89 (простая замена)'), (MethodName:'ГОСТ 28147-89 (Г)';MethodKey:'G';MethodProc:Coding_GOST;MethodDecProc:Coding_GOST; KeyMinLength:32;KeyMaxLength:32;KeyMinMessage:'Ключ должен быть длиной 32 символa';KeyMaxMessage:'Ключ должен быть длиной 32 символa'; MethodDescription:'Кодирование по ГОСТ 28147-89 (гаммирование)'), (MethodName:'К1';MethodKey:'K';MethodProc:Coding_K1;MethodDecProc:DeCoding_K1; KeyMinLength:8;KeyMaxLength:8;KeyMinMessage:'Ключ должен быть длиной 8 символов';KeyMaxMessage:'Ключ должен быть длиной 8 символов'; MethodDescription:'Сумма по модулю два'), (MethodName:'К2';MethodKey:'L';MethodProc:Coding_K2;MethodDecProc:DeCoding_K2; KeyMinLength:3;KeyMaxLength:8;KeyMinMessage:'Минимальная длина ключа - 3 символа';KeyMaxMessage:'Ключ должен быть длиной менее 9 символов'; MethodDescription:'Циклический сдвиг')); UsedMethods:array[1..QolMethods] of TCodingParameters = ((Key:'';WayCount:1;Direction:1), (Key:'';WayCount:1;Direction:1), (Key:'';WayCount:1;Direction:1), (Key:'';WayCount:1;Direction:1)); Used: array[1..QolMethods] of boolean = (false, false, false, false); implementation uses TestUnit, ProgressUnit; function MethodIndex(const S: String):integer; var i: integer; begin Result:=0; for i:=1 to QolMethods do begin if CompareStr(S,Methods[i].MethodName)=0 then Result:=i; end; end; function MethodByChar(const C: Char):integer; var i: integer; begin Result:=0; for i:=1 to QolMethods do begin if C=Methods[i].MethodKey then Result:=i; end; end; function GenerateFileName(s:string):string; begin Result:=concat(s,'.crf'); end; function GenerateDecFileName(s:string):string; begin If Pos('.CRF',UpperCase(s))<>0 then delete(s,Pos('.CRF',uppercase(s)),4); s:=concat(s,'.dec'); Result:=s; end; function DoCoding(S: String): integer; var j,i,ks,ls,size,res,fs,pr: integer; f,outp: file; buf: pointer; S1: String; begin result:=0; GetMem(buf,$10000); fillchar(buf^,$10000,0); if buf=nil then begin ShowMessage('Не хватает памяти под буфер'); Result:=1; exit; end; AssignFile(f,s); s1:=GenerateFileName(s); AssignFile(outp,s1); {$I-} Reset(f,1); fs:=filesize(f); Rewrite(outp,1); {$I+} if IOResult=0 then begin ProgressForm.UpdateProgress(s1,0,'Кодирование '); size:=$10000; while size=$10000 do begin BlockRead(f,buf^,$10000,size); for i:=1 to QolMethods do begin ks:=0; if (size mod 8)<>0 then begin ls:=(8*((size div 8)+1)); ks:=ls-size; for j:=size to ls-1 do PCHAR(buf)[j]:=#0; end else ls:=size; if Used[i] then Methods[i].MethodProc(buf,ls,UsedMethods[i]); if fs<>0 then pr:=round(filepos(f)*100 / fs) else pr:=round((100*i) / qolmethods); ProgressForm.UpdateProgress(s1,pr,'Кодирование '); end; BlockWrite(outp,buf^,ls,res); end; if ks<>0 then blockwrite(outp,ks,1); end else ShowMessage('Ошибка обращения к '+S); CloseFile(f); CloseFile(outp); FreeMem(buf,$10000); ProgressForm.EndProcess; end; function DoDecoding(S: String): integer; var ks,pr,i,size,res,fs: integer; f,outp: file; buf: pointer; s1: string; begin result:=0; GetMem(buf,$10000); fillchar(buf^,$10000,0); if buf=nil then begin ShowMessage('Не хватает памяти под буфер'); Result:=1; exit; end; AssignFile(f,s); s1:=GenerateDecFileName(s); AssignFile(outp,s1); {$I-} Reset(f,1); fs:=filesize(f); Rewrite(outp,1); {$I+} if IOResult=0 then begin ProgressForm.UpdateProgress(s1,0,'Декодирование '); size:=$10000; while size=$10000 do begin BlockRead(f,buf^,$10000,size); for i:=QolMethods downto 1 do begin if Used[i] then Methods[i].MethodDecProc(buf,size,UsedMethods[i]); if fs<>0 then pr:=round(filepos(f)*100 / fs) else pr:=round((100*i) / qolmethods); ProgressForm.UpdateProgress(s1,pr,'Декодирование '); if (size mod 8)<>0 then begin ks:=byte(PCHAR(Buf)[size-1])+1; end else ks:=0; end; BlockWrite(outp,buf^,size,res); end; Seek(outp,filepos(outp)-ks); Truncate(outp); end else ShowMessage('Ошибка обращения к '+S); CloseFile(f); CloseFile(outp); FreeMem(buf,$10000); ProgressForm.EndProcess; end; function Coding_Kir; begin Result:=0; end; function DeCoding_Kir; begin Result:=0; end; end. unit GOST; interface uses SysUtils, CodingTools; function coding_GOST(Buf: Pointer; Size: LongWord; Param: TCodingParameters):Integer; function coding_GOSTSE(Buf: Pointer; Size: LongWord; Param: TCodingParameters):Integer; implementation var Key: array [0..7] of LongWord; const ExchTable: array [0..7,0..15] of byte = ((2,5,3,7,12,1,15,14,9,4,6,8,10,0,11,13), (8,3,1,9,10,15,2,14,13,5,11,7,0,12,4,3), (15,1,14,2,13,3,12,4,11,5,10,0,6,9,7,8), (1,3,5,7,9,2,4,6,8,10,11,13,15,12,14,0), (1,4,7,10,13,2,5,8,11,0,14,3,6,9,12,15), (1,5,9,13,2,6,10,0,14,3,7,11,15,4,8,12), (1,6,11,2,7,12,0,3,8,13,4,9,14,5,10,15), (1,7,0,13,2,8,14,3,9,15,4,10,5,11,6,12)); C1 = $1010101; C2 = $1010104; procedure BaseStep(var N:word64; X: longword); var i:integer; s:word64; begin s.v32[0]:=(N.v32[0] + X) mod $100000000; for i:=0 to 3 do begin //Замена по таблице младшие или старшие 4 бита s.v8[i]:=(ExchTable[i*2,(s.v8[i] and $0F)]) or (ExchTable[i*2+1,((s.v8[i] shr 4) and $0F)] shl 4); end; asm push ecx mov cl,11 rol DWORD[s.v32[0]],cl pop ecx end; s.v32[0]:=s.v32[0] xor N.v32[1]; N.v32[1]:=N.v32[0]; N.v32[0]:=s.v32[0]; end; procedure SEcoding64bits(var N:word64); var k,j: integer; s:LongWord; begin for k:=1 to 3 do for j:=0 to 7 do BaseStep(N,Key[j]); for j:=7 downto 0 do BaseStep(N,Key[j]); s:=N.v32[0]; N.v32[0]:=N.v32[1]; N.v32[1]:=s; end; procedure SEdecoding64bits(var N:word64); var k,j: integer; s:LongWord; begin for j:=0 to 7 do BaseStep(N,Key[j]); for k:=1 to 3 do for j:=7 downto 0 do BaseStep(N,Key[j]); s:=N.v32[0]; N.v32[0]:=N.v32[1]; N.v32[1]:=s; end; procedure GOST_G_coding(var T: pointer; S:word64; Size:word); var i:integer; begin SEcoding64bits(S); for i:=1 to (Size div 8) do begin S.v32[0]:=(S.v32[0]+C1) mod $100000000; S.v32[1]:=((S.v32[1]+C2-1) mod ($ffffffff)) +1; word64(Pointer(LongWord(T)+LongWord((i-1)*8))^).v32[0]:= word64(Pointer(LongWord(T)+LongWord((i-1)*8))^).v32[0] xor S.v32[0]; word64(Pointer(LongWord(T)+LongWord((i-1)*8))^).v32[1]:= word64(Pointer(LongWord(T)+LongWord((i-1)*8))^).v32[1] xor S.v32[1]; end; end; function coding_GOST(Buf: Pointer; Size: LongWord; Param: TCodingParameters):Integer; var i: integer; s: word64; begin s.v32[0]:=0; s.v32[1]:=0; for i:=0 to 7 do begin Key[i]:=(BYTE(Param.Key[i*4+3]) shr 24) or (BYTE(Param.Key[i*4+2]) shr 16) or (BYTE(Param.Key[i*4+1]) shr 8) or (BYTE(Param.Key[i*4])); s.v32[i mod 2]:=s.v32[i mod 2]+Key[i]; end; GOST_G_coding(Buf,s,Size); end; function coding_GOSTSE(Buf: Pointer; Size: LongWord; Param: TCodingParameters):Integer; var i: integer; begin for i:=0 to 7 do begin Key[i]:=(BYTE(Param.Key[i*4+3]) shr 24) or (BYTE(Param.Key[i*4+2]) shr 16) or (BYTE(Param.Key[i*4+1]) shr 8) or (BYTE(Param.Key[i*4])); end; for i:=1 to (Size div 8) do begin SEcoding64bits(word64(Pointer(LongWord(Buf)+LongWord((i-1)*8))^)); end; end; var i: integer; begin for i:=0 to 7 do Key[i]:=0; end.
|