Простая проблема криптографии, которая будет реализована в PHP - PullRequest
2 голосов
/ 18 апреля 2009

Мне нужно реализовать несколько функций, которые соответствуют следующим требованиям:

  1. функция genKey: учитывая строку q (это может быть хеш MD5 или SHA) и начальную строку, функция должна генерировать новую строку p

  2. function checkKey: эта функция должна возвращать true, если строка p была сгенерирована из строки q (с использованием предыдущей функции)

В seudo-коде выше было бы что-то лежать так:

p=genKey(q,seed) ; // generate string p from q and seed 

checkKey(p,q)==true ; // if p was generated from q, then this must return true. False otherwise.

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

Ответы [ 6 ]

4 голосов
/ 18 апреля 2009

Похоже, вы пытаетесь описать MAC.

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

Получатель сообщения, который знает секрет, может выполнить такое же вычисление дайджеста и сравнить свой MAC с тем, который сопровождал полученное сообщение. Если они равны, он может верить, что сообщение не было изменено.


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

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

Используя цифровые подписи, вы можете сделать что-то вроде этого:

p = genKey(pvt, seed)
checkKey(pub, p)

Здесь pvt - это закрытый ключ сервера, pub - его открытый ключ. Параметр seed - это данные, которые подписываются. Если я понимаю ваше приложение (в чем я сомневаюсь), seed должен быть идентификатором клиента. Тогда p - это формат сообщения, объединяющий seed и его подпись. Ваш вопрос сбивает с толку, поскольку q используется как для генерации, так и для проверки p - как общий секрет.

Однако в этой схеме (или в схеме MAC) нет ничего, чтобы помешать одному клиенту использовать значение другого p. Все, что вы можете сделать с такой техникой, это убедиться, что содержание сообщения не было изменено. Например, если сообщение выглядит как «clientID = Alice, IPAddress = 192.168.1.1», вы можете убедиться, что Мэллори не подставил свой собственный IP-адрес для Алисы.

Но если сообщение просто "clientID = Alice", вы не можете помешать Алисе дать Бобу ее защищенное от несанкционированного доступа сообщение (взамен на разделение стоимости лицензии), и вы не можете контролировать, взламывает ли Мэллори в ящик Алисы и крадет сообщение.

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

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

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

Для этого обсуждения давайте p == hash (q)

После этого вы можете легко использовать OpenSSL с php, чтобы подписать 'p' закрытым ключом и сохранить эту подпись вдоль стороны 'p'.

Тогда просто использовать функцию проверки OpenSSL, чтобы проверить 'p' по сигнатуре, используя открытый ключ, который связан с вашим закрытым ключом. В этом случае 'p' будет данными для проверки.

См. openssl_sign и openssl_verify для получения информации и примеров использования OpenSSL в php для подписи и проверки данных:

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

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

В основных подписях RSA вы создаете подпись s , применяя следующую математику:

s = m^d % n

Где m - это сообщение (или строка q для вас), d - это закрытый ключ, n - это модуль (общий для частного и открытый ключ).

Тогда это можно проверить с помощью этой математики:

 m = s^e % n

Где e - открытый ключ.

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

Для получения дополнительной информации и математики, проверьте эту страницу.

РЕДАКТИРОВАТЬ: Я подумал, что должен упомянуть, почему вы хотите использовать криптографию с открытым ключом. По сути, он защищает от двух вещей: сообщение поддается проверке и не может быть подделано.

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

Вы можете попробовать что-то вроде этого:

$p = genKey($q,rand());
checkKey($p,$q) == true;


function genkey($q,$seed)
{
    if(array_search($_SESSION['seeds'],$seed) === FALSE)
    {
        $_SESSION['seeds'][] = $seed;
    }
    return hash("sha512", $q . $seed);
}

function checkKey($p,$q)
{
    $returnVal = false;
    foreach($_SESSION['seeds'] AS $s)
    {
        if(hash("sha512", $q . $s) == $p)
        {
            $returnVal = true;
            break;
        }
    }
    return $returnVal;
}

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

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

Вы можете использовать либо <a href="http://us.php.net/crypt" rel="nofollow noreferrer">crypt()</a>, <a href="http://uk3.php.net/manual/en/function.hash.php" rel="nofollow noreferrer">hash()</a>, либо <a href="http://uk3.php.net/manual/en/function.md5.php" rel="nofollow noreferrer">md5()</a>.

Edit: Я не против понижать голос. Глядя на сложность других ответов, я, должно быть, неправильно понял вопрос. Но было бы хорошо, если бы люди сопровождали свои отрицательные голоса комментарием, чтобы я хотя бы знал, что не так с моим ответом.

Что я понял из вопроса, так это то, что спрашивающий хочет реализовать что-то вроде:

function genKey($q, $seed) {
  // assuming $seed is a properly formatted md5/sha salt
  return crypt($q, $seed);
}

function checkKey($p, $q, $seed) {
  return ($p == genKey($q, $seed));
}

Я ошибаюсь, полагая, что для достижения этой цели может быть использована любая из функций одностороннего шифрования PHP?

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

Будет ли сторона проверки иметь доступ к посевным материалам? Если на стороне проверки (например, в веб-приложении) можно обеспечить безопасность семени, вы можете легко сделать что-то вроде HTTP Digest-аутентификации, используя MD5.

псевдокод:

   function genKey(q) {
      p = md5sum(q . ':' . seed);
      return p;
   }

   function checkKey(p,q) {
      return md5sum(q . ':' . seed) == p;
   }

Если вам нужна вторая сторона для проверки "подписи", вам, вероятно, просто захочется использовать PKI.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...