Warum einen API-Schlüssel und ein Geheimnis verwenden?

90

Ich bin auf viele APIs gestoßen, die dem Benutzer sowohl einen API- Schlüssel als auch ein Geheimnis geben . Aber meine Frage ist: Was ist der Unterschied zwischen beiden?

In meinen Augen kann ein Schlüssel ausreichen. Angenommen, ich habe einen Schlüssel und nur ich und der Server wissen es. Ich erstelle einen HMAC-Hash mit diesem Schlüssel und führe einen API-Aufruf durch. Auf dem Server erstellen wir den HMAC-Hash erneut und vergleichen ihn mit dem gesendeten Hash. Wenn es dasselbe ist, wird der Anruf authentifiziert.

Warum also zwei Schlüssel verwenden?

Bearbeiten: Oder wird dieser API-Schlüssel zum Nachschlagen des API-Geheimnisses verwendet?

EsTeGe
quelle

Antworten:

45

Die Kryptografie mit geheimen Schlüsseln basiert auf der Verwendung desselben Schlüssels zum Codieren und späteren Dekodieren einer Nachricht. Somit können nur diejenigen, die das "Geheimnis" kennen, die Nachricht lesen.

Die RSA-Sicherheit basiert auf 2 übereinstimmenden Schlüsseln. Für jeden Benutzer gibt es einen öffentlichen Schlüssel, den jeder kennen kann (sollte). Es gibt auch einen privaten Schlüssel, den nur der Benutzer kennen sollte. Eine mit dem öffentlichen Schlüssel verschlüsselte Nachricht kann nur mit dem privaten Schlüssel entschlüsselt werden und umgekehrt.

Wenn ich Ihnen also eine Nachricht senden möchte, die nur Sie lesen können, erhalte ich (vom Netzwerk) Ihren öffentlichen Schlüssel, verschlüssele die Nachricht mit diesem Schlüssel und Sie sind die einzige Person, die sie entschlüsseln kann.

Wenn ich Ihnen beweisen möchte, dass ich eine Nachricht gesendet habe, kann ich die Nachricht mit meinem privaten Schlüssel verschlüsseln und Ihnen (in offenem Text oder in einer anderen Nachricht) mitteilen, wie sie verschlüsselt wurde. Dann könnten Sie die Nachricht mit meinem öffentlichen Schlüssel entschlüsseln, und wenn sie lesbar wird, wissen Sie, dass sie von mir stammt.

Diese Form der Verschlüsselung ist ziemlich computerintensiv. Manchmal wird also ein einmaliger "geheimer Schlüssel" mit RSA-Technologie verschlüsselt, dann der Rest der Nachricht mit dem geheimen Schlüssel verschlüsselt und dann meine Signatur auf die zweite Weise verschlüsselt. Sie kehren diesen Vorgang dann um. Wenn die Nachricht und die Signatur lesbar sind, können Sie und nur Sie sie lesen, und Sie können sicher sein, dass ich die Nachricht gesendet habe.

ODER

Sie können diesen Link für eine detailliertere Erklärung besuchen.

Wie funktionieren API-Schlüssel und geheime Schlüssel?

