Шифрування особистого листування
Ще одна копія хабора
Головне меню
Навігація за записами
Шифрування особистого листування. П'ятничний піст
Привіт, Хабра! Тему шифрування особистого листування обговорювали вже багато разів. Але за фактом я не знайшов нічого більш-менш осудного, ніж міг би користуватися без геморою. Тому написав своє розширення для соц. мереж з покером та куртизанками. Оскільки сьогодні п'ятниця, перша половина посту складається із веселих історій із картинками. У другій частині — трохи проблем та способів їх вирішення.

Навіщо потрібне шифрування
Історія про кохання

Мишко на роботі любить листуватися з Катею. Вони часто пишуть один одному різні непристойні речі. Якось Мишко пішов додому і забув вимкнути свій комп'ютер. Цього дня його колеги дізналися багато нового про особисте життя Михайла. Адже всього на все, Мишкові з Катею потрібно було використовувати шифрування.
Історія ревнивого чоловіка

Сергій пише Юлі вірші про кохання. Юля відповідає взаємністю. Кирило сумує. Він чоловік Юлі і щось підозрює. Незабаром він прочитає листування Сергія та Юлі, і влаштує ББПЕ своїй дружині. Юля могла б з'їхати з теми та уникнути ББПЕ, якби більше знала про шифрування.
Історія про алібі

У Толіка дуже насичене життя. Якось, у листуванні інтернетом, Толик хвалився своїми пригодами. Тепер ці пригоди Толику можуть пред'явити. Цього могло б не бути, якби він шифрував свої подвиги.
Історія про масові заворушення

У Льоші активна громадянська позиція. Льоша любить збирати друзів та влаштовувати галасливі збори на міській площі. Гостей на ці збори Льоша запрошує через інтернет. Програміст Артем переглянув усі особистілистування, і швидко зрозумів, хто є організатором масових гулянь. Тепер у Льоші проблеми. Він міг би уникнути їх, якби шифрував свої повідомлення.
Історія про істеричку

Світлана надіслала повідомлення Глібу. Але Гліб зустрічається із Лідою. Гліб відійшов у туалет і забув мобільник. Ліда прочитала повідомлення Свєти. Приблизно за хвилину Ліда закотить скандал.
Як працює шифрування
Тимур має валізу і ключ. Він передає порожню валізу своєму другові Саші.

Сашко теж має свою валізу і ключ. Він робить їх копію, і ховає у чемодан Тимура.

Т.к. тому валіза повертається у закритому вигляді, відкрити її може тільки Тимур. Тільки Тимур має ключ від його валізи.

Тимур відкриває свою валізу і дістає звідти копію валізи та ключа Сашка.

Тепер Тимуру більше не потрібна своя валіза і свій ключ. Він може скористатися тими, що йому передав Сашко.

Приблизно працює алгоритм шифрування RSA. А ось так виглядає швидке розшифрування криптостійкого алгоритму з використанням терморектального криптоаналізатора.

Технічний бік питання.
Як алгоритм шифрування вибрав RSA. Незважаючи на те, що алгоритму близько 30 років, перші бібліотеки на JS виявилися вкрай поганої якості. Таке відчуття, що їх писали лише для одного проекту. Насилу та болем зміг пристосувати їх під потреби свого проекту, хоча завдання були типові:
- Згенерувати ключі
- Зашифрувати текст відкритим ключем
- Розшифрувати текст закритим ключем
Так само був здивований тим, що в половині аналогічних розширень потрібно придумувати якісь фрази, якось їх передавати і т.д. Хоча начебто вже давним-давнолюди передають шифрування відкритими каналами, і процес піддається автоматизації.
Проблеми парсингу соц. мереж.
Почав із вконтакту. Перша складність – на кожен діалог створюється своє поле введення та поле відображення повідомлень. Проблема вирішилася отриманням id співрозмовника.
Далі потрібно було перехопити натискання кнопки «Надіслати» і кнопки Enter. Проблема в тому, що вконтакт перший вішає події і лише потім ініціалізується плагін. Щоб виправити ситуацію, додав свої обробники на document.body, а потім фільтрував усі перехоплені події. Потрібно було першим отримати їх, щоб встигнути замінити оригінальне повідомлення на шифроване.
Сайт однокласники показав, що цього мало. Максимальна довжина повідомлення у них становить 3000 символів, а шифрована пара ключів має довжину 3800. Крім того, звичайні повідомлення також стають довшими за рахунок перетворення в base64. Довелося написати механізм, який розбивав повідомлення на частини, підписував їх (id, поточний індекс, загальна кількість частин), а потім збирав назад. Вийшло щось на кшталт пакетів у TCP/IP.
Далі треба було навчитися генерувати подію «Надіслати повідомлення», т.к. скрипту потрібно було самостійно надсилати пакети. Вконтакте проблема вирішилася дуже просто через виклик глобального методу IM.send(). Щоб дістатися області видимості сайту з області видимості розширення, довелося додавати тег SCRIPT і прописувати туди рядком виклик методу. Приклад:
Тут слід пояснити, що DOM на сайт і розширення той самий, а глобальна область видимості - різна. В однокласниках аналогічний метод знайти не зміг. Діти мінімізують код і не плодять глобали. Довелося емулювати подію на кнопці «Надіслати»:
Коли текст був зашифрований, розбитий на частини,надіслано та зібрано, потрібно було відрізняти нові та старі повідомлення, які відображаються на сайті. І вконтакті, і в однокласниках вони підписуються датою чи унікальним id… думав я… Я ще ніколи так не помилявся. Після цього виник «плаваючий» баг. Виявилося, що всі ці мітки можуть так чи інакше збігтися для двох різних повідомлень. Тому став надавати свій атрибут для всіх DOM-вузлів, щоб знати, хто вже оброблений, а хто ні.
Але дива на цьому не скінчилися. Однокласники публікували повідомлення, далі я його підміняв розшифрованим, потім відбувалася якась магія, і за кілька мілісекунд однокласники знову писали оригінальний текст той самий HTML-елемент. Довелося робити клон ноди повідомлення, писати туди розшифровку та приховувати оригінальний елемент. Оригінальна нода ховалася (display: none), але з видалялася, т.к. я не знав, як і навіщо її переписують. Була небезпека поламати скрипт однокласників у разі видалення HTML-елемента.
Остання загадка парсингу соц. мереж полягала в тому, що якщо з одного комп'ютера логінілося кілька людей, то їхня пара ключів для діалогів потрібно було зберігати в різні місця. Проблема вирішилася через вилучення ID поточного користувача. Знання ID користувача, зробило можливість створення персональних записів у localStorage: