Поддержание целостности сообщения - PullRequest
6 голосов
/ 02 апреля 2009

У меня есть сообщение, которое я передаю себе, которое подвергнется атакам «человек посередине». В связи с этим меня беспокоит целостность сообщения, которое сохраняется между временем, когда я его отправляю, и временем, когда я получаю его обратно.

Следует предположить, что после того, как я отправлю сообщение себе, никакая информация об отправленном сообщении не будет мне доступна в будущем. Сообщение полностью автономно.

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

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

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

В этом сценарии у меня есть набор пар ключ / значение. Для этого я должен предпринять следующие шаги:

  1. Добавьте соль к сообщению. Соль является секретом для остального мира. Он прикрепляется к содержимому сообщения перед хэшированием.
  2. Закажите пары ключ / значение в согласованном порядке, прежде чем генерировать хеш.
  3. Хотя это не напрямую и имеет отношение к делу, к содержимому каждого сообщения будет добавлена ​​временная метка перед хэшированием, чтобы предотвратить повторные атаки.

Это дополнительные шаги, которые я рассматриваю:

  1. Преобразование ключей, прежде чем я их закажу. Я подумал о том, чтобы поменять их, затем упорядочить по количеству / ключу.
  2. Игра с разделителями, которые разделяют пары ключ / значение (как для разделителя для ключа / значения, так и для разделителя для пары).

Примечание

Конфиденциальность сообщений здесь не является обязательным требованием, поэтому я не ищу шифрование. Значения должны передаваться в виде простого текста.

Наконец, каких алгоритмов хеширования мне следует избегать?


Особенности

У меня есть сайт ASP.NET MVC, на котором у меня есть контроллер, который управляет проверкой и сохранением ввода.

Если (на основе эвристики не важно, какой) вход определяется как автоматическая попытка спама, создается модель IDictionary<string, string> с входными значениями и ViewResult отправляется на общую страницу CAPTCHA.

В этом представлении в форме, содержащей элемент управления CAPTCHA, содержимое IDictionary<string, string> будет записано в скрытых полях ввода, а действие формы будет таким же, как и содержимое, которое было первоначально опубликовано. , Таким образом, MVC может получить значения при повторной отправке формы.

Именно по этой причине я не могу зашифровать пары ключ / значение (или, может быть, я могу и должен сказать, почему и как!).

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

Решение

Я решил использовать класс SignedCms в пространстве имен System.Security.Cyrptography.Pkcs, который представляет собой подписывание и проверку сообщений CMS / PKCS # 7.

Чтобы уточнить, я создал самостоятельно выданный сертификат с помощью MAKECERT.EXE, а затем в своем коде я использую приведенный здесь пример для цифровой подписи данных:

http://blogs.msdn.com/shawnfa/archive/2006/02/27/539990.aspx

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

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

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

Спасибо всем, кто внес свой вклад.

Ответы [ 5 ]

6 голосов
/ 02 апреля 2009

Я думаю, что PGP / GPG - это то, что вы хотите здесь.

2 голосов
/ 02 апреля 2009

Самый простой подход, позволяющий вашему приложению проверить, что его собственные сообщения не были подделаны, состоит в использовании ключевого кода аутентификации хеш-сообщения. Сообщение отправляется в незашифрованном виде, но оно также содержит хеш-код для предотвращения взлома. Хеш зависит как от содержимого сообщения, так и от секретного ключа. Человек посередине не может подделать хеш измененного сообщения, не зная ключа. Поскольку ваше приложение создает и проверяет сообщения, оно никогда не должно раскрывать секретный ключ.

Я бы особенно рекомендовал реализацию, описанную в RFC-2104 http://www.ietf.org/rfc/rfc2104.txt, так как она была тщательно продумана, чтобы избежать большинства возможных ошибок.

Если сообщения также должны быть проверены на подлинность ненадежными сторонами, вам следует вместо этого использовать схему цифровой подписи.

Вероятно, есть некоторая поддержка в библиотеках .Net. Майлз услужливо предоставил (в качестве комментария) ссылку на веб-страницу MSDN для функций библиотеки .Net, реализующих HMAC с ключами с использованием хэша SHA1: http://msdn.microsoft.com/en-us/library/system.security.cryptography.hmacsha1.aspx.

1 голос
/ 02 апреля 2009

Вы хотите сообщение с цифровой подписью . Используя GPG, вы можете подписать сообщение без его шифрования. Но никто не сможет подделать его, потому что они не могут сгенерировать хеш - только вы можете, потому что хеш использует ваш закрытый ключ .

0 голосов
/ 02 апреля 2009

Предполагая, что вы не можете передавать какую-либо информацию по «безопасному» каналу (т.е. хешу), вот как вы это сделаете:

  1. Хешируйте сообщение, затем подпишите хэш с закрытым ключом. Включите подписанный хеш в сообщение.
  2. Получив сообщение, используйте открытый ключ, чтобы расшифровать подписанный хеш и убедиться, что он соответствует фактическому хешу сообщения.

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

Как уже упоминали другие, это просто обычная цифровая подпись и может обрабатываться чем-то вроде PGP / GPG

0 голосов
/ 02 апреля 2009

Вероятно, вам следует подписать сообщение цифровой подписью (следовательно, PGP / GPG, рекомендованный Kalium, уместен в качестве опции). Любой чистый хеш, который вы можете создать, может быть воссоздан атакующим. Цифровая подпись - использование вашего личного ключа подписи, чтобы ваш открытый ключ мог быть использован для его проверки - это решение. Все остальное - бесполезное упражнение.

...