Po co używać klucza i klucza API?

93

Natknąłem się na wiele interfejsów API, które dają użytkownikowi zarówno klucz API , jak i sekret . Ale moje pytanie brzmi: jaka jest różnica między nimi?

Moim zdaniem wystarczy jeden klucz. Powiedzmy, że mam klucz i tylko ja i serwer o tym wiemy. Tworzę skrót HMAC z tym kluczem i wykonuję wywołanie API. Na serwerze ponownie tworzymy hash HMAC i porównujemy go z wysłanym hashem. Jeśli jest taki sam, połączenie jest uwierzytelniane.

Po co więc używać dwóch kluczy?

Edytuj: czy też ten klucz API jest używany do wyszukiwania tajnego klucza API?

EsTeGe
źródło

Odpowiedzi:

46

Kryptografia klucza tajnego polega na użyciu tego samego klucza do kodowania, a następnie dekodowania wiadomości. Dlatego tylko ci, którzy znają „sekret”, mogą przeczytać wiadomość.

Bezpieczeństwo RSA opiera się na 2 dopasowanych kluczach. Dla każdego użytkownika istnieje klucz publiczny i każdy może (powinien) go znać. Istnieje również klucz prywatny, który powinien znać tylko użytkownik. Wiadomość zaszyfrowaną kluczem publicznym można odszyfrować tylko za pomocą klucza prywatnego i odwrotnie.

Tak więc, jeśli chcę wysłać Ci wiadomość, którą tylko Ty możesz przeczytać, otrzymuję (z sieci) Twój klucz publiczny, szyfruję wiadomość tym kluczem i jesteś jedyną osobą, która może ją odszyfrować.

Lub, jeśli chcę ci udowodnić, że wysłałem wiadomość, mogę zaszyfrować wiadomość moim kluczem prywatnym, powiedzieć (w otwartym tekście lub w innej wiadomości), jak została zaszyfrowana. Wtedy możesz odszyfrować wiadomość moim kluczem publicznym, a jeśli stanie się czytelna, wiesz, że pochodzi ode mnie.

Ta forma szyfrowania jest dość obciążająca komputer, więc czasami wykonuje się szyfrowanie jednorazowego „tajnego klucza” za pomocą technologii RSA, a następnie szyfrowanie pozostałej części wiadomości tajnym kluczem, a następnie szyfrowanie mojego podpisu w drugi sposób. Następnie odwracasz ten proces, więc jeśli wiadomość i podpis są czytelne, ty i tylko ty możesz to przeczytać i masz pewność, że wysłałem wiadomość.

LUB

możesz odwiedzić ten link, aby uzyskać bardziej szczegółowe wyjaśnienie.

Jak działają klucze API i tajne klucze?

SALMAN
źródło
9
Dobra odpowiedź, ale kiedy używam sekretów i kluczy API z Facebookiem, Gmailem itp., W żadnym momencie nie muszę niczego szyfrować ani haszować. W takich przypadkach jaki jest sens sekretów i kluczy API?
Quintonn
2
Używając Facebooka jako przykładu, istnieją dwa scenariusze, w których użyjesz app_secret. Pierwsza nie wymaga haszowania. Służy głównie do zapobiegania przejęciu przekierowania URL. Gdy użytkownik zaloguje się i przyzna dostęp do aplikacji, jeśli Facebook wyśle ​​token dostępu bezpośrednio do adresu URL przekierowania, nie będziesz mieć możliwości sprawdzenia, czy token dostępu pochodzi z Facebooka. Mógłbym umieścić własny token dostępu na Twoim przekierowującym adresie URL i wykonać działania na Facebooku, które pochodzą z Twojego interfejsu API. Zamiast tego Facebook wysyła kod do adresu URL przekierowania. Następnie interfejs API wymienia kod na rzeczywisty token dostępu.
Ryan Thomas
2
W drugiej części, wymieniając kod na rzeczywisty token dostępu, facebook oczekuje, że Twój api zweryfikuje swoją tożsamość za pomocą podpisu. W tym scenariuszu nie wymagają kryptografii klucza publicznego do podpisywania, po prostu ufają, że utrzymasz swoją aplikację w tajemnicy i użyjesz jej jako podpisu. Zawsze wydawało mi się głupie, żebym nie używał funkcji jednokierunkowej do generowania podpisu, ale przypuszczam, że mają one powody, takie jak wydajność, aby zdecydować się na bezpośrednie użycie sekretu aplikacji.
Ryan Thomas
W drugim przypadku używasz haszowania kryptograficznego. Gdy masz rzeczywisty access_token, aby rozpocząć interakcję z Facebookiem, możesz potrzebować dodatkowych zabezpieczeń, aby zapobiec podszywaniu się pod Twoją aplikację. W konsoli aplikacji Facebook możesz włączyć funkcję, która wymaga, aby każde żądanie interfejsu API Facebooka z Twojej aplikacji zawierało Twój podpis oprócz tokena dostępu. Zgaduję tylko ich motywy, ale myślę, że w tym momencie nie chcą, abyś wielokrotnie wysyłał app_secret jako podpis przy każdym żądaniu. Im więcej go wyślesz, tym większa szansa na złamanie zabezpieczeń app_secret.
Ryan Thomas
1
Przypuszczam, że skoro zdecydowałeś się na tę dodatkową funkcję bezpieczeństwa, podjąłeś również decyzję, aby pozwolić na dodatkowe obciążenie wydajnościowe Facebooka weryfikującego twój podpis za pomocą kryptograficznego wywołania skrótu na końcu. W każdym razie w tym scenariuszu przekazujesz dwie wartości z żądaniami API Facebooka. Access_token i wartość o nazwie appsecret_proof, która służy jako Twój podpis. Tajny dowód aplikacji jest generowany przez szyfrowanie kryptograficzne access_token przy użyciu app_secret jako klucza.
Ryan Thomas
55

