Подтвердить что ты не робот

Как защитить небольшой php api с открытым и закрытым ключом

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

Это хороший способ или это опасно делать?

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

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

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

Из того, что я прочитал и понял от него, это должно быть так.

  • открытый ключ хранится в приложении, чтобы позволить пользователю или приложению войти.
  • сервер создает закрытый ключ для этого конкретного пользователя при его доступе. Или это должно быть всегда одинаковым или статическим значением, созданным человеком?
  • пользователь делает запрос отправляет вместе с запросом подпись, которая hash_hmac (некоторые значения + закрытый ключ); Сервер
  • проверяет правильность этих значений и делает, создавая один и тот же хэш из значения, которое отправляется.
  • Если сервер генерирует один и тот же хеш, запрос действителен и может быть выполнен.
  • Это их путь, или я не вижу здесь каких-то мэров.

Для того, чтобы получить данные, это способ, способный создать хэш?

$l_sPrivateKey = 'something returned by database when user loged in';
$l_aData = array();

foreach($_POST as $key => $value){
 if($key == 'signature') continue;
 $l_aData[$key] = $value;
}

//This should then be the same as $_POST['signature'];
hash_hmac('sha256',serialize($l_aData),$l_sPrivateKey, false); 

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

4b9b3361

Ответ 1

Протокол безопасного удаленного пароля (SRP6a) с HMAC подходит для ваших требований

Далее предполагается, что ваш API является браузером для сервера, поэтому JavaScript-to-PHP не сервер-сервер, использующий только PHP. SRP будет работать для обоих сценариев, но ниже будет рассмотрена библиотека "браузер-сервер".

Используйте протокол Secure Remote Password для аутентификации пользователя API, который имеет побочный эффект создания сильного сеансового ключа. Затем вы можете использовать общий сильный сеансовый ключ для подписывания запросов и ответов API с помощью HMAC.

RFC5054 использует SRP вместо открытых ключей для создания общего ключа сеанса для шифрования трафика TLS. Существует реализация в OpenSSL. Это демонстрирует, что аутентификация SRP является совершенно безопасной заменой открытым ключам для создания безопасного общего секрета. ИМХО, использующее SRP, более удобно решать вашу проблему.

Библиотека Thinbus SRP представляет собой библиотеку SRP JavaScript, которая имеет демоверсию на сервере PHP. Демоверсия PHP не отображается с использованием общего ключа сеанса, но просто он $srp->getSessionKey() на сервере и client.getSessionKey() в браузере после завершения протокола аутентификации. Конфигурация Thinbus по умолчанию имеет общий 256-разрядный ключ. Вы можете использовать это с помощью HMAC, см. Сноску 1 ниже о использовании подписанного JSON.

Как это работает

Регистрирующий поток:

  • Форма регистрации API-клиента генерирует случайный пароль API с использованием JavaScript на клиенте, который не передается на сервер. Это сохраняется в локальном хранилище браузера и отображается пользователю с просьбой распечатать его и сохранить резервную копию.
  • Пароль передается в библиотечный код JS-клиента клиента Thinbus SRP, который выводит идентификатор клиента и пароль.
  • Соль и верификатор отправляются на сервер и сохраняются в базе данных для этого клиента. Обычно Thinbus рекомендует сохранить скрытый верификатор с помощью HTTPS, чтобы отправить верификатор на сервер, чтобы предотвратить атаки грубой силы, чтобы восстановить пароль. Если вы используете случайный сгенерированный пароль до тех пор, пока это типичный лицензионный ключ программного обеспечения, вы можете передать верификатор через HTTP. См. Сноску 2 ниже.

