Шифровка данных заменой

 Предупреждаю сразу: изложенный в данной статье алгоритм не претендует на звание самого лучшего, это всего лишь очередная вариация на тему шифрования данных, не исключено что он уже был придуман кем-то раньше.

  Итак, приступим! Первое что приходит в голову при шифровании данных это простая замена символов согласно некоторой таблице соответствия, а саму таблицу соответствия можно генерировать случайным образом. Недостаток этого метода очевиден: при относительно длинном размере зашифрованных данных, можно найти соответствие между исходными символами и замененными.
  Итак, простая замена символов не подходит. Вспоминается старый метод шифрования данных, которым наверно пользовались наши прадедушки. Например, есть два человека, которые хотят вести конфиденциальную переписку. У них есть две одинаковые книги. Каждый символ в передаваемом сообщении кодируется следующим образом: номер страницы, номер строки и номер символа в строке.
Таким образом, одна и та же буква может быть заменена несколькими разными цифровыми последовательностями. При правильном использовании такого метода шифрования возможность расшифровки передаваемых данных без искомой книги почти невозможна.
  А теперь вспомним первый алгоритм и сделаем выводы: таблиц соответствия должно быть несколько (не несколько, а много!). А заменять один символ мы будем не одним символом, а двумя: номером таблицы соответствия и номером заменяемого символа в таблице соответствия.
  Теперь перенесём алгоритм в проблематику информатики. Символом сообщения у нас будет байт. Байт может принимать значение 0-255, и заменён он может быть любым значением от нуля до 255. Таблицу соответствия будем называть кодовой страницей. Кодовых страниц у нас будет 256. Набор из 256 кодовых страниц будем называть книгой кодов. В результате при шифровке данных один байт исходных данных будет заменяться двумя: номером кодовой страницы и байтом соответствия на этой кодовой странице. При шифровке кодовая страница будет выбираться случайным образом, таким образом, каждый раз при шифровке один и тех же данных мы будем получать разные данные.
  Кодовая страница будет представлять собой массив из 256 байт. Чтобы получить байт-замену необходимо найти заменяемый байт в этом массиве. Индекс заменяемого байта и будет байтом-заменой. Например, у нас есть байт со значением 125, в кодовой странице он находится на 239 месте, следовательно, байт со значением 125 будет заменён байтом со значением 239. Поиск символа в 256 байтовом массиве это не очень быстрая операция, но зато операция расшифровки будет иметь довольно-таки высокую скорость.
  Как видно при использовании данного алгоритма размер данных увеличивается в два раза. При обеспечении конфиденциальности данных этот фактор не является решающим.
  Теория изложена, осталось написать программу, которая производит шифровку данных согласно вышеизложенному алгоритму.
  Для начала напишем функции, которые случайным образом будут генерировать кодовые страницы и книгу кодов.
  Функция CreateCodePage генерирует случайным образом кодовую страницу. Функция принимает один параметр – указатель на буфер.

