
Задавались ли вы когда-нибудь вопросом, как работают QR-коды? Если да, то эта статья для вас. Здесь вас ждёт интерактивное объяснение*, которое мы составили для семинара, проводившегося в рамках Всемирного конгресса хакеров 37C3, но вы также можете использовать его самостоятельно.
Прочитав статью, вы узнаете:
- Из чего состоят QR-коды.
- Как декодировать QR-коды вручную (используя нашу шпаргалку).
*Прим. пер.: текст и приводимые в нём примеры соответствуют QR-коду, содержащему выражение «Hello world!» Полноценная интерактивная версия с возможностью использования собственных кодов и слов доступна в оригинале статьи.
▍ Содержание
- Анатомия QR-кода
- Шаблон маски
- Режим кодирования
- Порядок чтения
- Декодирование длины
- Декодирование содержимого
- Поздравления!
▍ Выберите QR-код
Для начала нам потребуется QR-код, с которым мы будем работать. И здесь у вас три варианта.
- Ввести любой текст, который обновит QR-код, объясняемый ниже.
- Отсканировать любой имеющийся QR-код с помощью камеры.
- Попрактиковаться на декодировании рандомных английских слов. В этом случае слово показано не будет, чтобы вы могли использовать его для обучения.
▍ Анатомия QR-кода
Вот QR-код для фразы «Hello world!»:

Размер этого кода 21×21 модуля (так в кодах называются пиксели).
QR-код может иметь разный размер, который иначе называется его версией. Самая маленькая версия имеет размер 21х21 модуль, и для каждой последующей этот размер увеличивается на 4. Выходит, что наш QR-код имеет версию 1. Вот его элементы наглядно:
▍ Опознавательные метки (finder pattern)
По опознавательным меткам сканеры распознают QR-коды.

▍ Разделители (separators)
Пустые строки вокруг опознавательных меток. При чтении содержимого кода их важно пропускать.

▍ Выравнивающие метки (alignment pattern)
Поскольку мы рассматриваем QR-код версии 1, выравнивающих меток у него нет (эти метки помогают сканерам правильно считывать QR-код).
▍ Метки тайминга (timing pattern)
Две всегда чередующиеся строки из чёрных/белых модулей — ещё один вспомогательный элемент для правильного считывания QR-кода.

▍ Информация о формате (format information)
Определяет шаблон маски и уровень коррекции ошибок.
Может быть представлена вертикально:

И горизонтально. Обратите внимание, что метка тайминга пересекает обе этих линии.

▍ Вот эти области вместе
Всё, что не выделено, является фактическим содержимым кода.

▍ Прочие области
Есть ещё один участок, который здесь не показан: тихая область — белая граница вокруг QR-кода. Она помогает сканерам определять его начало и конец.
▍ Шаблон маски
Для избежания сплошных пятен из чёрных и белых модулей в кодах используется маска, которая может иметь восемь разных форм.
Вот место, где указывается использованный шаблон маски:


Для каждого вида маски существует предопределённый шаблон. Чтобы лучше их запомнить, можете использовать приведённую ниже историю.




Для каждого чёрного модуля маски мы инвертируем модуль в QR-коде, и в следующих шагах вы увидите как. Мы подготовили самопальный зин со шпаргалками для всех типов масок. Можете свернуть его в виде буклета по этой инструкции.
▍ Режим кодирования
Приступим к расшифровке содержимого. Для начала нам нужно узнать используемую кодировку. Эта информация всегда указана в нижнем правом углу.

Но помните — первым делом нужно применить маску. Заглянем в нашу шпаргалку, чтобы понять как.

Нужно выполнить XOR для этих двух областей:


В случае нашего кода это будет режим Байтов (4).
Порядок чтения
Содержимое начинается в нижнем правом углу. Мы поднимаемся вверх, двигаясь зигзагом между двух столбцов, после чего также зигзагом опускаемся левее, повторяя этот процесс по всему QR-коду. При этом особые области всегда пропускаются.

▍ Байты
Первые четыре бита содержат информацию о режиме кодирования. Для режима ASCII следующие восемь битов указывают длину содержимого. Далее каждые восемь битов отражают байт содержимого.
И здесь снова нужно применить маску:

XOR

=

▍ Декодирование длины
Это информация о длине (без маски):

Это значение представляет общую длину содержимого в байтах.
▍ Декодирование содержимого
И, наконец, мы можем перейти к декодированию самого содержимого QR-кода.
Это первый байт (без маски):

Второй байт (без маски):

…И так далее. Декодирование остальных байтов оставим для вас в качестве практики. Вы можете остановиться, когда прочтёте столько символов, сколько было указано в поле длины ранее.
▍ Таблица ASCII

▍ Коррекция ошибок
Значит, всё остальное является содержимым? Не совсем. В QR-коде ещё есть коррекция ошибок, которая обеспечивает, чтобы его можно было прочитать даже в случае повреждения, размытости или отсутствия некоторых частей. Коррекция ошибок производится путём особых математических операций и в рамках процесса ручной расшифровки кода нас не интересует.
▍ Поздравляем!
Этого должно быть достаточно, чтобы самостоятельно декодировать простые QR-коды. Теперь вы можете либо нажать «Random code» в начале статьи (в оригинале, — прим. пер.), чтобы попрактиковаться на случайных английских словах, либо найти QR-код и просканировать его, нажав «Scan code».
▍ Нашли баг? Хотите внести свой вклад?
Исходный код лежит на Codeberg. Будем особенно благодарны за пул-реквесты с объяснением принципа работы режимов кодировки UTF-8.
Автор: Bright_Translate