Зачем использовать ключ и секрет API?

93

Я встречал множество API, которые предоставляют пользователю как ключ API, так и секрет . Но мой вопрос: в чем разница между ними?

На мой взгляд, одного ключа может хватить. Скажем, у меня есть ключ, который знают только я и сервер. Я создаю хеш HMAC с этим ключом и выполняю вызов API. На сервере мы снова создаем хеш HMAC и сравниваем его с отправленным хешем. Если это то же самое, вызов аутентифицируется.

Так зачем использовать два ключа?

Изменить: или этот ключ API используется для поиска секрета API?

EsTeGe
источник
Также см.
Дорогая,

Ответы:

46

Криптография с секретным ключом основана на использовании одного и того же ключа для кодирования и последующего декодирования сообщения. Таким образом, только те, кто знает «секрет», могут прочитать сообщение.

Безопасность RSA основана на 2 совпадающих ключах. У каждого пользователя есть открытый ключ, и каждый может (должен) его знать. Также существует закрытый ключ, который должен знать только пользователь. Сообщение, зашифрованное открытым ключом, может быть расшифровано только закрытым ключом, и наоборот.

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

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

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

ИЛИ

вы можете посетить эту ссылку для более подробного объяснения.

Как работают ключи API и секретные ключи?

Салман
источник
9
Хороший ответ, но когда я использую секреты и ключи API с Facebook, Gmail и т. Д., Мне ни в коем случае не нужно шифровать или хешировать что-либо. В чем тогда смысл секретов и ключей API?
Quintonn
2
Используя Facebook в качестве примера, вы можете использовать app_secret в двух сценариях. Первый не требует хеширования. В основном он используется для предотвращения взлома вашего URL-адреса перенаправления. После того, как пользователь войдет в систему и предоставит вашему приложению доступ, если facebook отправил токен доступа непосредственно на URL-адрес перенаправления, у вас не будет возможности проверить, был ли токен доступа от Facebook. Я мог бы опубликовать свой собственный токен доступа к вашему URL-адресу перенаправления и выполнить действия facebook, которые будут исходить из вашего api. Вместо этого facebook отправляет код на URL-адрес перенаправления. Затем api обменивает код на фактический токен доступа.
Райан Томас
2
Во второй части, обменивая код на фактический токен доступа, facebook ожидает, что ваш api подтвердит его личность с помощью подписи. В этом сценарии им не требуется криптография с открытым ключом для подписи, они просто доверяют вам хранить секрет своего приложения в секрете и использовать его в качестве своей подписи. Мне всегда казалось глупым не пойти дальше и не использовать одностороннюю функцию для генерации подписи, но я полагаю, что у них есть причины, такие как производительность, для прямого использования секрета приложения.
Райан Томас
Во втором случае вы используете криптографическое хеширование. После того, как у вас есть фактический access_token для начала взаимодействия с facebook, вам может потребоваться дополнительная безопасность, чтобы предотвратить олицетворение вашего приложения. В консоли приложения Facebook вы можете включить функцию, которая требует, чтобы каждый запрос API facebook от вашего приложения включал вашу подпись в дополнение к токену доступа. Я просто догадываюсь об их мотивах, но думаю, что на данный момент они не хотят, чтобы вы неоднократно отправляли app_secret в качестве подписи при каждом запросе. Чем больше вы отправляете, тем больше вероятность взлома app_secret.
Райан Томас
1
Я полагаю, с тех пор, как вы выбрали эту дополнительную функцию безопасности, вы также приняли своего рода решение разрешить дополнительные накладные расходы на производительность Facebook, проверяя вашу подпись с помощью криптографического хеш-вызова на своей стороне. В любом случае в этом сценарии вы передаете два значения с вашими запросами API Facebook. Access_token и значение с именем appsecret_proof, которое служит вашей подписью. Доказательство секретности приложения генерируется криптографическим хешированием access_token с использованием app_secret в качестве ключа.
Райан Томас
55

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

«Ключ» - это ваш идентификатор пользователя, а «секрет» - это ваш пароль. Они просто используют термины «ключ» и «секрет», потому что именно так они это реализовали.

Маркус Адамс
источник
1
А что, если вы общаетесь по https? Какой тогда смысл шифровать ваше сообщение каким-то секретным ключом?
kamuniaft
6
Дело всегда в том, чтобы снизить риск. Если соединение https скомпрометировано, злоумышленник, который может прочитать ваш запрос, не сможет подделать новые. Если ваш API собирается ранжировать изображения кошек, ничего страшного, если это платежный API, вам лучше иметь несколько уровней безопасности :)
Yall
Я полагаю, что это два отдельных ключа, потому что разные пользователи одного клиентского приложения могут иметь разные секреты, в противном случае, если бы у них был один и тот же секрет, то наличие ключа было бы бесполезным. Правильно?
Honey
Почему этот API не использует Bearer:для этого аутентификацию? У вас там будет ID и pwd.
Стефан Хаберл
7

Простой ответ, если я правильно понял ...

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