SALMAN
quelle
9
Gute Antwort, aber wenn ich API-Geheimnisse und -Schlüssel mit Facebook, Google Mail usw. verwende, muss ich zu keinem Zeitpunkt etwas verschlüsseln oder hashen. Was ist in diesen Fällen der Sinn der API-Geheimnisse und -Schlüssel?
Quintonn
2
Am Beispiel von Facebook gibt es zwei Szenarien, in denen Sie app_secret verwenden würden. Der erste erfordert kein Hashing. Es wird hauptsächlich verwendet, um zu verhindern, dass Ihre Weiterleitungs-URL entführt wird. Nachdem sich ein Benutzer angemeldet und Ihrer App Zugriff gewährt hat, wenn Facebook das Zugriffstoken direkt an die Weiterleitungs-URL gesendet hat, können Sie nicht überprüfen, ob das Zugriffstoken von Facebook stammt. Ich könnte mein eigenes Zugriffstoken auf Ihre Weiterleitungs-URL posten und Facebook-Aktionen ausführen, die von Ihrer API stammen würden. Stattdessen sendet Facebook einen Code an die Weiterleitungs-URL. Die API tauscht dann den Code gegen das eigentliche Zugriffstoken aus.
Ryan Thomas
2
Während des letzten Teils, bei dem der Code gegen das eigentliche Zugriffstoken ausgetauscht wird, erwartet Facebook, dass Ihre API ihre Identität mit einer Signatur überprüft. In diesem Szenario benötigen sie keine Kryptografie mit öffentlichem Schlüssel zum Signieren. Sie vertrauen einfach darauf, dass Sie Ihre App wirklich geheim halten und als Signatur verwenden. Das kam mir immer albern vor, keine Einwegfunktion zum Generieren einer Signatur zu verwenden, aber ich nehme an, sie haben Gründe wie die Leistung, sich für die direkte Verwendung von App Secret zu entscheiden.
Ryan Thomas
Im zweiten Anwendungsfall verwenden Sie kryptografisches Hashing. Nachdem Sie über das eigentliche access_token verfügen, um mit Facebook zu interagieren, möchten Sie möglicherweise zusätzliche Sicherheit, um zu verhindern, dass sich Ihre App imitiert. In der Facebook-App-Konsole können Sie eine Funktion aktivieren, bei der jede Facebook-API-Anfrage Ihrer App zusätzlich zum Zugriffstoken Ihre Signatur enthalten muss. Ich rate nur zu ihren Motiven, aber ich denke an dieser Stelle wollen sie nicht, dass Sie bei jeder Anfrage wiederholt app_secret als Signatur senden. Je mehr Sie es senden, desto größer ist die Wahrscheinlichkeit, dass app_secret kompromittiert wird.
Ryan Thomas
1
Ich nehme an, seit Sie sich für diese zusätzliche Sicherheitsfunktion entschieden haben, haben Sie auch eine Art Entscheidung getroffen, um den zusätzlichen Leistungsaufwand von Facebook zu ermöglichen, indem Sie Ihre Signatur mit einem kryptografischen Hash-Aufruf am Ende überprüfen. In diesem Szenario übergeben Sie mit Ihren Facebook-API-Anfragen zwei Werte. Das access_token und ein Wert namens appsecret_proof, der als Signatur dient. Der geheime App-Beweis wird durch kryptografisches Hashing des access_token unter Verwendung von app_secret als Schlüssel generiert.
Ryan Thomas
55

Sie benötigen zwei separate Schlüssel, einen, der ihnen sagt, wer Sie sind, und einen, der beweist, dass Sie der sind, für den Sie sich ausgeben .

Der "Schlüssel" ist Ihre Benutzer-ID und das "Geheimnis" ist Ihr Passwort. Sie verwenden nur die Begriffe "Schlüssel" und "Geheimnis", weil sie es so implementiert haben.

Marcus Adams
quelle
1
Und was ist, wenn Sie über https kommunizieren? Was bringt es dann, Ihre Nachricht mit einem geheimen Schlüssel zu verschlüsseln?
Kamuniaft
6
Es geht immer darum, das Risiko zu reduzieren. Wenn die https-Kommunikation beeinträchtigt ist, kann ein Angreifer, der Ihre Anfrage lesen kann, keine neuen fälschen. Wenn Ihre API im Begriff ist, Bilder von Katzen zu bewerten, ist das keine große Sache. Wenn es sich um eine Zahlungs-API handelt, sollten Sie mehrere Sicherheitsebenen haben :)
Yall
Ich nehme an, der Zweck sind zwei separate Schlüssel, weil verschiedene Benutzer einer einzelnen Client-App unterschiedliche Geheimnisse haben können. Wenn sie andernfalls alle dasselbe Geheimnis haben, ist es nicht sinnvoll, einen Schlüssel zu haben. Richtig?
Honey
Warum verwenden diese API dafür keine Bearer:Authentifizierung? Sie hätten dort einen Ausweis und einen PwD.
Stefan Haberl
7

Einfache Antwort, wenn ich es richtig verstanden habe ...

Wenn Sie Ihren API-Schlüssel zur Verschlüsselung verwenden, woher weiß der Dienst, wer ihn kontaktiert? Wie werden sie diese Nachricht entschlüsseln?

