Подпись URL с помощью HMAC или OpenSSL



Меня интересует подпись url (например, http://.../?somearg=value&anotherarg=anothervalue&sig=aSKS9F3KL5xc), но у меня есть несколько требований, которые оставили меня пока без решения.




  • я буду использовать либо PHP, либо Python для страниц, поэтому мне нужно будет иметь возможность подписывать и проверять подпись, используя один из двух.

  • Мой план состоял в том, чтобы использовать схему ключей priv/pub для подписи некоторых данных и иметь возможность проверить, что подпись действительна, но вот где она появляется сложно:
  • данные неизвестны, когда происходит проверка (это не просто somearg=value&anotherarg=anothervalue)


Моим первым побуждением было использовать OpenSSL, например, с помощью пары ключей RSA, чтобы сделать что-то вроде подписи: openssl rsautl -sign -inkey private.pem -in sensitive -out privsigned и проверки на основе данных privsigned и только ключа: openssl rsautl -verify -inkey public.pem -in privsigned -pubin.

Используя PHP openssl_get_privatekey() и openssl_sign() подписывает данные просто отлично, но мне нужно знать (расшифровано!) данные для проверки (которых у меня не будет): openssl_get_publickey() и openssl_verify($data, $signature, $pubkeyid); из http://php.net/openssl_verify .



Или я что-то упустил?





Поэтому я заглянул в HMAC, но, хотя многие хэш-функции доступны как в Python, так и в PHP, я озадачен тем, как я буду действовать проверка гашиш.
PHP 's hash_hmac() позволяет мне создать хэш, используя "ключ" (или в данном случае строку-ключ). Но как мне проверить, что хэш допустим (то есть &sig= не был просто вручную введен конечным пользователем &sig=abcdefg1234.



Итак, подведем итог (извините за длинный вопрос): Как я могу проверить, что подпись/хэш была сделана ключом моего сервера (cert/string) (учитывая, что я не могу проверить, повторив хэш указанных данных)? И есть ли у вас какие-либо предпочтения относительно того, какой маршрут я должен выбрать, Priv/pub-key или HMAC?



Любые указатели большие или маленькие очень ценятся!
Заранее благодарю,




  • Джош

800   3  

3 ответов:

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

Если вам не нужно, чтобы подписи были проверены кем-то, кто не знает секретный ключ, HMAC, вероятно, является лучшим выбором, чем системы с открытым ключом, по причинам эффективности. Для создания или проверки подписи с открытым ключом может потребоваться несколько миллисекунд (несколько лет назад я рассчитывал одну реализацию на 15 мс за операцию), в то время как HMAC достаточно быстр.

(О, и вы не можете проверить любой вид подписи, не зная данных, которые он должен подписать. Насколько я понимаю, в этом нет никакого смысла).

Как Хеннинг Makholm указал, ксом является лучшим выбором, чем открытого ключа. Есть некоторые рекомендации, которые вы должны рассмотреть для вашего конкретного сценария, которые повлияют на ваш выбор:

  • вы хотите рассмотреть имя хоста и схему (http / https) в подписи? Может быть.
  • Хотите ли вы рассмотреть путь в сигнатуре? Возможно.
  • Хотите ли вы рассмотреть строку запроса в подписи? Возможно.
  • вы хотите нормализовать порядок аргументов а побег до подписания контракта? Обычно нет.
  • вы хотите встроить время подписи и т. д. (Для создания ограниченных по времени URL-адресов)?
  • вы хотите привязать подписанный URL-адрес к какому-либо другому пользовательскому состоянию, например к cookie?
  • используете ли вы пользовательский или видимый пользователем контент непосредственно в HMAC? Если это так, вы должны "посолить" ключ, используя значение, которое рандомизировано для каждого запроса.

При вычислении подписи вам нужно будет закодировать ее удобным для URL способом (base64 и base32 являются популярные варианты) и выбрать алгоритм HMAC (например, SHA-256), а также решить, сколько битов подписи вы хотите сохранить (усечение значения HMAC в два раза обычно безопасно). Если вы выбрали base64, остерегайтесь различных алфавитов, используемых реализациями url-safe и non-url-safe.

Вот реализация псевдокода (без проверки ошибок или соления и т. д.) для подписи пути + строки запроса:

const secret = ...;

def sign(path, querystring):
  return path + "?" + querystring + "&sig=" + url_encode(base64_encode(hmacsha256(secret, path + "?" + querystring).truncate(16)))

def verify(path, querystring):
  querystring_without_sig = remove_query_parameter(querystring, "sig")
  sig = base64_decode(url_decode(get_query_parameter(querystring, "sig")))
  if hmacsha256(secret, path + "?" + querystring_without_sig)[:16] != sig:
    raise "invalid sig"

HMAC SHA256 рекомендуется и доступен во всех распространенных версиях. языки.

Java:

Mac mac = Mac.getInstance("HmacSHA256");
mac.init(secret);
return mac.doFinal(value.getBytes());

Python:

hmac.new(secret, input, hashlib.sha256).digest()

PHP:

hash_hmac("sha256", value, secret);

Если вы хотите использовать HMAC и Python, то:

$ pip install ska

На стороне клиента

from ska import sign_url

signed_url = sign_url(
    auth_user='user', 
    secret_key='your-secret_key', 
    url='http://e.com/api/'
)

Полученный URL выглядит следующим образом.

Http://e.com/api/?valid_until=1378045287.0&auth_user=user&signature=YlZpLFsjUKBalL4x5trhkeEgqE8%3D

На стороне сервера

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

from ska import validate_signed_request_data

validation_result = validate_signed_request_data(
    data = request.GET, # Note, that ``request.GET`` is given as example.
    secret_key = 'your-secret_key'
)

Validate_signed_request_data создает объект SignatureValidationResult, который в основном содержит два свойства:

  • result (bool): True, если данные верны. Ложь в противном случае.
  • причина (список): список строк, указывающих на ошибки проверки.

Comments

    Ничего не найдено.