Модуль перетасовування алфавіту призначений для додаткового захисту секретної інформації, що передається по каналу зв'язку. Хоча застосовуване нами в Extra Systems Cypher Net потокове шифрування RC4 і не має в нашій реалізації жодних уразливостей, проте зберігається теоретична можливість перебору ключів з подальшим лексичним аналізом спроб розшифровування інформації, що передається. Мова, звичайно, не йдеться про ті можливості, які людство має сьогодні. Для сучасних систем час перебору ключів RC4 у разі на багато порядків перевищує час існування Всесвіту. Йдеться про ті гіпотетичні можливості, які можуть з'явитися в майбутньому. Маючи намір застрахуватися від будь-яких можливих варіантів, ми і додали до Extra Systems Cypher Net даний модуль перетасовування алфавіту, який унеможливлює лексичний аналіз спроб розшифровки, і таким чином позбавляє зловмисника в принципі будь-якої можливості зламати цю систему шифрованої.
Суть цього методу полягає в тому, що коди 256 символів (кількість варіантів для одного байта з восьми біт) цілком випадковим чином переміщуються в таблиці, так що текст будь-якою мовою перетворюється на повну абракадабру, що складається з друкованих та недрукованих символів, перемішаних між собою абсолютно непередбачуваним чином. В результаті цього метод злому шляхом повного перебору паролів шифрування, суть якого полягає в пошуку варіантів, коли шифротекст перетворюється на набір деяких друкованих символів, повністю втрачає свою спроможність, оскільки правильний пароль, при нашому підході, який тут описується, перетворюється, як уже було зазначено, в абракадабру, яку ніяк не можна.
Таким чином, зломщик Extra Systems Cypher Net не може підбирати пароль, орієнтуючись на те, щоб отримати якийсь осмислений текст.
Спочатку в системі створюється таблиця, яка відповідає тотожному перетворенню (тобто вона нічого не робить - не змінює інформацію про кодування символів). Це робить модуль shuffle_init:
int main(void) { int i,file_handle; unsigned char data[256]; for (i=0; i<256; i++) data[i] = i; file_handle = creat("shuffle.encrypt", S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); write(file_handle, data, sizeof(data)); close(file_handle); return 0; }
Потім інформація в цій таблиці випадково тасується (цю процедуру можна, і навіть потрібно, робити не один раз). Цим займається модуль shuffle_randomize:
int main(void) { unsigned char src, dst; unsigned char shuffle_encrypt_data[256]; unsigned char random_src[256], random_dst[256]; int i, file_handle; file_handle = open("shuffle.encrypt", O_RDONLY); read(file_handle, shuffle_encrypt_data, sizeof(shuffle_encrypt_data)); close(file_handle); fill_random_buffer(random_src, sizeof(random_src)); fill_random_buffer(random_dst, sizeof(random_dst)); for(i = 0; i < 256; i++) { src = shuffle_encrypt_data[random_src[i]]; dst = shuffle_encrypt_data[random_dst[i]]; shuffle_encrypt_data[random_src[i]] = dst; shuffle_encrypt_data[random_dst[i]] = src; } file_handle = creat("shuffle.encrypt", S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); write(file_handle, shuffle_encrypt_data, sizeof(shuffle_encrypt_data)); close(file_handle); return 0; }
Застосуванням цього ключа в системі Extra Systems Cypher Net займається модуль shuffle (зверніть увагу, що shuffle_decrypt_data створюється "на льоту" на базі shuffle_encrypt_data відразу після її завантаження - цей факт автоматично забезпечує повну узгодженість алгоритмів кодування та декодування інформації, що передається), код якого мовою C виглядає так:
unsigned char shuffle_encrypt_data[256], shuffle_decrypt_data[256]; int load_shuffle_data(void) { unsigned char src; int i, file_handle; if((file_handle = open("shuffle.encrypt", O_RDONLY)) == -1) return 0; read(file_handle, shuffle_encrypt_data, sizeof(shuffle_encrypt_data)); close(file_handle); for(i = 0; i < 256; i++) { src = shuffle_encrypt_data[i]; shuffle_decrypt_data[src] = i; } return 1; } void shuffle_rotate_l(unsigned char *buffer_ptr, int buffer_len) { int i; unsigned char x; if (!buffer_len) return; x = buffer_ptr[0]; for(i = 0; i < (buffer_len - 1); i++) buffer_ptr[i] = (buffer_ptr[i] << 4) | (buffer_ptr[i + 1] >> 4); buffer_ptr[buffer_len - 1] = (buffer_ptr[buffer_len - 1] << 4) | (x >> 4); } void shuffle_rotate_r(unsigned char *buffer_ptr, int buffer_len) { int i; unsigned char x; if (!buffer_len) return; x = buffer_ptr[buffer_len - 1]; for(i = (buffer_len - 1); i > 0; i--) buffer_ptr[i] = (buffer_ptr[i] >> 4) | (buffer_ptr[i - 1] << 4); buffer_ptr[0] = (buffer_ptr[0] >> 4) | (x << 4); } void shuffle_twist(unsigned char *buffer_ptr, int buffer_len) { int i; unsigned char x, y; if (buffer_len < 2) return; for(i = 1; i < buffer_len; i++) { x = buffer_ptr[i - 1]; y = buffer_ptr[i]; buffer_ptr[i - 1] = (x & 0xF0) | (y >> 4); buffer_ptr[i] = (y & 0xF) | (x << 4); } } void shuffle_buffer(unsigned char *buffer_ptr, int buffer_len, unsigned char *shuffle_data) { short counter; for(counter = 0; counter < buffer_len; counter++) buffer_ptr[counter] = shuffle_data[buffer_ptr[counter]]; } void shuffle_swap_l(unsigned char *buffer_ptr, int buffer_len, unsigned char swap_old) { int i; unsigned char x, y, swap_new; if (buffer_len < 2) return; swap_new = ~swap_old; for(i = 1; i < buffer_len; i++) { x = buffer_ptr[i - 1]; y = buffer_ptr[i]; buffer_ptr[i - 1] = (x & swap_old) | (y & swap_new); buffer_ptr[i] = (y & swap_old) | (x & swap_new); } } void shuffle_swap_r(unsigned char *buffer_ptr, int buffer_len, unsigned char swap_old) { int i; unsigned char x, y, swap_new; if (buffer_len < 2) return; swap_new = ~swap_old; for(i = (buffer_len - 1); i > 0; i--) { x = buffer_ptr[i - 1]; y = buffer_ptr[i]; buffer_ptr[i - 1] = (x & swap_old) | (y & swap_new); buffer_ptr[i] = (y & swap_old) | (x & swap_new); } } void shuffle_encrypt_buffer(unsigned char *buffer_ptr, int buffer_len) { shuffle_buffer(buffer_ptr, buffer_len, shuffle_encrypt_data); shuffle_swap_l(buffer_ptr, buffer_len, SHUFFLE_SWAP_STEP_1); shuffle_buffer(buffer_ptr, buffer_len, shuffle_encrypt_data); shuffle_rotate_l(buffer_ptr, buffer_len); shuffle_buffer(buffer_ptr, buffer_len, shuffle_encrypt_data); shuffle_twist(buffer_ptr, buffer_len); shuffle_buffer(buffer_ptr, buffer_len, shuffle_encrypt_data); shuffle_swap_l(buffer_ptr, buffer_len, SHUFFLE_SWAP_STEP_2); shuffle_buffer(buffer_ptr, buffer_len, shuffle_encrypt_data); } void shuffle_decrypt_buffer(unsigned char *buffer_ptr, int buffer_len) { shuffle_buffer(buffer_ptr, buffer_len, shuffle_decrypt_data); shuffle_swap_r(buffer_ptr, buffer_len, SHUFFLE_SWAP_STEP_2); shuffle_buffer(buffer_ptr, buffer_len, shuffle_decrypt_data); shuffle_twist(buffer_ptr, buffer_len); shuffle_buffer(buffer_ptr, buffer_len, shuffle_decrypt_data); shuffle_rotate_r(buffer_ptr, buffer_len); shuffle_buffer(buffer_ptr, buffer_len, shuffle_decrypt_data); shuffle_swap_r(buffer_ptr, buffer_len, SHUFFLE_SWAP_STEP_1); shuffle_buffer(buffer_ptr, buffer_len, shuffle_decrypt_data); }
Завдяки цій хаотичній перестановці букв зловмисник повністю позбавляється можливості аналізувати текст, який виходить у нього при спробах розшифровки за методом перебору ключів. Файл "shuffle.encrypt" формується для кожного клієнта свій, і крім того, кожен клієнт, за бажання, забезпечується програмою shuffle_randomize, за допомогою якої він сам може зробити будь-яку кількість додаткових перестановок у цьому своєму ключовому файлі.
Призначення процедур shuffle_rotate_l і shuffle_rotate_r полягає в тому, щоб виключити регулярні повторення ключових байт кодування UTF8 (які виникають при вживанні всіх мов, крім англійської - і особливо це характерно для кирилиці) - оскільки ця обставина могла б служити зачіпкою для підбору ключа RC4 методом "грубою сили". Застосування нами цих процедур у цьому модулі повністю виключає у нашому продукті таку небезпеку.
Аналогічне завдання вирішує процедура shuffle_swap - її робота полягає у перестановці бітів у сусідніх байтах за певною маскою (SHUFFLE_SWAP_STEP). Конкретний вид цієї маски ми підбираємо з критерію досягнення максимального рівня ентропії підсумкової послідовності байт (попередньо зашифрованих даним модулем). Для різних мов використовуються різні маски. Ефективність їхньої роботи, як правило, перевищує показник 7.9 біт ентропії на один байт. Ми не публікуємо конкретних значень цих бітових масок, оскільки це ніяк не впливає на криптографічну стійкість нашої системи. Таке наше рішення не порушує принцип Керкгоффса, оскільки коди алгоритмів нами тут повністю опубліковані, а конкретні значення SHUFFLE_SWAP_STEP не стосуються кодів, а скоріше — ключових даних, зберігати які в секреті принцип Керкгоффса нікому не забороняє.
Природно, що у будь-якої пари (або компанії) абонентів, які спілкуються між собою через Extra Systems Cypher Net, файл "shuffle.encrypt" має бути ідентичним. Спочатку абоненти отримують ці файли від нас, але, як уже зазначалося вище, можуть самостійно їх створювати і додатково перетасовувати. Важливо лише, щоб вони в цьому випадку для забезпечення ідентичності всіх комплектів фізично їх передали своїм партнерам (при особистій зустрічі або через довіреного кур'єра).
Контент цієї сторінки доступний також англійською, французькою, німецькою, португальською, іспанською, італійською та російською мовами.
© Extra Systems, 2024 |
|