Как создать цифровую подпись, которую нельзя использовать для повторного воспроизведения сообщения - PullRequest
1 голос
/ 18 февраля 2011

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

Использование алгоритмов открытого / закрытого ключа имеет смысл, и в PHP мы можем использовать функции openssl_sign и openssl_verify, чтобы проверить, что данные получены кем-то, кто имеет закрытый ключ.

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

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

Ответы [ 4 ]

4 голосов
/ 18 февраля 2011

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

3 голосов
/ 18 февраля 2011

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

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

Сервер:

$message = 'foomessage';
$message .= ':' . hash_hmac('md5', $message, $sharedSecret);

Клиент:

list ($message, $hmac) = explode(':', $message, 2);
if ($hmac != hash_hmac('md5', $message, $sharedSecret)) {
    die('invalid signature');
}

Обратите внимание, что это 100%зависит от общего ключа.Если кто-то еще завладеет им, все ваши подписанные сообщения будут подделаны.

Еще один возможный способ обнаружения атаки в стиле сниффера - это использование подхода с синхронизацией.По сути, вы храните номер на сервере и на клиенте.При каждом запросе вы увеличиваете оба числа.Затем вы включаете это число в расчет hmac.Поскольку клиент и сервер общаются друг с другом, оба счета всегда должны быть синхронизированы.Но если они отключены, вы знаете, что произошел какой-то сбой связи, или кто-то ввел команду (угнали) с неправильным счетом.Таким образом, хотя он не будет «предотвращать» атаку повторного воспроизведения напрямую, он сделает его НАМНОГО сложнее, поскольку злоумышленнику потребуется отслеживать каждый отдельный HTTP-запрос между сервером и клиентом.

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

2 голосов
/ 18 февраля 2011

Звучит так, будто вам нужна интерпретация "Одноразового шифра для пэдов" в PHP?

Одноразовый пэд Одноразовый пэд - это длинная последовательность случайных букв.Эти буквы объединяются с открытым текстом для создания зашифрованного текста.Чтобы расшифровать сообщение, человек должен иметь копию одноразовой панели, чтобы полностью изменить процесс.Одноразовый блокнот должен использоваться только один раз (отсюда и название), а затем уничтожаться.Это первый и единственный алгоритм шифрования, который доказал свою необратимость.

Чтобы зашифровать сообщение, вы берете первую букву в текстовом сообщении и добавляете ее к первой случайной букве из одноразовой панели.,Например, предположим, что вы шифруете букву S (19-я буква алфавита), а одноразовый блокнот дает вам C (3-я буква алфавита).Вы добавляете две буквы и вычитаете 1. Когда вы добавляете S и C и вычитаете 1, вы получаете 21, который равен U. Каждая буква зашифрована в этом методе, причем алфавит переносится в начало, если в результате сложения получается число после26 (Z).

Чтобы расшифровать сообщение, вы берете первую букву зашифрованного текста и вычитаете первую случайную букву из одноразовой клавиатуры.Если число отрицательное, вы переходите к концу алфавита.

0 голосов
/ 18 февраля 2011

Создайте хеш (md5) для каждого сообщения и добавьте к нему метку времени.

...