Поток использования API начнется с аутентификации SRP клиента, которая имеет побочный эффект генерации ключа сеанса. Обратите внимание, что все это в демо-коде Thinbus как "стандартное использование", но здесь объясняется, как работает аутентификация STP. Этот протокол аутентификации показан в диаграмме последовательности страницы тонкого шифра и работает в онлайн-демонстрационных версиях:

  • Клиентский javascript загружает пароль API из локального хранилища браузера.
  • Клиент AJAX извлекает с сервера клиентскую соль и случайный одноразовый номер сервера B.
  • Клиент javascript генерирует одноразовый номер A, затем использует пароль, соль и оба одноразовых номера, чтобы сгенерировать сеансовый ключ K и хэши, которые с использованием одноразовых номеров для создания пароля M, который он отправляет на сервер вместе со своим случайным A.
  • Сервер использует верификатор паролей, сохраненный в базе данных при регистрации, соль клиента, и два случайных числа для вычисления ключа сеанса K, а затем подтверждает, что проверенный клиентом пароль M хорош. Если это все хорошо, он отправляет свое собственное доказательство M2 обратно клиенту. На этом этапе клиент был аутентифицирован с использованием STP в качестве нулевого доказательства пароля.
  • Клиент проверяет M2 на его вычисление. Если все хорошо, обе стороны имеют общий секрет K, который является одноразовым 256-битным сеансовым ключом, полученным из случайных A и B, которые невозможно знать человеку-в-середине.
  • Все запросы и ответы API могут быть подписаны HMAC с общим секретом и проверены с другой стороны.

Все вышеописанное описано в демонстрации PHP Thinbus минус, фактически называя $srp->getSessionKey() в конце, чтобы иметь ключ, который можно использовать для подписи с помощью HMAC.

Дайте, что SRP заменяет аутентификацию паролем криптографическим доказательством пароля с нулевым знанием. Удивительно, что не все разработчики используют его по умолчанию. Тот факт, что он также генерирует общий ключ сеанса для подписи API, - это просто дополнительный бонус.


Сноска 1:Большинство API-интерфейсов предпочитают размещать одно значение JSON со всеми данными в нем. Это связано с тем, что JSON прост, но более мощный со встроенным API в PHP и JavaScript, чтобы превращать объекты в строки и обратно. Как отметил @dbrumann в комментарии, существует стандарт для подписания JSON, который является JWT. Google предлагает, чтобы здесь были библиотеки для этого как в PHP, так и в JavaScript. Поэтому, если вы обновляетесь до передачи одного входного значения JSON и возвращаете один вывод JSON для каждой команды в вашем API, Ayou может использовать библиотеку JWT для подписи и проверки входов и выходов JSON API. Одним из алгоритмов JWS является "JWSAlgorithm.HS256 - HMAC с SHA-256, 256 + бит секрет". Библиотеки будут разбирать механику фактического подписания и проверки, поэтому вам не нужно писать этот код и беспокоиться о возможных ошибках безопасности.

Сноска 2: Рекомендация с Thinbus заключается в том, чтобы передать верификатор пароля на сервер через HTTPS, чтобы сохранить верификатор в секрете. Это необходимо для предотвращения перехвата, а затем автономного словаря атаки на верификатор пароля для восстановления пароля (т.е. Пароль солен в верификаторе, поэтому вам нужно будет запустить 16G пароль пользователя crackstation через код генерации верификатора с помощью соли пользователя, чтобы найти совпадение). При использовании API браузер window.crypto API может генерировать по-настоящему случайный "ключ API". Обычно клавиши Windows составляли 16 букв в верхнем регистре, отображаемых пользователю, отформатированному как XXXX-XXXX-XXXX-XXXX. Проверяя страницу поиска пароля в формате GRC, он говорит, что случайный пароль на 16 букв в верхнем регистре, размер которого займет 14 лет для полного поиска. Учитывая эту оценку, вы можете безопасно передавать верификатор паролей, сгенерированный для такого длинного случайного пароля по простому HTTP без шифрования, так как никто не выполнит многолетнюю вычислительную мощность, чтобы запускать так много догадок с помощью алгоритма генерации верификатора (который использует случайные клиентская соль поэтому не может быть предварительно вычислена), чтобы найти совпадение для восстановления пароля API-клиента.