Шифрование данных с помощью алгоритма DES
В начале над ключом шифра выполняется операция B, которая сводится к выбору определенных бит и их перестановке, как это показано в таблице 6. Причем, первые четыре строки определяют, как выбираются биты последовательности C (0) (первым битом C (0) будет бит 57 бит ключа шифра, затем бит 49 и т. д., а последними битами биты 44 и 36 ключа шифра), а следующие четыре строки — как выбираются биты… Читать ещё >
Шифрование данных с помощью алгоритма DES (реферат, курсовая, диплом, контрольная)
Муниципальное образовательное учреждение Средняя общеобразовательная школа № 1
Курсовой проект по информатике и программированию на тему:
Шифрование данных с помощью алгоритма DES
Выполнила: Мартьянова Юлия Ученица 10 «А» класса Руководитель: Еремеев С.В.
Муром 2011
1. Процесс шифрования алгоритма DES5
1.1 Процесс расшифрования
1.2 Процесс получения ключей
2. Спецификация программы
2.1 Список процедур и функций
2.2 Описание интерфейса пользователя Заключение Список использованной литературы Приложение, А Приложение Б
В данной работе рассматривается разработка приложения для шифрования данных с помощью алгоритма DES. Данное приложение предназначено для шифрования и защиты информации. Полученное индивидуальное задание по курсовой работе было выполнено в среде программирования DELPHI 7. Эта среда выбрана, так как она глубоко изучалась во время обучения, и хорошо отражает современные возможности программирования. В результате выполнения задания была создана программа, которая сочетает в себе: лёгкость в обращении, простоту интерфейса, возможность легко протестировать.
Данная программа наглядно демонстрирует сущность работы алгоритма шифрования данных DES (DataEncryptionSystem).
DES представляет собой блочный шифр, он шифрует данные 64-битовыми блоками. С одного конца алгоритма вводится 64-битовый блок открытого текста, а с другого конца выходит 64-битовый блок шифротекста. DES является симметричным алгоритмом: для шифрования и дешифрования используются одинаковые алгоритм и ключ (за исключением небольших отличий в использовании ключа).
Длина ключа равна 56 битам. (Ключ обычно представляется 64-битовым числом, но каждый восьмой бит используется для проверки четности и игнорируется.) Безопасность полностью определяется ключом.
При описании алгоритма шифрования используются следующие обозначения. Если L и R — последовательности бит, то через LR будем обозначать конкатенацию (операция склеивания объектов линейной структуры, обычно строк) последовательностей L и R, т. е. последовательность бит, размерность которой равна сумме размерностей L и R. В этой последовательности биты последовательности R следуют за битами последовательности L. Конкатенация битовых строк является ассоциативной, то есть запись ABCDE, означает, что за битами последовательности A, следуют, биты последовательности B, затем C и т. д. Символом + будем обозначать операцию побитового сложения.
1. Процесс шифрования алгоритма DES
Схема шифрования алгоритма DES указана на Рис.1
Процесс шифрования данных поясняется Рис.2
Исходный текст — блок 64 бит.
Процесс шифрования состоит в начальной перестановке, 16 циклах шифрования и конечной перестановке.
Рис. 1 Схема шифрования алгоритма DES
Сначала 64 бита входной последовательности перестанавливаются в соответствии с таблицей 1. Таким образом, бит 58 входной последовательности становится битом 1, бит 50 — 2 и т. д.
Таблица 1
Начальная перестановка
Затем выполняется итеративный процесс шифрования, который описывается следующими формулами:
L (i)=R (i-1), i=1,2,…, 16.
R (i)=L (i-1) + F (R (i-1), K (i)), i=1,2,…, 16.
Функция F называется функцией шифрования. Ее аргументами являются последовательность R, полученная на предыдущем шаге, и 48-битовый ключ K (i), который является результатом функции преобразования 64-битового ключа шифра.
На последнем шаге итерации (результат повторного применения какой-либо математической операции) будут получены последовательности L (16) и R (16), которые конкатенируются в 64-х битовую последовательность R (16)L (16). Видно, что в полученной последовательности 64 бита,
перестанавливаются в соответствии с таблицей 2. Как легко видеть данная перестановка является обратной по отношению к начальной (см. таблицу 1).
Таблица 2
" Конечная перестановка"
Полученная последовательность из 64 бит и будет являться зашифрованной последовательностью.
Рис. 2 Процесс шифрования данных
1.1 Процесс расшифрования
Процесс расшифрования данных является инверсным по отношению к процессу шифрования. Все действия должны быть выполнены в обратном порядке. Это означает, что расшифровываемые данные сначала переставляются в соответствии с таблицей 1, а затем над последовательностью бит R (16)L (16) выполняется те же действия, что и в процессе зашифрования, но в обратном порядке. Итеративный процесс расшифрования описан следующими формулами:
R (i-1)=L (i), i =16, 15, …, 1
L (i-1)=R (i)+F (L (i), K (i)), i=16, 15, …, 1.
На последнем шаге итерации будут получены последовательности L (0) и R (0), которые конкатенируются в 64 битовую последовательность L (0)R (0). В полученной последовательности 64 бита перестанавливаются в соответствии с таблицей 2. Результат преобразования — исходная последовательность бит (расшифрованное 64-битовое значение).
Функция шифрования F (R, K) схематически показана на рисунке 3. Для вычисления значения функции F используется функция E (расширение 32 бит до 48), функции S (1), S (2),…, S (8) преобразование 6-битового числа в 4-битовое) и функция P (перестановка бит в 32-битовой последовательности). Приведем определения этих функций. Аргументами функции шифрования являются R (32 бита) и K (48 бит). Результат функции E® есть 48-битовое число, которое складывается по модулю 2 с числом K. Таким образом, получается 48-битовая последовательность, которая рассматривается, как конкатенация 8 строк длиной по 6 бит (т.е.)
B (1)B (2)B (3)B (4)B (5)B (6)B (7)B (8)
Результат функции S (i)B (i) — 4 битовая последовательность, которую будем обозначать L (i). В результате конкатенаций всех 8 полученных последовательностей L (i) имеем 32-битовую последовательность
L=L (1)L (2)L (3)L (4)L (5)L (6)L (7)L (8).
Наконец, для получения результат функции шифрования надо переставить биты последовательности L. Для этого применяется функция перестановки P (L).
Функция расширения Е, выполняющая расширение 32 бит до 48, определяется таблицей 3. В соответствии с этой таблицей первые три бита Е® — это биты 32,1 и 2, а последние — 31,32,1.
Рис. 3
Таблица 3
Функция расширения Е
Функция S (i), которая преобразует 6-битовые числа в 4-битовые, определяется таблицей 4.
Таблица 4
" Функции преобразования S (i)" S (1)
S (2)
S (3)
S (4)
S (5)
S (6)
S (7)
S (8)
К таблице 4 требуются дополнительные пояснения. Каждая из функций S (i)B (i) преобразует 6-битовый код в 4-битовый выход по следующему алгоритму:
· первый и последний биты входной последовательности B, определяют номер строки k;
· второй, третий, четвертый и пятый биты последовательности B задают номер колонки l;
· результат преобразования выбирается из строки k и колонки l.
Предположим, что B=11 011. Тогда S (1)(B)=0101. Действительно, k=1, l=13. В колонке 13 строки 1 задано значение 5, которое и является значением функции S (1)(11 011).
Функция перестановки бит P (L), также используемая для определения функции шифрования, задается значениями, приведенными в таблице 5. В последовательности L 32 перестанавливается так, чтобы бит 16 стал первым битом, бит 7 — вторым и т. д.
Таблица 5
" Функция перестановки P"
1.2 Процесс получения ключей
Чтобы завершить описание алгоритма шифрования данных, осталось привести алгоритм получение ключей K (i), i=1,2,…, 16, размерностью в 48 бит. Ключи K (i) определяются по 64-битовому ключу шифра как это показано на рисунке 4.
Рис.4
В начале над ключом шифра выполняется операция B, которая сводится к выбору определенных бит и их перестановке, как это показано в таблице 6. Причем, первые четыре строки определяют, как выбираются биты последовательности C (0) (первым битом C (0) будет бит 57 бит ключа шифра, затем бит 49 и т. д., а последними битами биты 44 и 36 ключа шифра), а следующие четыре строки — как выбираются биты последовательности D (0) (т.е. последовательность D (0) будем состоять из битов 63,55,…, 12, 4 ключа шифра).
Таблица 6
Функция перестановки и выбора последовательности B
Как видно из таблицы 6, для генерации последовательностей C (0) и D (0) не используются биты 8,16,25,32,40,48,56 и 64 ключа шифра. Эти биты не влияют на шифрование и могут служить для других целей (например, для контроля по четности). Таким образом, в действительности ключ шифра является 56-битовым. После определения C (0) и D (0) рекурсивно определяются C (i) и D (i), i=1,2,…, 16. Для этого применяются операции сдвига влево на один или два бита в зависимости от номера шага итерации, как это показано в таблице 7.
Операции сдвига выполняются для последовательностей C (i) и D (i) независимо. Например, последовательность C (3) получается, посредством сдвига влево на две позиции последовательности C (2), а последовательность D (3) — посредством сдвига влево на две позиции последовательности D (2). Следует иметь в виду, что выполняется циклический сдвиг влево. Например, единичный сдвиг влево последовательности C (i) приведет к тому, что первый бит C (i) станет последним, и последовательность бит будет следующая: 2,3,…, 28,1.
Таблица 7
Функция сдвига Si
Ключ K (i), определяемый на каждом шаге итерации, есть результат выбора определенных бит из 56-битовой последовательности C (i)D (i) и их перестановки. Другими словами, K (i) = K (C (i)D (i)), где функция K определяется данными, приведенными в таблице 8.
Таблица 8
Функция перестановки и выбора K
Как следует из таблицы 8 первый бит K (i) — это бит 14 последовательности C (i)D (i), второй — бит 17, последний — бит 32.
приложение шифрование ключ процедура
2. Спецификация программы
2.1 Список процедур и функций
· ProcedureTForm1. FormCreate — выполняется, как только создается форма.
· ProcedureTForm1. Button1Click — выполняется при нажатии кнопки «Encode» .
· ProcedureTForm1. Button2Click — выполняется при нажатии кнопки «Decode» .
· ProcedureTForm1. Memo1Change — выполняется при изменении содержимого ТMemo1.
· ProcedureTForm1. Memo1Change — выполняется при изменении содержимого ТMemo2.
· Procedure TForm1. Edit1Change — выполняется при изменении содержимого TEdit1.
· FunctionBinToInt — перевод из двоичного представления числа в целочисленный десятичный тип.
· FunctionIntToBin — перевод из десятичного представления числа в двоичный тип с использованием указателей, выделением и освобождением памяти под этот процесс.
· FunctionBinToStr — перевод бинарных чисел в их строковый эквивалент.
· FunctionStrToBin — переводит строку содержащую бинарный код в соответствующее бинарное число.
· FunctionAnsiStrToBin — перевод строки символов в бинарное число.
· FunctionBinToAnsiStr — перевод бинарных комбинаций в строку символов.
· ProcedureCopyBits — процедура для побитового копирования данных из одной переменной в другую.
· FunctionConcatBits — функция для побитового объединения данных двух переменных.
· FunctionGetPermutedKey — первоначальная перестановка ключа в соответствии с таблицей перестановки с отбрасыванием каждого 8-го бита (бита четности).
· FunctionGetPermutedKey2 — перестановка со сжатием. После сдвига выбирается 48 из 56-ти битов.
· FunctionGetSplitKey — 56-ти битовый ключ делится на две 28-и битовых половины затем половины циклически сдвигаются влево на один или два бита.
· FunctionGetConcatKey — функция для объединения сгенерированного ключа после перестановки с расширением.
· FunctionGetIPKey — начальная перестановка. (Служит для облегчения побайтной загрузки открытого текста в микросхему DES).
· FunctionGetF — правая половина данных увеличивается до 48 битов с помощью перестановки с расширением, объединяется посредством XOR с 48 битами смещенного и переставленного ключа, проходит через 8 S-блоков, образуя 32 новых бита и переставляется снова.
· FunctionGetSBox — функция реализует 8 S-блоков. Каждый S-блок представляет собой таблицу из двух строк и 16-ти столбцов. По 6-ти входным битам S-блока определяется, под какими номерами столбцов и строк искать выходное значение.
· FunctionGetReverseIP — конечная (обратная) перестановка.
· ProcedureReverceSubKeys — обратная перестановка подключа.
· FunctionDESEncode — основная функция шифрующая данные. Переводит ключ в бинарный вид, получение сгенерированного ключа, перевод исходного текста в бинарный вид, начальная перестановка, блок разбивается на два 32-битных половины, затем выполняется 16 этапов одинаковых действий (функция GetF), после 16 -го этапа правая и левая половины объединяются и алгоритм завершается обратной перестнаовкой.
· FunctionDESDecode — функция дешифрующая данные. Аналогична функции DESEncode, с отличием, что после получения сгенерированного ключа он реверсируется функцией ReverceSubKeys.
2.2 Описание интерфейса пользователя
Интерфейс программы состоит из одного, главного окна. В верхней части находится поле, в которое необходимо ввести ключ (пароль). Пароль обязательно должен состоять из 8 символов (особенность алгоритма DES).
В поле ниже необходимо ввести текст сообщения, которое необходимо зашифровать. Количество символов должно быть кратно 8, причем переход на новую строку считается как 2 символа. Для облегчения над полем ввода будет отображаться количество введенных символов. При вводе сообщения символы будут автоматически переводится в бинарный код. Это сделано для наглядности работы алгоритма.
После ввода сообщения необходимо нажать кнопку с надписью «Шифровать», чтобы начать шифрование. При несоблюдении условия о кратности 8 будет выдано сообщение об ошибке.
По окончании шифрования в нижнем поле появится зашифрованное сообщение и его бинарная интерпретация.
Для расшифровки сообщения необходимо ввести зашифрованный текст в поле, ввести правильный пароль и нажать кнопку «Расшифровать».
Заключение
Данная программа разрабатывалась в качестве курсовой работы, и не воспроизводит все возможности данного алгоритма. Тем не менее, она решает поставленную на этапе проектирования задачу — «Шифрование данных с помощью алгоритма DES».
Разработанная программа позволяет наглядно ознакомиться с основными принципами алгоритма DES.
1. Брюс Шнайер. Прикладная криптография. Наука (1983).
2. Диффи У., Хеллмен Э. Новое направление в криптографии //ТИ-ИЭР. IT-22 (1976).
3. Диффи У., Хеллмен Э. Защищенность и имитостойкость: введение в криптографию (1979).
4. Система обработки информации. Защита криптографическая. Алгоритм криптографического преобразования. ГОСТ 28 147–89 (1989).
5. http://ru.wikipedia.org/wiki/DES (ссылка)
6. http://cryptogrof.ru/algoritm des
7. http://protect.htmlweb.ru/des.htm
Приложение А
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, DES, StdCtrls;
type
TForm1 = class (TForm)
Label1: TLabel;
Edit1: TEdit;
Label2: TLabel;
Memo1: TMemo;
Button1: TButton;
Label3: TLabel;
Memo2: TMemo;
Button2: TButton;
Memo3: TMemo;
Label4: TLabel;
Memo4: TMemo;
procedure Button1Click (Sender: TObject);
procedure Button2Click (Sender: TObject);
procedure Memo1Change (Sender: TObject);
procedureFormCreate (Sender: TObject);
procedure Edit1Change (Sender: TObject);
procedure Memo2Change (Sender: TObject);
private
{ Private declarations }
public
Data:TBitString;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1. Button1Click (Sender: TObject);
Var
I:Integer;
S:String;
begin
IF ((Length (Memo1.Text)mod 8 <> 0) OR (Length (Edit1.Text)mod 8 <> 0))
Then
Begin
MessageBox (Handle,
'Количество букв в сообщении должно быть кратоно 8 (перевод строки
считается за 2 буквы)'+
#10#13'Ключ должен состоять из 8 символов',
Nil, MB_ICONSTOP);
Exit;
End;
SetLength (Data, 0);
I:=1;
While I<=Length (Memo1.Text) Do
Begin
S:=Copy (Memo1.Text, I,8);
Data:=ConcatBits ([Data, DESEncode (S, Edit1. Text)]);
I:=I+8;
End;
Memo2.Text:=BinToAnsiStr (Data);
end;
procedure TForm1. Button2Click (Sender: TObject);
var
I:Integer;
begin
IF ((Length (Memo2.Text)mod 8 <> 0) OR (Length (Edit1.Text)mod 8 <> 0))
Then
Begin
MessageBox (Handle,
'Количество букв в сообщении должно быть кратоно 8 (перевод строки
считается за 2 буквы)'+
#10#13'Ключ должен состоять из 8 символов',
Nil, MB_ICONSTOP);
Exit;
End;
SetLength (Data, 0);
I:=1;
While I<=Length (Memo2.Text) Do
Begin
Data:=ConcatBits ([Data, DESDecode (Copy (Memo2.Text, I,8), Edit1. Text)]);
I:=I+8;
End;
Memo1.Text:=BinToAnsiStr (Data);
end;
procedure TForm1. Memo1Change (Sender: TObject);
begin
IF Memo1. Text<>'' Then
Memo3.Text:=BinToStr (AnsiStrToBin (Memo1.Text))
Else Memo3. Clear;
Label2.Caption:='Message — ('+IntToStr (Length (Memo1.Text))+'
characters)';
end;
procedure TForm1. FormCreate (Sender: TObject);
begin
Memo1.OnChange (Self);
Edit1.OnChange (Self);
end;
procedure TForm1. Edit1Change (Sender: TObject);
begin
Label4.Caption:=IntToStr (Length (Edit1.Text))+' characters';
end;
procedure TForm1. Memo2Change (Sender: TObject);
begin
IF Memo2. Text<>'' Then
Memo4.Text:=BinToStr (AnsiStrToBin (Memo2.Text))
Else Memo4. Clear;
Label3.Caption:='Encoded message — ('+IntToStr (Length (Memo2.Text))+'
characters)';
end;
end.
Приложение Б
unit DES;
interface
Uses Windows, Classes, SysUtils, Math, Dialogs;
Type
TBitString = Array of Boolean;
PBitString = ^TBitString;
TSplitKeyParts = record
C:TBitString;
D:TBitString;
end;
TSplitKey = Array[0.16]Of TSplitKeyParts;
TConcatKey = Array[0.15]Of TBitString;
TIPKeyParts = record
L:TBitString;
R:TBitString;
end;
TIPKey = Array[0.16]OF TIPKeyParts;
Const
DES_PC1:Array[0.55] Of Byte = (57,49,41,33,25,17,9,
1,58,50,42,34,26,18,
10,2,59,51,43,35,27,
19,11,3,60,52,44,36,
63,55,47,39,31,23,15,
7,62,54,46,38,30,22,
14,6,61,53,45,37,29,
21,13,5,28,20,12,4);
DES_PC2:Array[0.47] Of Byte = (14,17,11,24,1,5,
3,28,15,6,21,10,
23,19,12,4,26,8,
16,7,27,20,13,2,
41,52,31,37,47,55,
30,40,51,45,33,48,
44,49,39,56,34,53,
46,42,50,36,29,32);
DES_IP:Array[0.63] Of Byte = (58,50,42,34,26,18,10,2,
60,52,44,36,28,20,12,4,
62,54,46,38,30,22,14,6,
64,56,48,40,32,24,16,8,
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);
DES_E:Array[0.47] Of Byte = (32,1,2,3,4,5,
4,5,6,7,8,9,
8,9,10,11,12,13,
12,13,14,15,16,17,
16,17,18,19,20,21,
20,21,22,23,24,25,
24,25,26,27,28,29,
28,29,30,31,32,1);
S_BOXES:Array[0.7,0.3,0.15]Of Byte = (
((14,04,13,01,02,15,11,08,03,10,06,12,05,09,00,07),
(00,15,07,04,14,02,13,01,10,06,12,11,09,05,03,08),
(04,01,14,08,13,06,02,11,15,12,09,07,03,10,05,00),
(15,12,08,02,04,09,01,07,05,11,03,14,10,00,06,13)),
((15,01,08,14,06,11,03,04,09,07,02,13,12,00,05,10),
(03,13,04,07,15,02,08,14,12,00,01,10,06,09,11,05),
(00,14,07,11,10,04,13,01,05,08,12,06,09,03,02,15),
(13,08,10,01,03,15,04,02,11,06,07,12,00,05,14,09)),
((10,00,09,14,06,03,15,05,01,13,12,07,11,04,02,08),
(13,07,00,09,03,04,06,10,02,08,05,14,12,11,15,01),
(13,06,04,09,08,15,03,00,11,01,02,12,05,10,14,07),
(01,10,13,00,06,09,08,07,04,15,14,03,11,05,02,12)),
((07,13,14,03,00,06,09,10,01,02,08,05,11,12,04,15),
(13,08,11,05,06,15,00,03,04,07,02,12,01,10,14,09),
(10,06,09,00,12,11,07,13,15,01,03,14,05,02,08,04),
(13,15,00,06,10,01,13,08,09,04,05,11,12,07,02,14)),
((02,12,04,01,07,10,11,06,08,05,03,15,13,00,14,09),
(14,11,02,12,04,07,13,01,05,00,15,10,03,08,09,06),
(04,02,01,11,10,13,07,08,15,09,12,05,06,03,00,14),
(11,08,12,07,01,14,02,13,06,15,00,09,10,04,05,03)),
((12,01,10,15,09,02,06,08,00,13,03,04,14,07,05,11),
(10,15,04,02,07,12,09,05,06,01,13,14,00,11,03,08),
(09,14,15,05,02,08,12,03,07,00,04,10,01,13,11,06),
(04,03,02,12,09,05,15,10,11,14,01,04,06,00,08,13)),
((04,11,02,14,15,00,08,13,03,12,09,07,05,10,06,01),
(13,00,11,07,04,09,01,10,14,03,05,12,02,15,08,06),
(01,04,11,13,12,03,07,14,10,15,06,08,00,05,09,02),
(06,11,13,08,01,04,10,07,09,05,00,15,14,02,03,12)),
((13,02,08,04,06,15,11,01,10,09,03,14,05,00,12,07),
(01,15,13,08,10,03,07,04,12,05,06,11,00,14,09,02),
(07,11,04,01,09,12,14,02,00,06,10,13,15,03,05,08),
(02,01,14,07,04,10,08,13,15,12,09,00,03,05,06,11)));
DES_P:Array[0.31] Of Byte = (16,7,20,21,
29,12,28,17,
1,15,23,26,
5,18,31,10,
2,8,24,14,
32,27,3,9,
19,13,30,6,
22,11,4,25);
DES_REVERSE_IP:Array[0.63] Of Byte = (40,8,48,16,56,24,64,32,
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);
DES_LSH:Array[0.15] Of Byte = (1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1);
Function BinToInt (S:TBitString):Integer;
Function IntToBin (N:Integer;Precision:Integer=8):TBitString;
Function BinToStr (Bits:TBitString):String;
Function StrToBin (S:String):TBitString;
Function AnsiStrToBin (S:String; Zeroes: Boolean=True):TBitString;
Function BinToAnsiStr (Bits:TBitString):String;
Procedure CopyBits (VarDest:TBitString; Source: TBitString; NBits: Integer);
Function ConcatBits (Bits:Array Of TBitString):TBitString;
Function DESEncode (S, Key: String):TBitString;
Function DESDecode (S, Key: String):TBitString;
Function GetPermutedKey (Key:TBitString):TBitString;
Function GetPermutedKey2(Key:TBitString):TBitString;
Function GetSplitKey (Key:TBitString):TSplitKey;
Function GetConcatKey (Key:TSplitKey):TConcatKey;
Function GetIPKey (M:TBitString; ConcatKey: TConcatKey):TIPKey;
Function GetF (R, K: TBitString):TBitString;
Function GetSBox (Index:Integer; T: TBitString):TBitString;
Function GetReverseIP (RL:TBitString):TBitString;
Procedure ReverseSubKeys (VarKeys:TConcatKey);
implementation
Function ConcatBits (Bits:Array Of TBitString):TBitString;
Var
I, C: Integer;
Begin
SetLength (Result, 0);
For C:=0 To Length (Bits)-1 Do
Begin
SetLength (Result, Length (Result)+Length (Bits[C]));
For I:=0 To Length (Bits[C])-1 Do
Result[Length (Result)-Length (Bits[C])+I]: =Bits[C][I];
End;
End;
Procedure CopyBits (VarDest:TBitString; Source: TBitString; NBits: Integer);
Var
I:Integer;
Begin
SetLength (Dest, NBits);
For I:=0 To NBits-1 Do
Dest[I]: =Source[I];
End;
Function BinToInt (S: TBitString): Integer;
Var
L, I: Integer;
Begin
Result:=0;
L:=Length (S);
IF L=0 Then
Raise EConvertError. Create ('Specified bit string is zero length');
For I:=L-1 DownTo 0 Do
Result:=Result+Ord (S[I])*Trunc (Power (2,L-I-1));
End;
Function IntToBin (N:Integer; Precision: Integer):TBitString;
Var
BitList:TList;
Bit:PBoolean;
Begin
SetLength (Result, 0);
BitList:=TList.Create;
While N>0 Do
Begin
New (Bit);
Bit^:=Boolean (N mod 2);
BitList.Insert (0,Bit);
N:=N div 2;
End;
While BitList. Count
Begin
New (Bit);
Bit^:=False;
BitList.Insert (0,Bit);
End;
For N:=0 To BitList. Count-1 Do
Begin
SetLength (Result, N+1);
Bit:=BitList.Items[N];
Result[N]:=Bit^;
Dispose (Bit);
End;
BitList.Free;
end;
Function AnsiStrToBin (S: String; Zeroes: Boolean):TBitString;
Var
Temp, B: TBitString;
L, I, J:Integer;
Begin
L:=0;
SetLength (Result, L);
SetLength (Temp, L);
SetLength (B, 0);
For I:=1 To Length (S) Do
Begin
B:=IntToBin (Ord (S[I]));
L:=L+Length (B);
SetLength (Temp, L);
For J:=0 To Length (B)-1 Do
Temp[Length (Temp)-Length (B)+J]: =B[J];
End;
Result:=Temp;
End;
Function BinToStr (Bits:TBitString):String;
Var
I, L: Integer;
Begin
Result:='';
L:=Length (Bits);
IF L=0 Then
Raise EConvertError. Create ('Specified bit string is zero length');
For I:=0 To L-1 Do
IF Bits[I] Then Result:=Result+'1'
Else Result:=Result+'0';
End;
Function StrToBin (S:String):TBitString;
Var
I:Integer;
Begin
SetLength (Result, 0);
For I:=1 To Length (S) Do
Begin
IF (S[I]<>'1')And (S[I]<>'0') Then
Raise EConvertError. Create (S+' is invalid binary string');
SetLength (Result, I);
Result[I-1]: =Boolean (StrToInt (S[I]));
End;
End;
Function BinToAnsiStr (Bits:TBitString):String;
Var
I:Integer;
B:TBitString;
Begin
Result:='';
SetLength (B, 8);
I:=0;
While I<=Length (Bits)-8 Do
Begin
CopyMemory (B, Ptr (Integer (Bits)+I), 8);
Result:=Result+Char (BinToInt (B));
Inc (I, 8);
End;
End;
Function GetPermutedKey (Key:TBitString):TBitString;
Var
I:Integer;
Begin
SetLength (Result, Length (DES_PC1));
For I:=0 To Length (DES_PC1)-1 Do
Result[I]: =Key[DES_PC1[I]-1];
End;
Function GetPermutedKey2(Key:TBitString):TBitString;
Var
I:Integer;
Begin
SetLength (Result, Length (DES_PC2));
For I:=0 To Length (DES_PC2)-1 Do
Result[I]: =Key[DES_PC2[I]-1];
End;
Function GetSplitKey (Key:TBitString):TSplitKey;
Function LeftShift (Key:TBitString; N: Integer):TBitString;
Var
I, J: Integer;
Temp:TBitString;
Begin
SetLength (Result, 28);
SetLength (Temp, 28);
For I:=0 To 27 Do
Temp[I]: =Key[I];
For J:=1 To N Do
Begin
For I:=1 To 27 Do
Result[I-1]: =Temp[I];
Result[27]:=Temp[0];
For I:=0 To 27 Do
Temp[I]: =Result[I];
End;
End;
Var
I, J: Integer;
Begin
For J:=1 To 16 Do
Begin
SetLength (Result[J]. C, 28);
SetLength (Result[J].D, 28);
End;
CopyBits (Result[0].C, Key, 28);
CopyBits (Result[0].D, TBitString (Integer (Key)+28), 28);
For I:=1 To 16 Do
Begin
Result[I]. C:=LeftShift (Result[I-1].C, DES_LSH[I-1]);
Result[I].D:=LeftShift (Result[I-1].D, DES_LSH[I-1]);
End;
End;
Function GetConcatKey (Key:TSplitKey):TConcatKey;
Var
I:Integer;
Temp:TBitString;
Begin
For I:=0 To 15 Do
Begin
SetLength (Result[I], 56);
Temp:=ConcatBits ([Key[I+1]. C, Key[I+1].D]);
Result[I]:=GetPermutedKey2(Temp);
End;
End;
Function GetIPKey (M:TBitString; ConcatKey: TConcatKey):TIPKey;
Var
I, J: Integer;
IP, F: TBitString;
Begin
For I:=0 To 16 Do
Begin
SetLength (Result[I]. L, 32);
SetLength (Result[I].R, 32);
End;
SetLength (IP, 64);
For I:=0 To Length (DES_IP)-1 Do
IP[I]: =M[DES_IP[I]-1];
For I:=0 To 31 Do
Result[0]. L[I]:=IP[I];
For I:=32 To 63 Do
Result[0]. R[I-32]:=IP[I];
For I:=1 To 16 Do
Begin
Result[I]. L:=Result[I-1].R;
F:=GetF (Result[I-1].R, ConcatKey[I-1]);
For J:=0 To 31 Do
Result[I]. R[J]:=Result[I-1].L[J] XOR F[J];
End;
End;
Function GetF (R, K: TBitString):TBitString;
Var
I, J: Integer;
S, E, KE, F, T:TBitString;
Begin
SetLength (E, 48);
For I:=0 To 47 Do
E[I]: =R[DES_E[I]-1];
SetLength (KE, 48);
For I:=0 To 47 Do
KE[I]: =K[I] XOR E[I];
SetLength (T, 6);
SetLength (F, 0);
SetLength (S, 4);
I:=0;
While I<48 Do
Begin
For J:=0 To 6 Do
T[J]: =KE[J+I];
S:=GetSBox (I div 6, T);
F:=ConcatBits ([F, S]);
I:=I+6;
End;
SetLength (Result, 32);
For I:=0 To 31 Do
Result[I]: =F[DES_P[I]-1];
End;
Function GetSBox (Index:Integer; T: TBitString):TBitString;
Var
Val, Row, Col: Integer;
Temp:TBitString;
Begin
SetLength (Result, 4);
SetLength (Temp, 2);
Temp[0]: =T[0];
Temp[1]:=T[5];
Row:=BinToInt (Temp);
SetLength (Temp, 4);
CopyBits (Temp, TBitString (@T[1]), 4);
Col:=BinToInt (Temp);
Val:=S_BOXES[Index, Row, Col];
SetLength (Result, 4);
Result:=IntToBin (Val, 4);
End;
Function GetReverseIP (RL:TBitString):TBitString;
Var
I:Integer;
Begin
SetLength (Result, 64);
For I:=0 To Length (DES_REVERSE_IP)-1 Do
Result[I]: =RL[DES_REVERSE_IP[I]-1];
End;
Procedure ReverseSubKeys (VarKeys:TConcatKey);
Var
I, L: Integer;
T:TBitString;
Begin
SetLength (T, 48);
L:=Length (Keys);
For I:=0 To (L-1)Div 2 Do
Begin
T:=Keys[I];
Keys[I]:=Keys[(L-I)-1];
Keys[(L-I)-1]:=T;
End;
End;
Function DESEncode (S, Key: String):TBitString;
Var
I:Integer;
K:TBitString;
M:TBitString;
RL:TBitString;
Kplus:TBitString;
SplitKey:TSplitKey;
ConcatKey:TConcatKey;
IPKey:TIPKey;
Begin
K:=AnsiStrToBin (Key);
Kplus:=GetPermutedKey (K);
SplitKey:=GetSplitKey (Kplus);
ConcatKey:=GetConcatKey (SplitKey);
M:=AnsiStrToBin (S);
IPKey:=GetIPKey (M, ConcatKey);
SetLength (RL, 64);
For I:=0 To 31 Do
Begin
RL[I]: =IPKey[16].R[I];
RL[I+32]:=IPKey[16].L[I];
End;
RL:=GetReverseIP (RL);
Result:=RL;
End;
Function DESDecode (S, Key: String):TBitString;
Var
I:Integer;
K:TBitString;
M:TBitString;
RL:TBitString;
Kplus:TBitString;
SplitKey:TSplitKey;
ConcatKey:TConcatKey;
IPKey:TIPKey;
Begin
K:=AnsiStrToBin (Key);
Kplus:=GetPermutedKey (K);
SplitKey:=GetSplitKey (Kplus);
ConcatKey:=GetConcatKey (SplitKey);
ReverseSubKeys (ConcatKey);
M:=AnsiStrToBin (S);
IPKey:=GetIPKey (M, ConcatKey);
SetLength (RL, 64);
For I:=0 To 31 Do
Begin
RL[I]: =IPKey[16].R[I];
RL[I+32]:=IPKey[16].L[I];
End;
RL:=GetReverseIP (RL);
Result:=RL;
End;
end.