Sie verwenden den API-Schlüssel, um anzugeben, wer Sie sind. Dies senden Sie im Klartext. Den SECRET-Schlüssel senden Sie an niemanden. Sie verwenden es einfach zur Verschlüsselung. Dann senden Sie die verschlüsselte Nachricht. Sie senden nicht den Schlüssel, der für die Verschlüsselung verwendet wurde, da dies den Zweck zunichte machen würde.

ancajic
quelle
Sie machen. Sie senden den API-Schlüssel an den Server. Dies bedeutet also, dass Sie diesen Wert jedem geben, der möglicherweise Ihre Kommunikation mit dem Server abfängt.
ancajic
Bei fast jeder API, die ich gesehen habe, senden Sie sowohl den Schlüssel als auch das Geheimnis an den Server. Die Verbindung zum Server wird theoretisch mit der gleichen Sicherheitsstufe verschlüsselt. Aber ich gebe auch niemandem außer dem Server etwas.
sudo
Ich habe nie gesehen, wie ich secretim Klartext gesendet habe. Kannst du mir einen Link geben? Was ich gesehen habe, ist secretdas Verschlüsseln einiger Daten. Und zusammen mit den verschlüsselten Daten senden, apiKeydamit der Server weiß, wie die Daten zu entschlüsseln sind.
ancajic
twilio.com/docs/sms/tutorials/… und nexmo.github.io/Quickstarts/sms/send sind die Beispiele, die mich dazu veranlasst haben, nach StackOverflow zu suchen.
Sudo
Twilio verwendet diese Begriffe nicht genau. Aber Nexmo ist sicher ... Aber nach einem kurzen Blick scheint es, als würden sie nur die Daten aufrufen secretund apiKeyund was sie tatsächlich tun, ist usernameund password. Was ganz anders ist ...
ancajic
3

Es gibt Antworten, die erklären, was der geheime und (öffentliche) Schlüssel ist. Es ist ein öffentlich-privates Schlüsselpaar, dem sie verwirrende Namen geben. Aber niemand sagt, warum die APIs beides erfordern, und viele APIs geben Ihnen nur ein Geheimnis! Ich habe auch noch nie gesehen, dass API-Dokumente erklären, warum sie zwei Schlüssel haben. Das Beste, was ich tun kann, ist zu spekulieren ...

Es ist am besten, nur Ihren öffentlichen Schlüssel in Ihre Anfrage aufzunehmen und die Anfrage lokal mit Ihrem privaten Schlüssel zu signieren. Das Senden von mehr sollte nicht erforderlich sein. Aber einige kommen davon, nur das Geheimnis in der Anfrage zu haben. Ok, jede gute API verwendet eine gewisse Transportsicherheit wie TLS (normalerweise über HTTPS). Sie stellen Ihren privaten Schlüssel jedoch weiterhin auf diese Weise dem Server zur Verfügung und erhöhen so das Risiko, dass er ihn irgendwie falsch behandelt (siehe: Der kürzlich entdeckte Fehler bei der Kennwortprotokollierung von GitHub und Twitter). Und HTTPS ist theoretisch genauso sicher, aber es gibt immer Implementierungsfehler.

Bei vielen - eigentlich den meisten - APIs müssen Sie jedoch beide Schlüssel in Anfragen senden, da dies einfacher ist, als die Benutzer dazu zu bringen, ihre eigenen Signaturen zu erstellen. kann sonst keine reinen cURL-Beispiele haben! In diesem Fall ist es sinnlos, sie getrennt zu haben. Ich denke, die separaten Schlüssel sind nur für den Fall gedacht, dass sie die API später ändern, um sie zu nutzen. Oder einige haben eine Client-Bibliothek, die dies möglicherweise sicherer macht.

sudo
quelle
0

Eine Sache, die ich hier nicht erwähnt habe, obwohl sie eine Erweiterung von Marcus Adams 'Antwort ist, ist, dass Sie keine einzige Information verwenden sollten, um einen Benutzer zu identifizieren und zu authentifizieren, wenn die Möglichkeit von Timing-Angriffen besteht , die dies können Verwenden Sie die Unterschiede in den Antwortzeiten, um zu erraten, wie weit ein Zeichenfolgenvergleich gekommen ist.

