Кодировки и шифрование

Кодировки

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

Наиболее распространённые кодировки

Обозначение в python

Название кодировки

Описание

ascii

ASCII

Латинские буквы, цифры и простые символы

cp1251

windows-1251

Кириллическая кодировка (русский и другие языки)

koi8-r

KOI-8

Кодировка для русского языка

utf-8

UTF-8

Юникод-кодировка, все языки (длина символа - 8 бит)

utf-16

UTF-16

Юникод-кодировка, все языки (длина символа - 16 бит)

Unicode — стандарт кодирования символов, включающий в себя знаки почти всех письменных языков мира. В настоящее время стандарт является преобладающим в Интернете.

  • стандарт включает более 138 тысяч символов;

  • каждый символ имеет определённое название и код (номер);

  • коды состоят из латинских букв и шестнадцатеричных цифр, например: U+0073.

Примеры кодов, имен и соответствующих символов:

  • U+0073, «LATIN SMALL LETTER S» - s

  • U+1F383, «JACK-O-LANTERN» - 🎃

  • U+2615, «HOT BEVERAGE» - ☕

Конвертация данных между байтам и строками

Данные по сети передаются, как правило, в байтах. Например, метод socket.recv() получает данные в байтах. Чтобы преобразовывать данные из байт в строки и наоборот используются специальные методы:

  • метод encode('encoding_name') - позволяет перевести данные из строки в байты (str -> bytes);

  • метод decode('encoding_name') - позволяет перевести данные из байт в строку (bytes -> str);

В коде будет выглядеть так:

# кодирование строки в байты
s = 'привет'
s_bytes = s.encode ('utf-8')
print (s_bytes)

Out: b'\xd0\xbf\xd1\x80\xd0\xb8\xd0\xb2\xd0\xb5\xd1\x82'

# декодирование байт в строку
s_dec = s_bytes.decode ('utf-8')
print (s_dec)

Out: привет

При работе с кодировкой важно помнить:

  1. Если вы кодируете строку в байты кодировкой UTF-8, то и перекодировать её из байт нужно этой же кодировкой. Некоторые кодировки совместимы, но в большинстве случаев, нарушения этого правила ведёт к потере данных.

  2. В своём коде всегда используйте кодировки Unicode, оптимально UTF-8, она используется по умолчанию в большинстве методов и функций, так что это снижает риск ошибок.

  3. Декодирование байтовых данных в строки лучше производить сразу после их получения, а кодирование в байты - только перед отправкой. В коде лучше работать с привычными типами данных (строки, списки, числа), не с байтами, ведь большинство методов в Python с байтовыми строками не работают (или работают не так, как можно ожидать).

Шифрование

Шифр Цезаря

Шифр Цезаря — это вид шифра подстановки, в котором каждый символ в открытом тексте заменяется символом, находящимся на некотором постоянном числе позиций левее или правее него в алфавите. Например, в шифре со сдвигом вправо на 3, A была бы заменена на D, B станет E, и так далее.

Повторить шифр можно в занятии

Формула для кодирования символа:

symbol_encoded = ((((symbol) - first + key) % size) + first)

Шифр пар

Алфавит случайным образом записывают в 2 строки, и шифрование текста происходит заменой буквы на соседнюю ей по вертикали. Например:

['v', 'q', 'f', 's', 'p', 'u', 'n', 'a', 'm', 'j', 'c', 'k', 'h']
['l', 'r', 'o', 'e', 'x', 'd', 'z', 'g', 'b', 'w', 't', 'i', 'y']

In: hello
Out: ysvvf

Шифр Виженера

На алфавите длиной N вводят операцию добавления (циклического сдвига) букв. Пронумеровав буквы, добавляем их по модулю N (для англ. алфавита N=26).

Выбираем слово-ключ (пускай pass) и подписываем его под сообщением сколько нужно раз:

Сообщение: search
Ключ:      passpa
Шифр:      hesjrh

Задания

  1. Доработайте прототип чата из прошлого урока таким образом, чтобы он корректно работал с русским языком (используйте методы кодирования и декодирования байтовых строк).

2. Напишите функцию для шифрования файла шифром Цезаря. Расшифруйте:

key = 2
s = 'Oquv uvctu ctg qdugtxgf vq dg ogodgtu qh dkpctb uvct ubuvgou'

3. Напишите функцию для шифрования файла шифром пар. Расшифруйте:

d_1 = [109, 122, 106, 115, 100, 99, 105, 120, 110, 98, 121, 118, 107]
d_2 = [112, 103, 108, 104, 111, 102, 119, 117, 97, 101, 116, 113, 114]
s = 'A hynk wh na nhykdadpwfnj delbfy fdahwhywaz dc n jxpwadxh hmsbkdwo dc mjnhpn sbjo ydzbysbk et wyh dia zknqwyt.'

4.* Напишите функцию для шифрования файла шифром Виженера. Расшифруйте. 5. Добавьте в чат (с кодировкой) возможность выполнять шифрование и дешифрование сообщения одним из шифров по выбору пользователя. 6. Доработайте чат таким образом, чтобы пользователь отправлял серверу имя зашифрованного файла и шифр, а сервер дешифровал его и отправлял содержимое файла обратно пользователю.