- Регистрация
- 12.04.17
- Сообщения
- 19.095
- Реакции
- 107
- Репутация
- 0
You must be registered for see links
Вы ведь обращаете внимание на зашифрованную информацию? Все эти бесконечные штрих, QR и другие коды, встречающиеся буквально на каждом шагу. Товары в магазинах, кассовые чеки, таблички с информацией для туристов, квитанции для оплаты коммунальных платежей и так далее.
Сегодня я хочу рассказать о коде, который регулярно можно увидеть в аэропортах, а если точнее — на посадочных талонах. Герой этой истории — код PDF417. Давайте посмотрим, можно ли расшифровать такой код вручную и без подсказок? Какой информацией нужно обладать для этого? Сколько на это понадобится времени? Всё это и множество другого ждёт вас в данной публикации. Начнём!
Внимание, под катом — 30 изображений общим размером в 16.3 МБ.
Оглавление
Оглавнение
Часть 01. Первое знакомство
You must be registered for see links
You must be registered for see links
You must be registered for see links
You must be registered for see links
You must be registered for see links
You must be registered for see links
You must be registered for see links
You must be registered for see links
Часть 02. Первый словарь
You must be registered for see links
You must be registered for see links
You must be registered for see links
You must be registered for see links
You must be registered for see links
You must be registered for see links
You must be registered for see links
You must be registered for see links
Часть 03. Новых кодов уже не будет
You must be registered for see links
You must be registered for see links
You must be registered for see links
You must be registered for see links
You must be registered for see links
You must be registered for see links
You must be registered for see links
You must be registered for see links
You must be registered for see links
You must be registered for see links
Часть 04. Финал
You must be registered for see links
You must be registered for see links
You must be registered for see links
You must be registered for see links
01. Вступление и о повествовании
(
You must be registered for see links
|
You must be registered for see links
|
You must be registered for see links
)Первый вопрос, на который я сразу же хочу ответить, — "Зачем это нужно?". Ответ достаточно прост — в какой-то момент мне было скучно и я задумался. А после — не мог остановиться.
Данная история покажет, как и в какой последовательности я определял части разных PDF417 кодов. Естественно, не все предпринятые мной шаги были рациональными или принесли какой-либо результат. Однако, ещё в самом начале я решил, подсматривать в ответ — не так интересно, как промучиться во много раз больше и убить гору времени даже не на стопроцентный результат.
Весь рассказ поделен на разделы, согласно этапам. Если какой-то из них покажется вам слишком многословным, просто переходите к следующему.
02. Базовая информация
(
You must be registered for see links
|
You must be registered for see links
|
You must be registered for see links
)Итак, PDF417 коды печатают на всех посадочных талонах при регистрации в аэропорту. Кроме того, именно их присылают по электронной почте при самостоятельной регистрации онлайн. Иногда такие коды получают и при регистрации через мобильные приложения авиакомпаний, но в таких случаях чаще используют более компактные коды.
Начнём с кода #01 одного из моих посадочных талонов авиакомпании UIA (
You must be registered for see links
). Это небольшое TIFF изображение. Его наименьший элемент — прямоугольник 2 х 4 пикселя. Назовём его символом. Код состоит из 6 блоков шириной в 17 и высотой в 12 символов. В каждом блоке первый символ — заполненный, а последний — пустой.Рис. 1. Пример стандартного PDF417 кода прямиком с одного из моих посадочных талонов (#01)
Присмотревшись к любому блоку, можно заметить, что строка в нём — набор из 4 заполненных и 4 пустых последовательностей символов, общей длиной в 17 символов. Разгадка названия кода оказалась весьма прозаичной — это параметры одного блока информации. Такую последовательность из 17 символов будем называть словом.
По краям кода расположены ещё два блока (похожие на штрихкод) шириной в 17 (левый) и 18 (правый) символов. Вероятно, они лишь определяют тип кода, поскольку не меняются между строками. В таком случае, полезной информации они не несут.
Если сравнить несколько разных PDF417 кодов одного перевозчика (
You must be registered for see links
), можно выяснить, что первый и последний блоки в них всех одинаковы. Очевидно, они содержат сервисную информацию или же параметры записи данных.Рис. 2. Пять разных PDF417 кодов с посадочных талонов одной авиакомпании (#01: #05)
03. Применение PDF417 кодов
(
You must be registered for see links
|
You must be registered for see links
|
You must be registered for see links
)Данные коды посадочных талонов проверяют перед тем, как пустить вас на рейс. В таком случае, код должен содержать как минимум номер рейса. Последний представляет из себя комбинацию 2 букв (код авиакомпании) и 4 цифр (порядковый номер рейса). Если порядковый номер меньше тысячи, его иногда указывают без 0 вначале. В итоге, в каждом коде должно содержаться 5-6 символов, ответственных за номер рейса.
Кроме того, всегда перед посадкой в самолёт проверяют ваши документы (а иногда ещё и переспрашивают ваше имя, особенно когда прочитать его не так просто). Есть два варианта, где взять эту информацию:
- Имя содержится прямо в коде;
- В коде есть номер билета, а все данные о пассажире получают по этому номеру онлайн.
Второй вариант лично мне видится менее реалистичным. Несмотря на то, что номер билета и не так велик (около 13 цифр, хотя и может быть длиннее в зависимости от перевозчика), потребовалось бы при считывании получать данные каждого билета от аэропорта или авиакомпании. Это было бы немного (или не немного) дольше и сильно повлияло бы на скорость пропуска сотни пассажиров (что бывает критично для недорогих перевозчиков).
Для упрощения, предположим, что имя на самом деле зашифровано прямо в коде. В моем случае — это 18 символов. Поскольку необходим ещё и разделитель между именем и фамилией, то все 19.
04. Позиционируем данные
(
You must be registered for see links
|
You must be registered for see links
|
You must be registered for see links
)Поскольку я не знаю, как именно информация записана в коде, попробуем найти области одинаковых слов в разных кодах (
You must be registered for see links
).Далее я буду называть слова по их положению в коде, указывая вначале индекс ряда, а после слеша — индекс слова в ряду. Последовательность рядов или слов объединяются двоеточием.
В каждом из 5 кодов содержится 14 одинаковых слов вначале (0/0: 3/1) и ещё 9 слов разбросаных по коду (5/2:3, 6/1, 7/0:1, 8/0, 9/1:3). То есть 25 слов, общих для всех посадочных талонов. При этом, слова 9/1:3 одинаковые. Возможно, они просто показывают конец полезной информации в коде, поскольку далее все слова во всех пяти кодах разные.
Итак, у нас есть достаточно длинный набор из 14 тех же слов в каждом случае. Предположим, здесь спрятано имя. Кроме того, там должен быть минимум один разделитель — между именем и фамилией. Возможно, есть также и второй — в конце, чтобы отделить остальную информацию. Поскольку каждое слово точно не может содержать лишь один символ, оно, вероятно, содержит два. Тогда я могу поместиться в 9 слов + 1 слово разделитель.
Дальше, где-то должна быть представлена информация о рейсе. #01, #02 и #04 — это коды, соответствующие одному и тому же рейсу PS 0336, а #03 и #05 — рейсу PS 0335. Одинаковыми для этих двух групп являются слова:
- 4/3: 5/1 (3 слова);
- 6/1.
Поскольку нам нужно ещё и наличие 2 букв авиакомпании где-то рядом, нам подходит второй вариант, расположенный сразу после повторяющихся для всех кодов слов. Хочу обратить внимание на тот факт, что перед 6/1 присутствует сразу 3 одинаковых во всех случаях слова.
В кодах можно заметить слова, одинаковые для #02 и #03, а также другие одинаковые для #04 и #05. Это 5 слов в диапазоне 3/2: 4/2. Для этих пар общее — номер брони, состоящий из 6 символов (латиница + цифры в произвольном порядке).
Рис. 3. Построчное сравнение кодов #01: #05
05. Добавляем новых PDF417
(
You must be registered for see links
|
You must be registered for see links
|
You must be registered for see links
)Следующим шагом было добыть ещё несколько кодов с посадочных талонов для проверки части предположений. С этим мне помогла моя жена, разрешив взять данные из её посадочных талонов на рейс PS 0336 (#06) и ещё две пары PS 0335 / PS 0336 (#07: #10). При этом, #09: #10 относятся к тому же бронированию билетов, что и #04: #05. Интересен тот факт, что код #06 на одну строку короче и состоит лишь из 11 строк. Все 5 кодов приведены на
You must be registered for see links
.Сразу можно заметить, что #06 выбивается из этой группы из-за нестыковок в правом и левом информационных блоках. При этом, им свойственна цикличность каждые 3 строки. Так каждое
Коды #07: #10 отлично подходят под все предыдущие предположения. Это касается как вероятного размещения кода бронирования, так и информации одинаковой для одного номера рейса. Кроме того, первые 14 слов кода, в которых вероятно размещается имя, тоже одинаковы для четырёх кодов.
И это всё перестаёт работать для более короткого кода #06. Конечно, не совсем всё, 13 слов в диапазоне 0/1: 3/1 остаются такими же, как и для других кодов. При этом, все остальные слова не соответствуют другим кодам. Но на данный момент нам это не важно.
Стоит отметить, что самое первое слово в коде отличается от других кодов, хотя вся остальная строка такая же. Значит это слово содержит информацию о всём коде. Возможно, размер кода (количество слов или строк).
Рис. 4. Построчное сравнение кодов #06: #10
06. Уточняем позиционирование
(
You must be registered for see links
|
You must be registered for see links
|
You must be registered for see links
)Итак, у нас есть 9 и ещё 1 код. Давайте сравним интересующие нас блоки и попробуем определить положение информации в коде. Возьмём чуть больше чем половину кода. Ту, где по моему мнению находится имя, номер брони и номер рейса (
You must be registered for see links
).Как видно, слова 0/1:2 одинаковы для нас обоих. Потому пришлось воспользоваться тем, что я именую логикой. Где-то давно я предположил, что каждое слово может содержать 2 буквы. Если бы была всего 1 буква на слово, то в 11 букв и два разделителя поместились бы даже не все фамилии жителей Земли. Если 3 или больше — в моём коде наблюдались бы одинаковые слова для большого количества "пробелов" (пустых символов) перед началом следующей значимой информации кода.
Для нас двоих совпадают только 2 первые буквы в именах, а фамилии разные. При этом в моём коде слова 1/0 и 1/2 одинаковы. Предположив, что метод передачи данных в одной строке одинаков, это означает повторение двух пар символов, разделённых ещё одной парой. Это было не сложно.
Итак, фамилия пасажира начинается со слова 0/3. После неё, вероятно, идёт разделитель, а потом — имя и ещё раз разделитель. В таком случае, максимум информации о пасажире в подобном коде — 20 символов, а минимум 2 символа — разделители. Но пока оставим имя в покое.
Следующая часть кода, предположительно, номер бронирования. Этому свидетельствуют 5 одинаковых слов для 4 билетов из одной брони (#04, #05, #09, #10). Кроме того, слово 3/2 для #07 и #08 тоже совпадает со словами в перечисленной четвёрке.
Номера бронирования для всех билетов:
- SNK79J (#01);
- RUKG4T (#02, #03);
- LW2BUW (#04, #05, #09, #10);
- SLRSFS (#06);
- LWJ2JA (#07, #08).
Для приведённых шести общее — LW. Слово 3/2 совпадает также для #01 и #06, у которых общая лишь S. Предположим, что это слово скрывает лишь 1 символ (либо разделитель и 1 символ).
Слова 4/3: 5/1 всё также соответствуют каждому рейсу. Что это за 3-6 символов остаётся неочевидным.
Поскольку я уже почти уверен, что за одним словом скрывается до двух символов, слова 6/0:1 соответствуют номеру рейса (03 и 36 либо 35). Слова 5/2:3 содержат код авиаперевозчика PS и один либо 2 разделителя.
Рис. 5. Уточнение позиций данных #01: #10 для первых 7 рядов
07. Метод подбора
(
You must be registered for see links
|
You must be registered for see links
|
You must be registered for see links
)Давайте посмотрим, что же осталось во второй половине кода. Как я уже упоминал ранее, последние 8 слов вряд ли содержат полезную информацию, а перед ними находится 3 слова, показывающие конец данных.
Аналогично со словом 6/3, слова 7/2 и 8/1 повторяются в парах билетов из одного бронирования и одного рейса (#02 и #07, #03 и #08, #04 и #09, #05 и #10). Слова 7/0:1 и 8/0 одинаковы для всех билетов (за исключением нашего уникального #06), а 8/3 и 9/0 одинаковы для всех, кроме #01 и #06.
Поскольку здесь я уже не мог угадать, что же может скрываться за этими словами, я решил посмотреть на тексты посадочных талонов. Там находится стандартная информация, которую вам и / или работникам аэропорта стоит знать о билете. Сюда входит:
- номер билета (13 цифр);
- некий номер безопасности (3-буквенный код аэропорта вылета, минус и 3 цифры);
- номер участника программы лояльности (зависит от программы, иногда буквы вначале, всегда много цифр);
- информация о багаже;
- аэропорты вылета и прилёта (и их коды);
- время и дата посадки и вылета;
- терминал (не часто отображает актуальную информацию);
- ваше место в самолёте;
- класс резервирования (одна латинская буква).
Ранее я уже решил, что 13 цифр номера билета шифровать нет смысла — он занимает слишком много места. Аналогично с программой лояльности (кроме того, что тогда этот номер был бы во всех 5 билетах одного человека).
Информацию о багаже, время с датой вылета и посадки, а также терминал писать смысла не много, поскольку эти данные могут меняться практически в любой момент до непосредственно посадки в самолёт.
Осталось немного — код безопасности, аэропорты, место в самолёте и класс резервирования. Сравним их для разных билетов.
PDF417 | Код безопасности | Откуда | Куда | Место | Класс |
---|---|---|---|---|---|
#01 | VCE-037 | VCE | KBP | 4D | X |
#02 | VCE-047 | VCE | KBP | 24A | N |
#03 | KBP-053 | KBP | VCE | 6F | Q |
#04 | VCE-082 | VCE | KBP | 26B | X |
#05 | KBP-026 | KBP | VCE | 17B | X |
#06 | VCE-077 | VCE | KBP | 15A | N |
#07 | VCE-046 | VCE | KBP | 24B | M |
#08 | KBP-055 | KBP | VCE | 6E | X |
#09 | VCE-083 | VCE | KBP | 26C | X |
#10 | VCE-025 | KBP | VCE | 17C | X |
Заметили? У нас есть 3 разных места с буквой B, а также 2 — A и 2 — C. Их найти было не сложно — слово 7/3. В таком случае, слово 7/2 содержит цифры из номера места. Потому их четыре пары и ещё два разных.
Не многим сложнее было найти и код безопасности. А точнее, его цифры — в словах 8/1:2. При этом, 8/1 содержит первые две, а 8/2 — последнюю цифру и, возможно, разделитель. Слово 8/0 разделяет место пассажира и код безопасности и одинаково для всех кодов.
Что скрывается за словами 6/2 и 6/3 непонятно. Это же касается и последних слов-данных 8/3 и 9/0. Слова 8/0, 7/0 и 7/1 одинаковы для всех кодов.
Рис. 6. Уточнение позиций данных #01: #10 для последних 6 строк
08. Построчный анализ
(
You must be registered for see links
|
You must be registered for see links
|
You must be registered for see links
)Настало время рассмотреть особенности разных строк кодов. Здесь не будет текста. Давайте просто посмотрим на свойства слов каждые три строки. Представим каждое слово как последовательность из 8 символов, шириной от 1 до 6. Тогда для строк 0, 3, 6 и 9 получим следующий результат на основе 19 разных слов (
You must be registered for see links
).Рис. 7. Слова в строках 0, 3, 6 и 9
А вот для строк 1, 4, 7 и 10, состоящих из 32 разных слов, правила немного другие (
You must be registered for see links
).Рис. 8. Слова в строках 1, 4, 7 и 10
Соответственно, для 28 слов из строк 2, 5, 8 и 11 результат будет следующий (
You must be registered for see links
).Рис. 9. Слова в строках 2, 5, 8 и 11
В таком случае, с помощью трёх несложных шагов, можно вывести формулу для определения группы, к которой относится строка (
You must be registered for see links
).Рис. 10. Общие правила
09. Получение всех возможных слов
(
You must be registered for see links
|
You must be registered for see links
|
You must be registered for see links
)Итак, в каждом слове есть 8 символов. Максимальная длина одного — 6 элементов. Отталкиваясь лишь от этого, можно получить 1 679 616 комбинаций. Если же уточнить, что длина слова должна быть равна 17 элементов, а также для слов в каждой строке должны выполняться найденные ранее правила, у нас остаётся лишь 3 488 возможных вариантов.
Из этих 3 488 вариантов:
- 1 484 для группы 0;
- 1 002 для группы 3;
- 1 002 для группы 6.
Поскольку группы 3 и 6 содержат меньше возможных комбинаций, а все три группы должны бы быть абсолютно одинаковы, будем считать их верхней границей. Таким образом, 482 комбинации из группы 0 не используются.
Осталось понять, как же эти слова кодируются. Я уже практически уверен, что каждое слово кода может содержать 2 буквы. В латинице — 26 букв от A до Z, для которых потребуется
Не сложно заметить, что цифры сюда уже не влезают, поскольку
Итак, вернёмся к количеству возможных комбинаций. Мы можем зашифровать не больше чем квадрат числа возможных символов. Получается, что наш лимит — 31 символ (961 комбинация).
Предполагаемая таблица
Индекс | Режим 0 | Режим 1 |
---|---|---|
0 | A | 0 |
1 | B | 1 |
2 | C | 2 |
3 | D | 3 |
4 | E | 4 |
5 | F | 5 |
6 | G | 6 |
7 | H | 7 |
8 | I | 8 |
9 | J | 9 |
10 | K |