Potrzebujesz dwóch oddzielnych kluczy, jednego, który powie im, kim jesteś, a drugiego, który udowodni, że jesteś tym, za kogo się podajesz .

„Klucz” to identyfikator użytkownika, a „sekret” to hasło. Po prostu używają terminów „klucz” i „sekret”, ponieważ tak to zaimplementowali.

Marcus Adams
źródło
1
A co, jeśli komunikujesz się przez https? Jaki jest więc sens szyfrowania wiadomości jakimś tajnym kluczem?
kamuniaft
6
Zawsze chodzi o to, aby zmniejszyć ryzyko. Jeśli komunikacja https zostanie naruszona, osoba atakująca, która może odczytać Twoje żądanie, nie będzie w stanie sfałszować nowych. Jeśli twoje API ma zamiar oceniać zdjęcia kotów, nic wielkiego, jeśli jest to API płatności, lepiej mieć wiele warstw zabezpieczeń :)
Yall
Przypuszczam, że celem są dwa oddzielne klucze, ponieważ różni użytkownicy jednej aplikacji klienckiej mogą mieć różne sekrety, w przeciwnym razie gdyby wszyscy mieli ten sam klucz, posiadanie klucza nie jest przydatne. Dobrze?
Kochanie,
Dlaczego te API nie używają Bearer:do tego uwierzytelniania? Miałbyś tam identyfikator i pwd.
Stefan Haberl
7

Prosta odpowiedź, jeśli dobrze ją zrozumiałem ...

Jeśli używasz klucza API do szyfrowania, w jaki sposób usługa będzie wiedzieć, kto się z nią kontaktuje? Jak odszyfrują tę wiadomość?

Używasz klucza API, aby określić, kim jesteś, to jest to, co wysyłasz w postaci zwykłego tekstu. TAJNY klucz, którego nikomu nie wysyłasz . Po prostu używasz go do szyfrowania. Następnie wysyłasz zaszyfrowaną wiadomość. Nie wysyłasz klucza, który był używany do szyfrowania, który zniweczyłby cel.

ancajic
źródło
Ty robisz. Wysyłasz klucz API do serwera. Oznacza to, że nadajesz tę wartość każdemu, kto może przechwytywać Twoją komunikację z serwerem.
ancajic
Prawie każde API, które widziałem, wysyłało zarówno klucz, jak i sekret na serwer. Połączenie z serwerem jest szyfrowane z teoretycznie takim samym poziomem bezpieczeństwa. Ale nigdy nie oddaję nikomu poza serwerem.
sudo
Nigdy nie widziałem wysyłania secretzwykłego tekstu. Czy możesz podać link? To, co widziałem, służy secretdo szyfrowania niektórych danych. I wraz z zaszyfrowanymi danymi wysyłane, apiKeyaby serwer wiedział, jak odszyfrować dane.
ancajic
twilio.com/docs/sms/tutorials/… i nexmo.github.io/Quickstarts/sms/send to przykłady, które zobaczyłem, a które skłoniły mnie do wyszukiwania w StackOverflow.
sudo
Twilio nie używa dokładnie tych terminów. Ale Nexmo pewno jest ... Ale, po szybkim rzut oka wydaje się, że są one po prostu wywołanie danych secretoraz apiKeyi to, co rzeczywiście robi, to usernamei password. Zupełnie inaczej ...
ancajic
3

Istnieją odpowiedzi wyjaśniające, czym jest sekret i (publiczny) klucz. Jest to para kluczy publiczny-prywatny, której dają mylące nazwy. Ale nikt nie mówi, dlaczego interfejsy API wymagają obu, a wiele interfejsów API podaje tylko jeden sekret! Nigdy też nie widziałem dokumentów API wyjaśniających, dlaczego mają dwa klucze, więc najlepsze, co mogę zrobić, to spekulować ...

