Предлагаю читателям Хабрахабра перевод статьи «Как расшифровать данные магнитной карты с помощью DUKPT» .
Недавно мне понадобилось расшифровать данные карты с помощью считывателя магнитных карт. Казалось бы, это просто.
Я беру ключ и выполняю определенный алгоритм расшифровки.
Но не тут-то было.
Оказалось, что мои читатели используют схему, известную как DUKPT (Derived Unique Key Per Transaction).
Идея этой схемы заключается в том, что для каждой транзакции (или, в нашем случае, для каждого проката карты) данные шифруются с использованием ключа, рассчитанного для индивидуального проката карты.
Таким образом, чтобы расшифровать данные, которые были зашифрованы по этой схеме, необходимо уметь рассчитать ключ для индивидуального проката карты.
Процесс вычисления такого ключа (сессионного ключа) далеко не прост. Процесс описан в документе ANSI X9.24 часть 1. Однако стоит документ примерно 140 долларов.
Бесплатную, легкодоступную документацию, описывающую этот процесс, найти сложно.
Лучший ресурс, который я нашел, это здесь ; есть довольно хорошее объяснение того, как рассчитывается IPEK (начальный ключ шифрования PIN).
К сожалению, это лишь часть полной схемы.
В этом посте я попытаюсь подробно объяснить схему ДУКПТ.
Определения
БДК : это сокращение от «Базовый ключ деривации».Этот ключ известен только производителю и разработчику программного обеспечения, взаимодействующего со сканером магнитных дорожек.
ИПЭК : это сокращение от «Первоначальный ключ шифрования».
Этот ключ определяется из BDK. Этот ключ загружается на устройство производителем и используется для генерации будущих ключей.
Компрометация IPEK не ставит под угрозу BDK. КСН : это сокращение от Key Serial Number. KSN представляет собой комбинацию серийного номера сканера магнитной полосы и счетчика количества проведений карты, совершенных на устройстве.
Как это работает
BDK используется производителем для создания IPEK, который загружается на устройство во время разработки.Устройство использует IPEK и KSN для расчета сеансового ключа, который шифрует данные, считываемые с карты.
BDK требуется разработчикам программного обеспечения для расчета IPEK. Получив IPEK, они могут запросить KSN с устройства.
IPEK и KSN используются для получения ключа для индивидуальной транзакции/аренда карты.
С помощью этих ключей разработчики смогут расшифровать данные карты.
расчет ИПЭК
Чтобы получить исходный ключ вычисления ключа (IPEK), нам нужен базовый ключ алгоритма (BDK) и серийный номер ключа (KSN).IPEK определяется с помощью алгоритма TripleDES. TripleDES — это простой алгоритм DES, выполняемый за три прохода.
Алгоритм использует ключ длиной 24 байта.
Алгоритм DES используется трижды: сначала с ключом длиной 1–8 байт, затем 9–16 байт и, наконец, 17–24 байта отдельно для каждого прохода.
TripleDES может использовать 16-байтовый ключ — метод EDE3. Сначала будут использоваться байты 1–8, затем 9–16 и снова 1–8, создавая 24-байтовый ключ.
Некоторые реализации TripleDES не могут автоматически использовать короткий ключ.
Прежде чем осознать это, я потратил много времени, пытаясь выяснить, в чем проблема.
Предполагая, что это специальная реализация TripleDES, я использовал выдаваемый 24-байтовый ключ длиной 16 байт. После долгих мучений мне пришло в голову попробовать взять первые 8 байт и добавить их в конец ключа перед передачей его алгоритму TripleDES. Это решило проблему.
Подробности
IPEK состоит из двух 8-байтовых частей, полученных в результате двух отдельных проходов алгоритма TripleDES. И то, и другое получается путем шифрования старших 8 байт KSN со сбросом счетчика.Разница между левой и правой частью заключается в том, что правая часть получается путем шифрования KSN с помощью слегка модифицированной версии БДК.
Я опишу этот процесс ниже.
Предположим, имеется 16-байтовый BDK, представленный шестнадцатеричной строкой «0123456789ABCDEFFEDCBA9876543210».
Также у нас есть 10-байтовый KSN со счетчиком, равным 8, представленный шестнадцатеричной строкой «FFFF9876543210E00008».
Давайте заставим BDK зашифровать левую часть IPEK, добавив первые 8 байтов в конец BDK, это будет следующий 24-байтовый ключ.
Если длина KSN не 10 байт, то дополняем его до 10 байт шестнадцатеричного «F» (1111).0123456789ABCDEFFEDCBA98765432100123456789ABCDEF
Важно отметить, что ИПЭК – это самый первый ключ на устройстве.
Это означает, что мы вычисляем его со счетчиком в КСН, равным 0. Чтобы получить КСН со счетчиком, равным 0, мы накладываем на него маску с шестнадцатеричным представлением, которой является строка «FFFFFFFFFFFFFE00000».
FFFF9876543210E00008
and FFFFFFFFFFFFFFE00000
= FFFF9876543210E00000
Удивительный.
Теперь у нас нулевой КСН.
Однако нам нужны старшие 8 байт KSN. Их мы получаем сдвигом КСН вправо на 16 бит. FFFF9876543210E00000 >> 16 = FFFF9876543210E0
Большой.
Следующий шаг — шифрование TripleDES строки «FFFF9876543210E0» с использованием 24-байтового ключа BDK «0123456789ABCDEFFEDCBA98765432100123456789ABCDEF».
Результатом этого шифрования будет левая часть IPEK. 6AC292FAA1315B4D
Если помните, я упоминал, что для получения нужной детали будет использоваться слегка модифицированная версия БДК.
Итак, для этого нам нужно взять исходный 16-байтовый BDK «0123456789ABCDEFFEDCBA9876543210» и выполнить XOR следующую маску «C0C0C0C000000000C0C0C0C000000000».
Вроде бы это совершенно произвольная маска, но увы, необходимо получить правильный IPEK. 0123456789ABCDEFFEDCBA9876543210
xor C0C0C0C000000000C0C0C0C000000000
= C1E385A789ABCDEF3E1C7A5876543210
Мы сделаем то же самое, что и с ключом для левой части, возьмем самые значимые 8 байт и сложим их в конец, получим следующий 24-байтовый ключ.
C1E385A789ABCDEF3E1C7A5876543210C1E385A789ABCDEF
Далее возьмем старшие 8 байт KSN с нулевым счетчиком (который мы вычислили ранее) и зашифруем его с помощью TripleDES только что вычисленным нами ключом.
Это даст нам правильный регистр IPEK, что даст нам следующие 16 байт IPEK (для ясности я разделил левую и правую части).
6AC292FAA1315B4D 858AB3A3D7D5933A
Вычисление сеансовых ключей
У нас есть ИПЭК.Далее нам необходимо получить от ИПЭК уникальный ключ для аренды индивидуальной карты (сессионный ключ).
Для его получения используется некая подпрограмма, назовем ее черным ящиком, цель которой — вернуть отдельный сеансовый ключ.
Что происходит в черном ящике, нас пока не касается.
Прямо сейчас мы посмотрим на входные данные этой подпрограммы.
Наш черный ящик имеет два входа.
Один из них — это ключ, а второй — строка шифрования.
Линия представляет собой модифицированный KSN. Если помните, младшие 21 бит KSN содержат счетчик количества прокатов карт на устройстве.
Модифицированный KSN мы будем передавать в подпрограмму столько раз, сколько единиц есть в двоичном представлении счетчика.
Ключом, который передается с модифицированным KSN, является IPEK на первой итерации, а на последующих итерациях это будет ключ, полученный из черного ящика на предыдущей итерации.
Начнём со смены KSN. Сначала мы возьмем младшие 8 байт KSN и обнулим значение счетчика в KSN. Это можно сделать, замаскировав KSN с помощью следующей маски.
FFFF9876543210E00008
and 0000FFFFFFFFFFE00000
= 00009876543210E00000
Мы будем использовать полученное значение для расчета каждого сообщения, отправленного в черный ящик.
В нашем примере со счетчиком 8 мы должны передать в черный ящик двоичное представление числа 8 (1000).
Для демонстрации предположим, что счетчик имеет более сложное значение 10 (1010).
Мы извлечем из счетчика набор двоичных чисел.
В нашем случае для числа 10 (1010) будет два двоичных числа: 1000 и 0010. Улавливаете закономерность? Мы получаем набор чисел, представляющий каждую двоичную единицу числа 10. Далее мы берем первое число и применяем операцию ИЛИ к KSN, счетчик которого обнуляется, как было показано ранее (обратите внимание, что шестнадцатеричное представление первого числа будет 0008).
9876543210E00000
OR 0000000000000008
= 9876543210E00008
Теперь передаем в черный ящик ИПЭК в качестве ключа и вновь модифицированный KSN. Черный ящик вернет новый ключ.
Это первый сеансовый ключ (представленный в шестнадцатеричном формате): «27f66d5244ff62e1aa6f6120edeb4280».
Далее мы повторяем процесс со следующим двоичным числом, вычисленным ранее, 2 (0010).
На этот раз мы воспользуемся только что полученным первым сеансовым ключом и рассчитаем новую модификацию KSN.
Для расчета новой модификации KSN выполним операцию ИЛИ с последней полученной модификацией: 9876543210E00008. 9876543210E00008
OR 0000000000000002
= 9876543210E0000A
Теперь перенесем в черный ящик наш новый ключ «27f66d5244ff62e1aa6f6120edeb4280» и новую модификацию KSN «9876543210E0000A» и получим еще один будущий ключ «6cf2500a22507c7cc776ceadc1e33014».
Это сеансовый ключ для нашего устройства счетчика 10. Однако наш реальный счетчик был равен 8, и на первом этапе мы вычислили реальный сеансовый ключ «27F66D5244FF62E1AA6F6120EDEB4280».
Последняя операция, которую мы должны выполнить с полученным значением, — это окончательное преобразование ключа, которым мы будем расшифровывать данные.
Мы должны выполнить XOR для ключа с маской «00000000000000FF00000000000000FF».
27F66D5244FF62E1AA6F6120EDEB4280
XOR 00000000000000FF00000000000000FF
= 27F66D5244FF621EAA6F6120EDEB427F
Это ключ, который необходим для расшифровки данных.
Черный ящик
Я назвал алгоритм, вычисляющий сеансовые ключи, «черным ящиком».Черный ящик принимает текущий сеансовый ключ, который я назову current_sk , а модификацию KSN обозначим ksn_mod .
Если в начале предполагалось, что полученный выше IPEK был передан как current_sk , А ksn_mod было равно значению «9876543210E00008», которое мы рассчитали выше.
Сначала нам нужно взять current_sk , получаем старшие 8 байт и сдвигаем их на 64 бита вправо, получаем «6AC292FAA1315B4D».
Этого можно добиться с помощью битовой маски.
6AC292FAA1315B4D858AB3A3D7D5933A
AND FFFFFFFFFFFFFFFF0000000000000000
= 6AC292FAA1315B4D0000000000000000
Здесь нам нужно сдвинуть это значение на 64 бита вправо, чтобы получить «6AC292FAA1315B4D».
Давай позвоним ему левый_ключ (выглядит как левая сторона current_sk ).
Далее мы получаем 8 младших байтов current_sk , используя маску.
6AC292FAA1315B4D858AB3A3D7D5933A
AND 0000000000000000FFFFFFFFFFFFFFFF
= 0000000000000000858AB3A3D7D5933A
Назовем это значение (как вы уже догадались) правый_ключ .
Далее мы берем правый_ключ и выполните XOR с ksn_mod «9876543210E00008».
858AB3A3D7D5933A
AND 9876543210E00008
= 1DFCE791C7359332
Назовем это ценностным сообщением.
Далее мы берем сообщение и шифруем его с помощью DES (простого DES).
Алгоритм сообщения передадим в DES как данные, которые нужно зашифровать, и левый_ключ , как ключ для шифрования.
Результатом будет «2FE5D2833A3ED1BA».
Теперь нам нужно выполнить XOR для этого значения и правый_ключ .
2FE5D2833A3ED1BA
XOR 858AB3A3D7D5933A
= AA6F6120EDEB4280
Это значение младших 8 байт нашего сеансового ключа! Теперь нам нужно повторить только что описанные операции с другими входными данными.
На этот раз мы берем current_sk и выполните XOR с помощью «C0C0C0C000000000C0C0C0C000000000».
Насколько я могу судить, это значение произвольное, но оно является частью стандарта ANSI, так что вам придется просто поверить мне на слово.
6AC292FAA1315B4D858AB3A3D7D5933A
XOR C0C0C0C000000000C0C0C0C000000000
= AA02523AA1315B4D454A7363D7D5933A
Если мы возьмем значение «AA02523AA1315B4D454A7363D7D5933A» и заменим его на current_sk в описанной выше операции мы получим «27F66D5244FF62E1».
Это самые важные 8 байтов нашего сеансового ключа.
Объединив их, получим «27F66D5244FF62E1AA6F6120EDEB4280».
Заключение
Надеюсь, я объяснил схему ДУКПТ и то, как она связана с эффективностью сканеров магнитных следов.Буду рад исправлениям и вопросам в комментариях.
Теги: #шифрование; магнитные карты; ДУКПТ #информационная безопасность #Алгоритмы
-
Ракетное Оружие
19 Oct, 24 -
Твирп Против Grpc. Стоит Ли Оно Того?
19 Oct, 24