Wenn Sie ein System verwenden, das einen "Schlüssel" verwendet, um den Benutzer oder die Anmeldeinformationen nachzuschlagen, können diese Informationen im Laufe der Zeit schrittweise erraten werden, indem Tausende von Anforderungen gesendet und die Zeit untersucht werden, die Ihre Datenbank benötigt, um sie zu finden (oder nicht) finde) einen Datensatz. Dies gilt insbesondere dann, wenn der "Schlüssel" im Klartext anstelle eines Einweg-Hash des Schlüssels gespeichert ist. Sie möchten die Schlüssel der Benutzer im Klartext oder symmetrisch verschlüsselt speichern, wenn Sie den Schlüssel dem Benutzer erneut anzeigen möchten.

Wenn Sie über eine zweite Information oder ein "Geheimnis" verfügen, können Sie zuerst den Benutzer oder den Berechtigungsnachweis mithilfe des "Schlüssels" nachschlagen, der für einen Timing-Angriff anfällig sein könnte, und dann mithilfe einer zeitsicheren Vergleichsfunktion den Wert von überprüfen das Geheimnis".

Hier ist Pythons Implementierung dieser Funktion:

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

Und es ist in der hmacBibliothek (und wahrscheinlich auch in anderen) ausgesetzt :

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


Eine Sache, die hier zu beachten ist, ist, dass ich nicht denke, dass diese Art von Angriff auf Werte funktioniert, die vor der Suche gehasht oder verschlüsselt wurden, da sich die verglichenen Werte jedes Mal zufällig ändern, wenn sich ein Zeichen in der Eingabezeichenfolge ändert. Ich habe hier eine gute Erklärung dafür gefunden .

Lösungen zum Speichern von API-Schlüsseln wären dann:

  1. Verwenden Sie einen separaten Schlüssel und ein separates Geheimnis, verwenden Sie den Schlüssel, um den Datensatz nachzuschlagen, und verwenden Sie einen zeitsicheren Vergleich, um das Geheimnis zu überprüfen. Auf diese Weise können Sie dem Benutzer den Schlüssel und das Geheimnis erneut einem Benutzer zeigen.
  2. Verwenden Sie einen separaten Schlüssel und ein separates Geheimnis, verwenden Sie eine symmetrische, deterministische Verschlüsselung für das Geheimnis und führen Sie einen normalen Vergleich verschlüsselter Geheimnisse durch. Auf diese Weise können Sie dem Benutzer den Schlüssel und das Geheimnis erneut anzeigen und müssen keinen zeitsicheren Vergleich durchführen.
  3. Verwenden Sie einen separaten Schlüssel und ein separates Geheimnis, zeigen Sie das Geheimnis an, hashen und speichern Sie es und führen Sie dann einen normalen Vergleich des gehashten Geheimnisses durch. Dadurch entfällt die Notwendigkeit der bidirektionalen Verschlüsselung, und Sie haben den zusätzlichen Vorteil, dass Sie Ihr Geheimnis sicher aufbewahren, wenn das System kompromittiert wird. Es hat den Nachteil, dass Sie dem Benutzer das Geheimnis nicht erneut zeigen können.
  4. Verwenden Sie einen einzelnen Schlüssel , zeigen Sie ihn dem Benutzer einmal, hashen Sie ihn und führen Sie dann eine normale Suche des gehashten oder verschlüsselten Schlüssels durch. Dies verwendet einen einzelnen Schlüssel, kann dem Benutzer jedoch nicht erneut angezeigt werden. Hat den Vorteil, dass die Schlüssel sicher sind, wenn das System kompromittiert wird.
  5. Verwenden Sie einen einzelnen Schlüssel , zeigen Sie ihn dem Benutzer einmal, verschlüsseln Sie ihn und führen Sie eine normale Suche nach dem verschlüsselten Geheimnis durch. Kann dem Benutzer erneut angezeigt werden, jedoch auf Kosten der Verwundbarkeit von Schlüsseln, wenn das System gefährdet ist.

Von diesen denke ich, dass 3 das beste Gleichgewicht zwischen Sicherheit und Komfort ist. Ich habe gesehen, dass dies auf vielen Websites implementiert wurde, als Schlüssel ausgegeben wurden.

Außerdem lade ich alle tatsächlichen Sicherheitsexperten ein, diese Antwort zu kritisieren. Ich wollte dies nur als weiteren Diskussionspunkt herausbringen.

kbuilds
quelle