Контакти

Операція XOR та найпростіше шифрування файлів. Поточні шифри Виключне або шифрування

Тому, коли executing exclusive OR, they will always be a zero value if the variables have the same values.

Піктограма XOR є те, що один і той самий функція може бути затверджено data and decrypt it. Це є простий спосіб з'єднання даних, який може бути скинуто блискавично, якщо він є великим простим текстом, або великим слівом слова. Але неймовірно, що це може бути використано для малого початкового захисту.

У контексті Qt, використання XOR не відрізняється від того, як програма була написана без використання Qt. Оцінка, якою є те, що відображається інформація для відображення від QString об'єктів, для прикладу, якщо текст був введений в QTextEdit.

To do this, write a program that contains:

  • QTextEdit, У якому текст буде введено, який буде введено.
  • QLineEdit, У якому натискання клавіші буде введено.
  • QPushButton, в клапті кнопки handler which, data encryption / decryption will be performed. Again, I note that the method will be used the same.

The program will look like this:

Project structure

Project is written using CMake, so structure will be as follows:

  • CMakeLists.txt
  • main.cpp
  • EncoderWidget.h
  • EncoderWidget.cpp

Encryption / decryption function

Для implementation encryption / decryption it is necessary:

  • The presence of a char array with the оригінал
  • Length of the array with the оригінал
  • Key as array char
  • Length of key
  • Andalso an array with output data.
const char * input; int inputLength; const char * key; int keyLength; char output; for (int i = 0; i< inputLength + 1; ++i) { output[i] = input[i] ^ key; }

Slot handler for encryption

Як тільки mentioned, для перегляду тексту, ви потребуєте докорінно extract data from the input fields. Для цього, вам потрібно переписати текст у вигляді типу QString string в QByteArray від якого вичерпувати дані в формі const char *. Andalso таке length of this data.

There is one point. Цей з QString в QByteArray is translated using toLatin1 () метод, який буде результат в межах до ASCII table, який буде спрямований на data corruption якщо текст був написаний в Cyrillic. Це є, цей крок до об'яви буде відповідати, якщо тільки символи від ASCII table є використані, для прикладу, для повідомлення і повідомлення.

Void EncoderWidget::encodeDecode() ( const char* input = m_textEdit->toPlainText().toLatin1().data(); int inputLength = m_textEdit->toPlainText().toLatin1().length(); const char* = m_keyLineEdit->text().toLatin1().data();int keyLength = m_keyLineEdit->text().toLatin1().length();< inputLength + 1; ++i) { output[i] = input[i] ^ key; } m_textEdit->setText(QString::fromLatin1(output, inputLength)); )

Відповідно до визначення, двомісна однобітова операція "що виключає АБО" виконує дії, показані в табл. 19.1.

Таблиця 19.1. Виключне АБО(ХОЯ)

Вхід 1

Вхід 2

Вихід

Її можна назвати " операція розбіжності " - на виході логічна одиниця тоді, коли значення на входах не збігаються. З цього визначення легко вивести основну властивість цієї операції: будучи застосована двічі до того самого операнду, вона нічого не змінить, незалежно від значення другого операнда, аби він не змінювався. Цим, зокрема, широко користуються в комп'ютерній графіці: якщо прикласти через операцію XOR до фону маску, що складається з усіх одиниць (чисто білу), то зображення на цьому місці інвертується за кольорами, при повторенні тієї ж дії все відновлюється у незмінному вигляді (так , зокрема, зручно проводити виділення (див. розділ 10).

Ця властивість і покладено в основу практично всіх алгоритмів шифрування, які іноді можуть бути дуже навороченими, але ми не заглиблюватимемося в це питання, а просто спробуємо застосувати цей метод у його первісному вигляді. Для перевірки можна використовувати таку просту процедуру. Нехай ми хочемо зашифрувати текстовий файл. Так як ми дипломатичні секрети не ховаємо, то нам вистачить звичайної в таких випадках довжини ключа в 8 символів (64 біти) - цього достатньо, щоб зробити злом шифру методом перебору на звичайному персональному комп'ютері завданням "з нальоту" не вирішуваним. Наприклад ключем буде служити слово "yvre- vich". Створювати такі ключі зі свого прізвища на практиці ні в якому разі не можна, не можна також вживати будь-які словникові слова, дати, номери телефонів-ще Вернам показав, що для ефективного шифрування ключ повинен бути суворо випадковим, тут це робиться тільки як приклад ( про те, як можна задавати випадковий ключ, ми поговоримо пізніше).

