Рейтинг:1

Как составить несколько значений для аутентификации MAC?

флаг sr

Если данные, которые я хочу аутентифицировать, состоят из нескольких значений, и я вычисляю MAC, просто объединяя значения, злоумышленник может «сдвинуть» символы в этих значениях, не аннулируя MAC. Как обычно и лучше всего решается эта проблема?

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

Рассмотрим следующий надуманный пример:

Предположим, у меня есть сервер, на котором хранятся подлинные записи журнала для клиентов. Клиент записывает запись в журнал, аутентифицирует ее с помощью MAC и отправляет на сервер. Позже, когда клиент получит записи журнала с сервера, он сможет проверить их подлинность.

Допустим, записи журнала имеют следующую структуру:

{
  createdAt: "1621012345",
  сообщение: "первая запись"
}

Наивно я мог создать MAC для записи в журнале л как $$ mac = \text{HMAC}(K, l.createdAt \| l.message) $$ куда $\|$ обозначает конкатенацию и $К$ является секретным ключом.

Если бы я сохранил эту запись журнала и MAC-адрес на сервере и получил их позже, сервер мог бы вернуть

{
  создано по адресу: "1621012",
  сообщение: "345первая запись",
  mac: "<MAC, вычисленный выше>"
}

С 1621012 || 345первая запись такой же как 1621012345 || первая запись Я бы не заметил манипуляций при проверке MAC.

Обратите внимание, что в этом случае я должен фактически обнаружить манипуляцию, проверив затем длину создано в. Но это работает, только если длина фиксирована, а не если бы я, скажем, имя автора вместо отметки времени.

Я могу придумать следующие способы справиться с этим:

1. Вставьте разделитель

Если бы я рассчитал свой MAC как $mac = \text{HMAC}(K, l.createdAt \| \text{':'} \| l.message)$ Я считаю, что эта атака больше невозможна. На первый взгляд кажется проблематичным, что в сообщении может появиться символ-разделитель. Но это только делает невозможным однозначное восстановление значений из объединенной строки, что не имеет значения в этом сценарии. Я не могу придумать никакого способа сделать здесь расчет MAC неоднозначным. Безопасно ли это простое решение?

2. Хэш-значения перед конкатенацией

Я мог бы рассчитать MAC, например, как $mac = \text{HMAC}(K, \text{SHA256}(l.createdAt) \| \text{SHA256}(l.message))$ (или любую другую криптографическую хеш-функцию). Это гарантирует, что злоумышленник не сможет осмысленно манипулировать значениями, которые я объединяю. Это также гарантирует, что конкатенированные значения всегда имеют фиксированную длину. Добавляет ли хеширование какую-либо ценность по сравнению с первой идеей?

3. Аутентифицировать все структурированные данные

Я также мог бы рассчитать MAC для всего объекта JSON записи журнала. По сути, это означает, что у меня есть более сложные, осмысленные разделители (ключи и синтаксис). В общем, как JWT. Обратите внимание, что этот подход также имеет некоторые недостатки, которые в основном сводятся к потере гибкости API и необходимости канонизировать JSON. Об этом есть отличная запись в блоге на https://latacora.micro.blog/2019/07/24/how-not-to.html.


Я пропускаю какие-либо хорошие решения для этой проблемы? Есть ли рекомендуемый способ справиться с этим?

poncho avatar
флаг my
Одним из альтернативных решений было бы предварять каждую запись ее длиной; например $HMAC_k( len(createdAT) | createdAT | len(сообщение) | сообщение)$. Конечно, вам нужен какой-то канонический способ преобразования длины в строку байтов; например всегда преобразовывайте его в 4-байтовое значение с прямым порядком байтов...
leftfold avatar
флаг sr
Хорошая точка зрения! Я забыл это. Я прочитал [что Эфириум делал это] (https://medium.com/mycrypto/the-magic-of-digital-signatures-on-ethereum-98fe184dc9c7), а затем изменил на `32 || Keccak256(сообщение)` (поскольку хэш всегда 32 байта). К сожалению, из статьи мне не понятна мотивация этого изменения.
poncho avatar
флаг my
Еще одна вещь, которую вам нужно включить в свой MAC, — это метки полей; если злоумышленник может преобразовать «createdAT: time» в «deleteBY: time», ну, это то, что мы хотели бы обнаружить...
leftfold avatar
флаг sr
Верно, хотя зависит от варианта использования и от того, как клиент выполняет проверку. Я предполагаю, что когда клиент вычисляет MAC для проверки, он ищет `l.createdAt` и использует это значение для MAC. Если поля `createdAt` нет, то объект, полученный с сервера, уже недействителен. (`deletedBy` потенциально игнорируется.) Тем не менее, если мы хотим рассматривать весь JSON как один «документ», мы должны включить метки. Я считаю, что это очень близко к канонизации и аутентификации всего JSON, как указано в третьей идее.
Maarten Bodewes avatar
флаг in
Для записей в журнале я бы отдельно использовал MAC для канонизированных сообщений, но я бы включил счетчик. Вы все равно захотите иметь централизованное ведение журнала, и я бы не хотел включать счетчик субнаносекунд или выполнять трюки, такие как ожидание по крайней мере наносекунды, прежде чем продолжить. Если синхронизация является проблемой, вы можете указать идентификатор службы или что-то подобное. Базы данных хороши в таких вещах.
Рейтинг:0
флаг sr

Чтобы частично ответить на мой собственный вопрос здесь: идея 1 на самом деле небезопасна.

Это становится проблематичным, если разделитель все-таки появляется в значении. Рассмотреть возможность с использованием , как разделитель значений Привет, и Мир. Вперемешку с , это дает Привет, мир, где первая запятая является частью сообщения, а вторая — разделителем. К сожалению, значения Привет и ,Мир выдать одно и то же сообщение. Таким образом, интуиция о том, что составленное сообщение должно быть разборчивым, кажется, в конце концов верна.

Как указал @poncho в комментариях, это можно исправить, добавив длину поля к каждому полю вместо использования разделителей.

Лично я, вероятно, выберу вторую версию (хэширование значений перед объединением). Но мне все равно было бы интересно, сталкивался ли кто-нибудь с этим и как вы его решили.

Ответить или комментировать

Большинство людей не понимают, что склонность к познанию нового открывает путь к обучению и улучшает межличностные связи. В исследованиях Элисон, например, хотя люди могли точно вспомнить, сколько вопросов было задано в их разговорах, они не чувствовали интуитивно связи между вопросами и симпатиями. В четырех исследованиях, в которых участники сами участвовали в разговорах или читали стенограммы чужих разговоров, люди, как правило, не осознавали, что задаваемый вопрос повлияет — или повлиял — на уровень дружбы между собеседниками.