W żądaniu najlepiej umieścić tylko swój klucz publiczny i podpisać żądanie lokalnie kluczem prywatnym; wysyłanie czegoś więcej nie powinno być potrzebne. Ale niektórym uchodzi na sucho po prostu posiadanie tajemnicy w prośbie. Ok, każdy dobry interfejs API będzie używał pewnych zabezpieczeń transportu, takich jak TLS (zwykle przez HTTPS). Ale nadal ujawniasz swój klucz prywatny na serwerze w ten sposób, zwiększając ryzyko, że w jakiś sposób go niewłaściwie obchodzą (zobacz: Niedawno wykryto błąd logowania do GitHub i Twittera). Protokół HTTPS jest teoretycznie równie bezpieczny, ale zawsze są błędy implementacyjne.

Ale w wielu - a właściwie wydaje się to większość - interfejsów API wysyła oba klucze w żądaniach, ponieważ jest to łatwiejsze niż zmuszanie ludzi do składania własnych podpisów; inaczej nie można mieć czystych przykładów cURL! W takim przypadku nie ma sensu ich rozdzielać. Sądzę, że oddzielne klucze są tylko na wypadek, gdyby później zmienili API, aby z nich skorzystać. Niektórzy mają bibliotekę klienta, która może zrobić to w bezpieczniejszy sposób.

sudo
źródło
1

Jedną rzeczą, o której tutaj nie wspomniałem, chociaż jest to rozszerzenie odpowiedzi Marcusa Adamsa, jest to, że nie powinieneś używać jednej informacji do identyfikacji i uwierzytelniania użytkownika, jeśli istnieje możliwość ataków czasowych , co może użyj różnic w czasach odpowiedzi, aby zgadnąć, jak daleko zaszło porównanie ciągów.

Jeśli używasz systemu, który używa „klucza” do wyszukania użytkownika lub danych uwierzytelniających, ta informacja może być odgadywana stopniowo w czasie, wysyłając tysiące żądań i badając czas potrzebny do znalezienia (lub nie) bazy danych znajdź) rekord. Jest to szczególnie ważne, jeśli „klucz” jest przechowywany w postaci zwykłego tekstu zamiast jednokierunkowego skrótu klucza. Chcesz przechowywać klucze użytkowników w postaci zwykłego tekstu lub zaszyfrowanych symetrycznie, jeśli chcesz ponownie wyświetlić klucz użytkownikowi.

Mając drugą informację, „tajną”, możesz najpierw wyszukać użytkownika lub poświadczenie za pomocą „klucza”, który może być podatny na atak czasowy, a następnie użyć funkcji porównywania z bezpiecznym czasem, aby sprawdzić wartość tajemnica".

Oto implementacja tej funkcji w Pythonie:

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

I jest ujawniony w hmacbibliotece (i prawdopodobnie innych):

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


Należy tu zauważyć, że nie sądzę, aby ten rodzaj ataku zadziałał na wartościach, które są zaszyfrowane lub zaszyfrowane przed wyszukiwaniem, ponieważ porównywane wartości zmieniają się losowo za każdym razem, gdy zmienia się znak w ciągu wejściowym. Znalazłem dobre wytłumaczenie tego tutaj .

Rozwiązania do przechowywania kluczy API to:

  1. Użyj oddzielnego klucza i hasła, użyj klucza do wyszukania rekordu i użyj bezpiecznego porównania, aby sprawdzić sekret. Pozwala to ponownie pokazać użytkownikowi klucz i sekret.
  2. Użyj oddzielnego klucza i sekretu, użyj symetrycznego, deterministycznego szyfrowania sekretu i wykonaj normalne porównanie zaszyfrowanych sekretów. Pozwala to na ponowne pokazanie użytkownikowi klucza i tajnego klucza i może uchronić Cię przed koniecznością wdrażania bezpiecznego porównania czasowego.
  3. Użyj oddzielnego klucza i sekretu, wyświetl sekret, zhaszuj i zapisz go, a następnie wykonaj normalne porównanie zaszyfrowanego sekretu. Eliminuje to konieczność korzystania z szyfrowania dwukierunkowego i ma dodatkową zaletę polegającą na zachowaniu tajemnicy w przypadku naruszenia bezpieczeństwa systemu. Ma tę wadę, że nie można ponownie pokazać tajemnicy użytkownikowi.
  4. Użyj jednego klucza , pokaż go raz użytkownikowi, zhaszuj, a następnie przeprowadź normalne wyszukiwanie klucza zaszyfrowanego lub zaszyfrowanego. Używa jednego klucza, ale nie można go ponownie pokazać użytkownikowi. Ma tę zaletę, że zapewnia bezpieczeństwo kluczy w przypadku naruszenia bezpieczeństwa systemu.
  5. Użyj jednego klucza , pokaż go użytkownikowi, zaszyfruj i przeprowadź normalne wyszukiwanie zaszyfrowanego klucza . Może być ponownie pokazany użytkownikowi, ale kosztem narażenia kluczy na włamanie do systemu.

Spośród nich myślę, że 3 to najlepsza równowaga między bezpieczeństwem a wygodą. Widziałem to zaimplementowane na wielu stronach internetowych podczas uzyskiwania wydanych kluczy.

Zapraszam również wszystkich ekspertów ds. Bezpieczeństwa do krytyki tej odpowiedzi. Chciałem tylko, żeby to było kolejnym punktem dyskusji.

kbuilds
źródło