<code class=" cpp"><br /><span class="keyword">void</span> CreateCodePage(BYTE *Page)<br />{<br />    <span class="keyword">for</span> (<span class="keyword">int</span> i=<span class="number">1</span>;i<<span class="number">256</span>;i++)<br />    {<br />        <span class="keyword">int</span> pos = rand()%<span class="number">256</span>;<br />        <span class="keyword">if</span> (Page[pos])<br />        {<br />            <span class="keyword">while</span> ((Page[pos]) and (pos<<span class="number">255</span>) pos++;<br />            <span class="keyword">if</span> (Page[pos])<br />            {<br />                pos=<span class="number">0</span>;<br />                <span class="keyword">while</span> ((Page[pos]) and (pos<<span class="number">255</span>) pos++;<br />            }<br />            Page[pos] = i;<br />        } <span class="keyword">else</span><br />        Page[pos]=i;<br />    }<br />}</code>

Функция CreateCodeBookInBuffer создаёт 256 кодовых страниц, которые располагаются последовательно в буфере, указатель на который передаётся через единственный параметр.

<code class=" cpp"><br /><span class="keyword">void</span> CreateCodeBookInBuffer(BYTE *Buffer)<br />{<br />    <span class="keyword">for</span> (<span class="keyword">int</span> i=<span class="number">0</span>;i<<span class="number">256</span>;i++)<br />    {<br />        CreateCodePage(Buffer+(i<<<span class="number">8</span>);<br />    }<br />}</code>

В данной функции непосвящённого программиста может сбить с толку битовый сдвиг влево на 8 бит. На месте битового сдвига должна стоять операция умножения на 256. Битовый сдвиг влево на 1 бит равносильно умножения на 2, на 2 бита равносильно умножению на 4, а сдвиг на 8 бит равносилен умножения на 256. Причина использования сдвига очень проста: операция битового сдвига производится быстрее, чем операция умножения, это знает любой, кто имеет опыт программирования на ассемблере.
  Функция CreateCodeBook создаёт книгу кодов и сохраняет её в файл.

<code class=" cpp"><br /><span class="keyword">bool</span> CreateCodeBook(LPCTSTR FileName)<br />{<br />    BYTE* MemCodeBook = (BYTE*)VirtualAlloc(<span class="number">0</span>, <span class="number">0x10000</span>, MEM_COMMIT + MEM_RESERVE, PAGE_READWRITE);<br />    CreateCodeBookInBuffer(MemCodeBook);<br /><br />    HANDLE FH = CreateFile(FileName, GENERIC_WRITE, FILE_SHARE_READ, <span class="number">0</span>, CREATE_ALWAYS,<span class="number">0</span>,<span class="number">0</span>;<br />    <span class="keyword">if</span> (FH==INVALID_HANDLE_VALUE) <span class="keyword">return</span> <span class="keyword">false</span>;<br />    DWORD Writed;<br />    WriteFile(FH,(<span class="keyword">void</span>*)MemCodeBook,<span class="number">0x10000</span>,&Writed,<span class="number">0</span>;<br />    CloseHandle(FH);<br />    VirtualFree(MemCodeBook,<span class="number">0</span>,MEM_RELEASE);<br />    <span class="keyword">return</span> (Writed==<span class="number">0x10000</span>;<br />}</code>

  Итак, книгу кодов мы создали теперь надо написать функции, которые производят шифровку и расшифровку данных.

<code><br />void CryptData(BYTE* CodeBook, BYTE *SourceBuff, int BuffSize, BYTE *DestBuff)<br />{<br />    BYTE CB, CCB;<br />    int CP;<br />    for(int i=0;i<BuffSize;i++)<br />    {<br />        CB = SourceBuff<em></em>;<br />        CP = rand()%256;<br />        CCB =GetBytePos(CodeBook+(CP<<8),CB);<br />        DestBuff<em></em>=CP;<br />        DestBuff[(i<<1)+1]=CCB;<br />    }<br />}</code>

Функция элементарна: мы берём байт из исходных данных, генерируем случайным образом номер кодовой страницы, получаем индекс исходного байта на выбранной кодовой странице и записываем в результирующий буфер номер кодовой страницы и байт-замену на этой кодовой странице. Функция GetBytePos производит поиск байт в указанном буфере.
  Осталось написать функцию расшифровки, она ещё проще:

<code><br />void DeCryptData(BYTE* CodeBook, BYTE *SourceBuff, BYTE *DestBuff, int BuffSize)<br />{<br />    BYTE CB, CCB;<br />    int CP;<br />    for(int i=0;i<BuffSize;i++)<br />    {<br />        CP=SourceBuff<em></em>;<br />        CCB=SourceBuff[(i<<1)+1];<br />        CB = CodeBook[(CP<<8)+CCB];<br />        DestBuff<em></em>=CB;<br />    }<br />}</code>

Здесь тоже всё очень просто: извлекается два байта из исходных (зашифрованных) данных, первый байт это номер кодовой страницы второй это индекс на этой кодовой странице, в результирующий буфер заносится байт, находящийся на указанной кодовой странице по указанному индексу.
  Следующим шагом будет написание функций производящих шифрование файлов. Код функции, осуществляющий шифрование файлов тривиальный: считывается в память книга кодов, считывается в память исходный файл, зашифрованный данные записываются в результирующий файл.

<code class=" cpp"><br /><span class="keyword">bool</span> CryptFile(LPCTSTR SourceFile, LPCTSTR DestFile, LPCTSTR CodeBookFile)<br />{<br />    HANDLE CBFH = CreateFile(CodeBookFile, GENERIC_READ, FILE_SHARE_READ,<span class="number">0</span>,OPEN_EXISTING,<span class="number">0</span>,<span class="number">0</span>;<br />    <span class="keyword">if</span> (CBFH==INVALID_HANDLE_VALUE) <span class="keyword">return</span> <span class="keyword">false</span>;<br />    <span class="keyword">int</span> CBFS = GetFileSize(CBFH,<span class="number">0</span>;<br />    <span class="keyword">if</span> (CBFS!=<span class="number">0x10000</span><br />    {<br />        CloseHandle(CBFH);<br />        <span class="keyword">return</span> <span class="keyword">false</span>;<br />    }<br /><br />    HANDLE SFH = CreateFile(SourceFile, GENERIC_READ, FILE_SHARE_READ,<span class="number">0</span>,OPEN_EXISTING,<span class="number">0</span>,<span class="number">0</span>;<br />    <span class="keyword">if</span> (SFH==INVALID_HANDLE_VALUE) <span class="keyword">return</span> <span class="keyword">false</span>;<br />    HANDLE DFH = CreateFile(DestFile, GENERIC_WRITE, FILE_SHARE_READ,<span class="number">0</span>,CREATE_ALWAYS,<span class="number">0</span>,<span class="number">0</span>;<br />    <span class="keyword">if</span> (DFH==INVALID_HANDLE_VALUE) <span class="keyword">return</span> <span class="keyword">false</span>;<br /><br />    BYTE* SourceBuff = (BYTE*)VirtualAlloc(<span class="number">0</span>,BufferSize,MEM_COMMIT+MEM_RESERVE,PAGE_READWRITE);<br />    BYTE* DestBuff = (BYTE*)VirtualAlloc(<span class="number">0</span>,BufferSize*<span class="number">2</span>,MEM_COMMIT+MEM_RESERVE,PAGE_READWRITE);<br />    BYTE* CodeBook = (BYTE*)VirtualAlloc(<span class="number">0</span>,<span class="number">0x10000</span>,MEM_COMMIT+MEM_RESERVE,PAGE_READWRITE);<br /><br />    DWORD Readed = <span class="number">0</span>;<br />    ReadFile(CBFH,CodeBook,<span class="number">0x10000</span>,&Readed,<span class="number">0</span>;<br />    CloseHandle(CBFH);<br /><br />    DWORD Writed = <span class="number">0</span>;<br />    <span class="keyword">do</span><br />    {<br />        ReadFile(SFH,SourceBuff,BufferSize,&Readed,<span class="number">0</span>;<br />        CryptData(CodeBook,SourceBuff,Readed,DestBuff);<br />        WriteFile(DFH,DestBuff,Readed*<span class="number">2</span>,&Writed,<span class="number">0</span>;<br /><br />    }<br />    <span class="keyword">while</span> (Readed==BufferSize);<br /><br />    CloseHandle(SFH);<br />    CloseHandle(DFH);<br /><br />    VirtualFree(SourceBuff,<span class="number">0</span>,MEM_RELEASE);<br />    VirtualFree(DestBuff,<span class="number">0</span>,MEM_RELEASE);<br />    VirtualFree(CodeBook,<span class="number">0</span>,MEM_RELEASE);<br /><br />    <span class="keyword">return</span> <span class="keyword">true</span>;<br />}</code>

Следует подметить, что шифровка файла производится по порциям размером в 1 МБ, это обусловлено тем что при шифровке файлов большого размера (более 600 МБ), реальна ситуация нехватки виртуальной памяти. Функция расшифровки файлов аналогична вышеприведённой, приводить её здесь не имеет никакого смысла.
  Все вышеприведённые функции и вынесены в заголовочный файл (RDC.h), который вы можете подключить в своём проекте на С++. Также мною была создана DLL содержащая функции из RDC.h. Созданную DLL можно использовать в программах написанных на других языках. В качестве примера я написал программу на Delphi, которая производит шифрование файлов с использованием функций из RDC.DLL.
  Исходники RDC.DLL и программы производящей шифрование файлов с использованием RDC.DLL находятся в архиве, прилагающемся к данной статье.

Скачать исходники
1. Исходники RDC.DLL на С++ (CodeBlocks+MinGW)
2. Исходники программы использующей RDC.DLL (Delphi 7)

Обсудить у себя 1
Комментарии (0)
Чтобы комментировать надо зарегистрироваться или если вы уже регистрировались войти в свой аккаунт.

Войти через социальные сети:

Marina
Marina
Была на сайте никогда
тел: +380665011134
Читателей: 7 Опыт: 0 Карма: 1
Я в клубах
Фотографируем Пользователь клуба
Inks under the skin Пользователь клуба
все 1 Мои друзья