Обеспечение полноты и достоверности данных в стороннем хранилище

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

Пример:

У меня есть два доверенных объекта TA и TB, эти объекты должны иметь возможность изменять данные, хранящиеся в облачном/ненадежном хранилище, но никто другой. Поэтому мое решение я оснащаю TA и TB общедоступными ключами, и у меня есть структура данных, которую можно сравнить с таблицей с версиями:

 Ver | Data | Signature       | Signee
  4  |  ... | (AAAAAAAAA)_TA  | TA
  3  |  ... | (ZZZZZZZZZ)_TB  | TB
  2  |  ... | (YYYYYYYYY)_TA  | TA
  1  |  ... | (XXXXXXXXX)_TA  | TA

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

Однако я также хотел бы проверить полноту записи. Скажем, TA загружает версию 4, но TB знает только все записи до версии 3. Теперь поставщик хранилища может полностью отказаться от версии 4, когда TB запрашивает ее.

Поскольку между TA и TB нет прямого бокового канала, невозможно обменять текущую версию. Есть ли способ обойти это?

Я подумывал о том, чтобы периодически вставлять фиктивные записи, чтобы хотя бы некоторое время убедиться. Тем не менее, этот подход не обладает масштабируемостью и приведет к большому количеству накладных расходов на хранение и подписи. Каково фактическое системное свойство, которое я ищу (трудно найти исследование для чего-то, чего вы не знаете)?

Ответ 1

Эта проблема не полностью разрешима без фиктивных записей:

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

Таким образом, вам придется периодически подписывать обновления "без изменений". Вы не сможете избежать накладных расходов на подписку, но вам не нужно хранить все эти данные. Вы делаете отдельную таблицу "lastupdate":

 Signer | Last | Timestamp | Signature
  TA    |  4   | 2013-1... | (TA;4;2013-1...)_TA
  TB    |  3   | 2013-1... | (TB;3;2013-1...)_TB

Значение "Signer TA подтверждает, что с 2013-1... последняя версия, отправленная мной, была 4". Если поставщик хранилища не может показать вам текущее подтверждение от всех подписчиков о том, что они не выпустили более новую версию, вы должны предположить, что он что-то скрывает (или что-то сломалось - в любом случае, данные не обновлены). Любой новый подписанный оператор заменяет более старые из этого подписавшего, потому что теперь они неактуальны.

Теперь, если у вас нет только одной версии с версией, но большого числа из них, вам необязательно иметь один такой фиктивный журнал на "вещь". Например, вы могли бы рассчитать хеш (или хеш-дерево) по всем самым последним линиям вашего подписывающего лица (например, "Thing A, Version 3. Thing B, Version 7. Thing C, Version 2." ), а затем просто поместите хэш или корень дерева хешей в таблице lastupdate.

Если вы действительно хотите избежать дополнительных подписей, и некоторые вещи обновляются постоянно, вы можете включить хеш и метку времени в подписи записей о версиях, которые вы подписываете, - самая последняя подписанная запись будет тогда достаточным доказательством для свежести, и если он был слишком старым, вы все равно можете использовать таблицу "lastupdate". Это не стоит сложности, ИМХО.

Ответ 2

Если проблема связана с целостностью записи, я бы рекомендовал использовать MAC (Message Authentication Code). В этом случае вы должны использовать криптографию с симметричным ключом и намного эффективнее криптографических подписей (асимметричных).

Я думал о двух направлениях:

  • Вы можете уменьшить свою проблему, чтобы зафиксировать целостность. Если у вас есть определенные важные данные, которые вы хотите проверить, вы можете просто создать определенную таблицу в хранилище, которая сохраняется, когда каждый из доверенных лиц обновляет каждую из ваших важных переменных. Важные данные могут быть примерно такими: количество записей (общее количество, новое, согласно какой-либо категории), последняя версия и т.д. Когда кто-то делает изменения, которые влияют на важные данные, он обновляет соответствующую запись в пространственной таблице и подписывает запись - и запись также содержит дату последнего обновления. Теперь, чтобы предотвратить невосстановленное хранилище от возврата старых записей или таких вещей, каждая из доверенных сторон должна обновлять записи не реже одного раза в каждый промежуток времени (например, один день) - записи могут не изменяться (только дата в запись), и знак изменится (теперь знак находится позже). Когда сущность читает информацию, он может проверить, что данные являются подлинными и верно для (в примере) не более, чем за один день до этого. Если дата возвращенной записи старше одного дня, она не должна рассматриваться. Вы можете изменять частоту периодических обновлений в соответствии с вашими потребностями. Для этой опции вы можете использовать MAC вместо подписей (для повышения эффективности).

  • Вы можете попробовать другую стратегию: вы не можете проверить полноту каждого обновления, но можете попытаться поймать ненадежное хранилище, если оно пытается лгать! Вы можете сделать это, планируя обновления и запрашивая их.

Последняя вещь - Вы писали:

Поскольку между TA и TB нет прямого бокового канала, нет способа для обмена текущей версией. Есть ли способ обойти это?

Я считаю, что вы имели в виду канал связи. Боковой канал - это нечто другое. Если бы это был я, я бы просто создал такой канал связи для решения проблемы. И, кстати, аналогично первому варианту, который я описываю, вы можете создать такой канал:

Создайте таблицу сообщений из разных объектов, где они объявляют о важных изменениях, которые они сделали, и подписывают их с датой изменения:

Сущность | Изменения | Дата | Подпись (или MAC)

Как и в первом варианте, каждый объект должен добавить такое сообщение после каждого определенного предопределенного периода времени - и у вас есть доверенный канал связи между объектами.