Для этого один из американских ученых по фамилии Фейштель разработал алгоритм, в последствии который стал называться сетью Фейштеля. Он до сих пор используется в в качестве основного движка во многих алгортмах шифрования, да хотябы в том же MD5. Я рассмотрю основной движек, без навороченных навесок типа перемешивания и прочего.
Смысл его в чем:
У нас есть сообщение которое мы хотим зашифровать, например изречение Конфуция
"It does not matter how slowly you go so long as you do not stop." и ключ которым будем шифровать "konf".
1. Берем исходное сообщение и разбиваем его на куски по 32бита. Тоесть по 4 буквы.
2. Берем первые 2 части по 32 бита. В 16ричном выглядят они так "49742064" и "6F657320". Одну часть называем левой, вторую правой.
3. Теперь берем ключ konf. - 66 6E 6F 6B
4. Сдвигаем по кругу на 1 бит в право. Это так называемая функция F. Которая важна чтобы не получить закономерности.
5. Делаем XOR c левой части с ключем.
6. Делаем XOR результата предыдущей функции с с правой частью.
7. Меняем местами левую и правую часть - и снова переходим на первый пункт. Повторить до получения удовлетворения.
В картинках это выглядит следующим образом:
Вообщем ничего сложного в этом нет, а теперь посмотрим как это выглядит на ассембелере:
.386 .model flat, stdcall option casemap:none include \masm32\include\kernel32.inc includelib \masm32\lib\kernel32.lib code proto:DWORD, :DWORD, :DWORD, :DWORD, :DWORD ; прототип функции .data clear_text db "It does not matter how slowly you go so long as you do not stop." ; строка которую шифруем msg_l dd 40h ; длинна строки key dd "konf" ; ключ которым шифруем code_repeat dd 20h ; сколько раз будем повторять .data? code_text db 40h DUP (?) ; выходная строка .code start: invoke code, ADDR clear_text, ADDR key, ADDR code_text, code_repeat, msg_l ; шифруем строку shl code_repeat,1 ; умножим количество раундов в 2 раза для расшифровки invoke code, ADDR code_text, ADDR key, ADDR code_text, code_repeat, msg_l ; расшифровывем invoke ExitProcess,0 ; корректно выходим из программы code proc uses ebx edi edx ecx c_msg:DWORD, c_key:DWORD, c_ctext:DWORD, c_rep:DWORD, c_msg_l:DWORD local buf_l:DWORD ; буфер для левой части local buf_r:DWORD ; буфер для правой части mov edi, c_msg ; кладем в edi начало не зашифрованной строки mov edx, c_ctext ; кладем в edx куда будем писать зашифрованные данные next_part: mov eax, DWORD PTR [edi] ; читаем первые 4 байта сообщения mov buf_l, eax ; кладем их в левый буфер mov eax, DWORD PTR [edi+4] ; читаем следующие 4 байта mov buf_r, eax ; кладем в правую часть mov eax, c_key ; в eax помещаем адрес ключа mov eax, [eax] ; в eax помещаем сам ключ mov ecx, c_rep ; в ecx - сколько раз повторить процесс pov: mov ebx, DWORD PTR [buf_l] ; в ebx кладем левую часть ror eax, 1 ; сдвигаем на 1 бит в право ключ xor ebx, eax ; ксорим левую часть с ключем, это и есть функция F xor DWORD PTR [buf_r], ebx ; получившееся ксорим с правой частью push DWORD PTR [buf_l] ; кидаем в стек левую часть push DWORD PTR [buf_r] ; кидаем в стек правую часть pop DWORD PTR [buf_l] ; поднимаем данны из стека в левую часть pop DWORD PTR [buf_r] ; поднимаем данны из стека в правую часть loop pov ; повторить пока не закончится ecx mov eax, DWORD PTR [buf_l] ; поместить в eax левый буфер mov DWORD PTR [edx], eax ; записать в хранилище зашифрованного сообщения mov eax, DWORD PTR [buf_r] ; поместить в eax правый буфер mov DWORD PTR [edx+4], eax ; записать в хранилище зашифрованного сообщения add edi, 8h ; сдвинуть позицию в незашифрованной строке add edx, 8h ; сдвинуть позицию в зашифрованной строке sub c_msg_l,8h ; уменьшить количество символов в оставшейся строке на 8 cmp c_msg_l, 0 ; сравнить с нулем jz end_fest ; если равно нулю - закончить шифрование jmp next_part end_fest: mov eax, c_ctext Ret code EndP end start
Комментариев нет:
Отправить комментарий