Вы используете ключ API, чтобы указать, кто вы, это то, что вы отправляете в виде обычного текста. СЕКРЕТНЫЙ ключ вы никому не отправляете . Вы просто используете его для шифрования. Затем вы отправляете зашифрованное сообщение. Вы не отправляете ключ, который использовался для шифрования, это нарушило бы цель.

анкайский
источник
Ты сделаешь. Вы отправляете ключ api на сервер. Итак, это означает, что вы придаете эту ценность любому, кто может перехватить ваше общение с сервером.
ancajic
Почти в каждом API, который я видел, вы отправляете на сервер и ключ, и секрет. Соединение с сервером зашифровано с теоретически таким же уровнем безопасности. Но я никогда не отдаю никому, кроме сервера.
sudo
Я никогда не видел отправки secretв виде обычного текста. Можете дать ссылку? То, что я видел, используется secretдля шифрования некоторых данных. И вместе с зашифрованными данными отправка, apiKeyчтобы сервер знал, как их расшифровать.
ancajic
twilio.com/docs/sms/tutorials/… и nexmo.github.io/Quickstarts/sms/send - это примеры, которые я видел, которые побудили меня искать в StackOverflow.
sudo
Twilio не совсем использует эти термины. Но Nexmo уверенная ... Но, после того, как быстрый взгляд, кажется , что они просто звонят данные secretи apiKeyи то , что они на самом деле делают это usernameи password. Это совсем другое ...
Анкаджич
3

Есть ответы, объясняющие, что такое секретный и (открытый) ключ. Это пара открытого и закрытого ключей, которой они дают запутанные имена. Но никто не говорит, почему API требуют и того, и другого, а многие API дают вам только один секрет! Я также никогда не видел, чтобы документы API объясняли, почему у них два ключа, поэтому лучшее, что я могу сделать, это предположить ...

Лучше всего указать в запросе только свой открытый ключ и подписать запрос локально своим закрытым ключом; посылать больше ничего не нужно. Но некоторым удается просто раскрыть секрет в запросе. Хорошо, любой хороший API будет использовать некоторую транспортную безопасность, такую ​​как TLS (обычно через HTTPS). Но вы по-прежнему открываете свой закрытый ключ серверу таким образом, увеличивая риск того, что он каким-то образом неправильно его обработает (см. Недавно обнаруженная ошибка регистрации паролей в GitHub и Twitter). И HTTPS теоретически так же безопасен, но всегда есть недостатки в реализации.

Но во многих - на самом деле, кажется, в большинстве - API вы отправляете оба ключа в запросах, поскольку это проще, чем заставлять людей делать свои собственные подписи; иначе не может быть чистых примеров cURL! В таком случае бессмысленно разделять их. Я предполагаю, что отдельные ключи нужны только на тот случай, если они позже изменят API, чтобы воспользоваться ими. Или у некоторых есть клиентская библиотека, которая может сделать это более безопасным способом.

судо
источник
1

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

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

Имея вторую часть информации или «секрет», вы можете сначала найти пользователя или учетные данные с помощью «ключа», который может быть уязвим для временной атаки, а затем использовать безопасную по времени функцию сравнения, чтобы проверить значение секрет".

Вот реализация этой функции в Python:

https://github.com/python/cpython/blob/cd8295ff758891f21084a6a5ad3403d35dda38f7/Modules/_operator.c#L727

И он представлен в hmacбиблиотеке (и, возможно, в других):

https://docs.python.org/3/library/hmac.html#hmac.compare_digest


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

Тогда решениями для хранения ключей API будут:

  1. Используйте отдельный ключ и секрет, используйте ключ для поиска записи и используйте безопасное по времени сравнение для проверки секрета. Это позволяет вам снова показать пользователю ключ и секрет.
  2. Используйте отдельный ключ и секрет, используйте симметричное детерминированное шифрование секрета и выполняйте обычное сравнение зашифрованных секретов. Это позволяет вам снова показать пользователю ключ и секрет и избавить вас от необходимости выполнять безопасное по времени сравнение.
  3. Используйте отдельный ключ и секрет, отобразите секрет, хеш и сохраните его, затем выполните обычное сравнение хешированного секрета. Это избавляет от необходимости использовать двустороннее шифрование и дает дополнительное преимущество, заключающееся в сохранении секретности в случае взлома системы. У него есть обратная сторона: вы не можете снова показать секрет пользователю.
  4. Используйте один ключ , один раз покажите его пользователю, хешируйте его, а затем выполните обычный поиск хешированного или зашифрованного ключа. Здесь используется один ключ, но он не может быть снова показан пользователю. Имеет преимущество хранения ключей в безопасности в случае взлома системы.
  5. Используйте один ключ , один раз покажите его пользователю, зашифруйте его и выполните обычный поиск зашифрованного секрета. Может быть снова показан пользователю, но ценой уязвимости ключей в случае взлома системы.

Из них я считаю, что 3 - лучший баланс безопасности и удобства. Я видел, как это реализовано на многих сайтах при выдаче ключей.

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

kbuilds
источник