Стандартный номер кредитной карты имеет ограниченную энтропию. Пер ИСО/МЭК 7812 первые 6 цифр фиксированы для данного эмитента карты, и самое простое разумное предположение — они известны злоумышленникам. Последняя цифра является публичной функцией остальных. Для 16-значных номеров кредитных карт остается 9 цифр (в лучшем случае <30 бит энтропии). Его можно лишь немного увеличить (например, 5 бит), используя дату истечения срока действия.
Это означает, что мы не можем использовать быструю и общедоступную функцию (как хэши, если не указано иное) и получить желаемую односторонность. И что любая медленная публичная функция будет иметь ограниченную безопасность. Кроме того, размер слишком мал для криптографии с открытым ключом.
Я пришел к выводу, что мы можем использовать только симметричную криптографию с секретным ключом. Формат, сохраняющий шифрование вдали. Мы могли бы также использовать переформатированный Код аутентификации сообщения, но мы должны опасаться коллизий, и это даст менее надежную гарантию целостности, чем FPE.
По запросу в комментарий, я подробно опишу переформатированный MAC. Я предполагаю, что вывод должен состоять из 16 десятичных цифр без других ограничений. Это означает, что мы готовы допустить некоторую низкую вероятность столкновения: для $n$ номера карт, вероятность которых будет ограничена сверху $n\,(n-1)/(2\cdot10^{16})$; видеть это. Например, мы должны быть удовлетворены 99-процентной уверенностью в отсутствии коллизии между 14 миллионами номеров карт (выбранных без знания ключа).
- Предположим, что фиксированный секретный ключ имеет по крайней мере 128-битную энтропию.
- Вычислить HMAC-SHA-256 номера кредитной карты и ключа, с
выходной размер
= 32 байта
- Рассмотрим вывод как целое число в $[0,2^{256})$ (согласно соглашению с прямым порядком байтов), уменьшите его по модулю $10^{16}$и выразить результат в виде 16 десятичных цифр (с ведущими нулями, если необходимо), формируя токен.
Практически невозможно инвертировать эту токенизацию без доступа к ключу или к устройству с ключом; но это возможно с помощью ключа и умеренных усилий, методом проб и ошибок с номерами кредитных карт.
Если мы хотим дополнительно затруднить инвертирование для одного с ключом, мы можем заменить HMAC-SHA-256 на Аргон2 (номер кредитной карты в качестве пароля, ключ в качестве ключа, фиксированная соль, длина тега
= 32 байта), параметризованный для максимально допустимого замедления. Это не меняет вероятность столкновения, но повышает безопасность: предположим, что Argon2 параметризован на 0,1 секунды времени вычислений определенного ПК; у злоумышленника 100 подобных ПК; 9 цифр номера кредитной карты абсолютно случайны, 6 известны, а последняя цифра является обычной контрольной суммой; тогда потребуется в среднем миллион секунд (11,6 дней) для инвертирования данного хэша или 1 секунда для инвертирования одного хэша из миллиона заданных хэшей.
Если мы не можем жить с риском коллизии, мы должны использовать настоящее шифрование с сохранением формата, но мы теряем сложность инвертирования для того, кто держит ключ. FPE, который значительно сложнее вычислить в обратном направлении, не является стандартным, но возможен, см. вопрос.