Створимо новий проект (у папці Glaval9\l) під назвою ProbaCrypt, і розмістимо в тій же папці файл на пробу. Я взяв текст пісні "Одного разу світ прогнеться під нас" з репертуару А. Макаревича (в текстовому форматі, файл mashinavremeni.txt) з акордами, тому що досить складне форматування цього тексту зробить приклад наочніше 3 .

Помістимо на форму компонент Memo, діалог OpenDialog та дві кнопки Butt ел. У заголовку Buttoni напишемо Зашифрувати, у заголовку Buttoni - Розшифрувати. Оголосимо такі змінні:

Forml: TForml; fname,key:string; fi, fo: file of byte; i:integer; xb:byte;

При створенні форми ініціалізуємо ключ та діалог:

procedure TForml.FormCreate(Sender: TObject); begin key:='yvrevich";

OpenDialogl.InitialDir:=ExtractFiieDir(Application.ExeName); end;

В обробнику натискання кнопки Buttonl напишемо наступний довгий код:

procedure TForml.ButtonlClick(Sender: TObject); begin /Зашифрувати/ OpenDialogl. FileName:?= 11;(очистимо) OpenDialogl.Filter:=”; if OpenDialogl.Execute then fname:=OpenDialogl.FileName else exit; assignfile(fi,fname);(задали вихідний файлI try

reset(fi); (відкрили вихідний) except

exit; (якщоне відкривається – на вихід) end;

assignfile(fo,ChangeFileExt(fname, 1 .sec')) ; rewrite(fo);

read(fi, xb); (прочитай перший байт)

Forml.Caption:='ProbaCrypt: '+ExtractFileName(fname);

/назвафайлу – уЗаголовок) Memol.Lines.Clear; Memol.Lines.Add('Зачекайте...');

Application.ProcessMessages; Memol.Lines.Clear; while not eof(fi) do begin

xb:=xb xor ord(key[i]);(шифруємо)

Memol.Text:=Kemol.Text+chi(xb);(Виводимо в Memo)

write (fo, xb); (записуємо у файл)

read(fi, xb); (якщо кінець файлу – виходимо) except break; end; end; end;

closefile(fi);

erase(fi); (Знищуємо вихідник)

closefile(fo);

(зашифрували) end;

Тут ми складаємо через операцію XOR кожен байт вихідного файлу з байтами ключа по черзі; коли ключ закінчується, ми знову починаємо з першого символу. Результати пишемо у файл із розширенням sec (від "security") і виводимо в Memoi. В точності ту ж операцію ми робимо при розшифровці, тільки вже із зашифрованим файлом, внаслідок чого вихідний файл відновлюється повністю:

procedure TForml.Buttor.2Click(Sender: TObject); begin(Pa оцифрувати j OpenDialogl.FileName:=”;(очистимо/ OpenDialogl.Filter: = '№4>poBaHHbie файли| *.sec'; if OpenDialogl.Execute then fname:OpenDialogl.FileName else exit; assignfile(fi, fname);(відчинили шифрований) try

reset(fi); except exit; end;

assignfile(fo,ChangeFileExt(fname, '.txt')); rewrite(fo);(перезаписуємо старий) read(fi, xb);

Forml.Caption:='ProbaCrypt: '+ExtractFileNajne (fname) ;

! Назва файлу - в заголовокj

Memol.Lines.Clear;

Memol.Lines.Add(1 Зачекайте…’);

Application.ProcessMessages;(щоб побачити попередження) Memol.Lines.Clear; while not eof(fi) do begin /асе беззмін, як вище) for i:=l до кінця(key) do begin

xb:=xb xor ord(keyU));

Memol.Text:=Memol.Text+chr(xb);

write (fo, xb);

read(fi, xb); except break; end; end; end;

closefile(fi); closefile(fo);(pa сшифрували) end;

Зверніть увагу, що я зашифрований файл не знищую - в принципі операцію шифрування можна робити скільки завгодно раз над вже зашифрованим текстом, для його розшифровки доведеться також повторити все стільки ж разів, і цей прийом часто застосовують в "офіційних" алгоритмах шифрування (тільки в даному Якщо доведеться зашифрований файл перейменувати вручну або кілька модифікувати програму, в наявному вигляді вона вам не дозволить відкрити один і той же файл і для розшифровування і для шифрування). Звичайно, процедуру шифрування можна застосовувати до будь-яких файлів, не тільки текстових.

Є тонкий момент, пов'язаний зі знищенням оригіналу - як відомо, при знищенні дискового файлу він не стирається, подібно до музичного запису на магнітній стрічці, а просто в заголовних структурах FAT місце, яке займає, позначається, як вільне (приблизно також відбувається це і в NTFS). Саме з цією особливістю була пов'язана робота DOS-програми Unerase (якщо хтось пам'ятає, що це таке). Тому, якщо ви навіть видалите файл з Кошика (видалений з нашої програми файл у Кошик, правда, отже не потрапляє), на диску залишиться його зміст доти, доки туди не буде записано щось ще. Тому для особливо параноїдальних особистостей просунуті програми шифрування пропонують опцію, коли файли після стирання знищуються гарантовано- на їх місце записуються нулі. У нашому випадку для цього в принципі не закриваючи файл, заповнити його байтами з нульовим значенням (або будь-яким іншим, але не збільшуючи і не зменшуючи розмір файлу), записати це на диск (закривши файл), а потім вже його знищувати. Правда, у Windows стовідсоткової гарантії, що він запишеться в точності на те саме місце, я дати не можу, тому краще в таких випадках застосовувати все ж таки "офіційні" програми, які, до речі, знищують сліди вихідника не тільки в тій області диска, де він зберігався, але і SWAP-файл Windows, якщо вони там залишилися.

Що стосується генерації випадкових ключів, то ось один із способів. I Вказувати реалізацію повністю не буду, оскільки вона проста. Генератор псевдовипадкових чисел в Delphi (і не тільки в Delphi) влаштований наступним чином: через змінну RandSeea задається початкове число генератора (але замовчуванням воно дорівнює 0). Тоді функція Random при послідовному зверненні до неї завжди повертатиме один і той же набір чисел, незалежно від того, в якій програмі і коли ми її використовуємо. Звідси й спосіб ви встановлюєте в програмі такий генератор і на його основі генеруєте ключ, наприклад. ось так можна згенерувати випадковий 16-байтний (128-бітний) набір символів, який залежатиме лише від величини початкового зміщення генератора init:

:

init:integer; st:string;

st:=”;

RandSeed:=init;(Початкове зміщення) while length(st)<16 do begin xb:=Random(255); if xb>31 then st:=st+chr(xb); end;

При цьому ви передаєте вашому кореспондентові не сам ключ, а величину ir.j. У нього буде згенерований за ідентичною процедурою точно той же ключ. Можна вигадати, зрозуміло, і хитріші механізми реалізації цього методу.

Хочу помітити, щоб не затемнювати суть справи, раніше в програмі я використав традиційне читання побайтів з дискового файлу. Різко прискорити процедуру можна за допомогою одного з механізмів попереднього читання файлу в пам'ять-file mapping, як у розділі 14, потокового читання або будь-якого іншого способу організації динамічних масивів у пам'яті (див. розділ 21). У прикладі з використанням стеганографії, якого ми зараз приступимо, частково положення буде виправлено.

Поточний шифр виконує операції над бітами або символами (наприклад, 8-, 16- або 32-бітовими). Поточний шифр перетворює один і той же символ відкритого тексту в різні символи шифртексту, наприклад, залежно від того, скільки і яких символів було оброблено раніше.

Xor-шифрування

Багато потокових шифрах зашифровування виробляється в такий спосіб. Генератор псевдовипадкових чисел видає послідовність бітів (гаму). Ця гама накладається на відкритий текст за допомогою побітової операції XOR. В результаті виходить шифртекст. Для розшифровування необхідно виконати в точності ту ж процедуру, тільки накласти гаму, отриману з використанням ідентичного генератора з таким самим початковим станом, на шифртекст.

Розглянемо ідею цього найпростішого способу. Як відомо з булевої алгебри, операція логічного складання «⊕» за модулем 2 (або логічного виключає АБО – XOR, eXclusive OR) має наступну семантику:

Таблиця істинності для XOR:

x i ⊕ y i

x = 10011 101

y= 01001 100

z= 11010 001

Тобто операція z= xyнасправді порозрядна (побітова – результат залежить від сусідніх бітів). Якщо тільки один із відповідних бітів дорівнює 1, то результат 1. А якщо обидва 0 або обидва 1, то результат 0. Якщо уважно подивитися на результат застосування XORдо двох двійкових числах, можна помітити, що ми можемо відновити одне з доданків за допомогою другого: x= zyабо y= zx.

Звідси можна зробити такі висновки: знаючи число yта застосовуючи XORдо x, ми отримаємо z. Потім, ми, знову ж таки використовуючи y, отримаємо з zназад число x. Таким чином ми можемо перетворити послідовність чисел ( x) iу послідовність ( z) i. Тепер ми можемо назвати число yкодуючим (або шифруючим) ключем. Якщо людина не знає ключа, то вона не зможе відновити вихідну послідовність чисел ( x) i. Але якщо ( x) iє байтовим уявленням букв тексту, то досвідчений користувач зможе розкрити зашифрований текст. Оскільки кожна літера буде представлена ​​в шифротексті одним і тим самим кодом z, то скориставшись частотним словником зломщик зможе обчислити шифруючий ключ yякщо у нього буде в розпорядженні досить довгий шифротекст.

У світлі останніх міркувань приходимо до думки, що безпосередньо кодувати простий текст не можна. По-перше, число, що представляє прогалину, як і раніше, розділяти слова і в шифротексті. Виділивши це те, що часто зустрічається одне і те ж число, користувач здогадається, що це закодований пробіл. По-друге, короткі прийменники, що часто зустрічаються, і союзи також допоможуть зломщику у визначенні ключа. Тому найефективнішим способом є використання довгого ключа, що покриває кілька літер, а краще за довжину самого повідомлення. Так, якщо ми кодуємо досить довге повідомлення (не менше 5-10 пропозицій) за допомогою випадкового ключа такої самої довжини, таке повідомлення дуже складно розшифрувати. Ще більш високих результатів надійності можна досягти, якщо перед шифруванням зробити, наприклад, стиснення тексту будь-яким архіватором. Плюс до того ж, якщо повідомлення має малу довжину, можна додати на початок і в кінці повідомлення випадкові послідовності символів.

Таким чином, стійкість алгоритму залежить виключно від характеристик гами, що видається генератором. Якщо гама складається з одних нулів (вироджений випадок), дані при шифруванні взагалі не змінюються. Якщо гама має короткий період (наприклад, 32 біти), то шифрування зводиться до операції XOR з 32-бітовою константою. Якщо ж гама являє собою випадковий набір бітів, що не підкоряється ніякої закономірності, виходить аналог одноразового блокнота шифровального, який забезпечує абсолютний захист. Зрозуміло, детермінований алгоритм, що використовується в генераторі гами, не може видавати випадкову послідовність. Якщо послідовність не вдасться повторити, то не вдасться розшифрувати повідомлення.

Якщо два повідомлення були зашифровані з використанням однієї і тієї ж гами і для одного з повідомлень (довшого) вдалося якимось чином отримати відкритий текст, легко отримати відкритий текст і для іншого повідомлення. Застосувавши операцію XOR До відкритого тексту та шифртексту першого повідомлення ми отримаємо фрагмент гами. А наклавши гаму на шифртекст другого повідомлення, ми матимемо його відкритий текст. Саме тому не можна допускати, щоб та сама гамма використовувалася при шифруванні двох різних потоків або повідомлень.

Якщо гамма генерується незалежно від вмісту повідомлення, такий потоковий алгоритм називається синхронним. Як правило, у синхронних потокових шифрах ключ шифрування використовується для встановлення початкового внутрішнього стану генератора гами.



Сподобалась стаття? Поділіться їй