Ihr Browser versucht gerade eine Seite aus dem sogenannten Internet auszudrucken. Das Internet ist ein weltweites Netzwerk von Computern, das den Menschen ganz neue Möglichkeiten der Kommunikation bietet.

Da Politiker im Regelfall von neuen Dingen nichts verstehen, halten wir es für notwendig, Sie davor zu schätzen. Dies ist im beidseitigen Interesse, da unnötige Angstzustiände bei Ihnen verhindert werden, ebenso wie es uns vor profilierungs- und machtsächtigen Politikern schützt.

Sollten Sie der Meinung sein, dass Sie diese Internetseite dennoch sehen sollten, so können Sie jederzeit durch normalen Gebrauch eines Internetbrowsers darauf zugreifen. Dazu sind aber minimale Computerkenntnisse erforderlich. Sollten Sie diese nicht haben, vergessen Sie einfach dieses Internet und lassen uns in Ruhe.

Die Umgehung dieser Ausdrucksperre ist nach §95a UrhG verboten.

Mehr Informationen unter www.politiker-stopp.de.

2 10. März 2010


Identifikation und Authentifikation in RESTful APIs

Ja, viele von euch (srsly?) haben sicher schon einmal ein (semi) RESTful API entwickelt. Ein haeufiges Problem ist herauszufinden, ob ein Aufruf auch durchgefuehrt werden darf. Das Problem besteht darin, dass wir es dabei mit einem zustandslosen Protokoll (RFC 2616) zu tun haben, also fallen die Elgamal- und Diffie-Hellman-Kryptosysteme aus.

Um nun festzustellen, ob die Person (bzw. eine Applikation, stellvertretend fuer eine Person), die die Anfrage sendet auch wirklich die Person ist, fuer die sie sich ausgibt (Identifikation) und um gleichzeitig festzustellen, ob die Anfrage nicht manipuliert wurde (Authentifikation), gibt es zum einen das freie OAuth Protokoll, was aber relativ kompliziert zu implementieren ist, und zum anderen gibt es aehnliche Ansaetze, wie zum Beispiel das Flickr Auth Protokoll. Beide Protokolle bieten ausserdem die Moeglichkeit externen Programmen (Clients) den Zugriff auf das System (Service Provider) zu authorisieren.

Sofern letzteres nicht noetig ist, reicht jedoch ein abgespecktes Protokoll, das dem Flickr Protokoll sehr nah kommt. Hierbei faellt der Aufwand der sicheren Schluesseluebertragung weg. Und so einfach kann es gehen:

  • Der Service Provider generiert einen oeffentlichen Schluessel (API Key) und einen privaten Schluessel (Secret). Ich habe fuer den oeffentlichen Schluessel die SHA1 Pruefsumme verschiedener Variablen und fuer den privaten Schluessel die MD5 Pruefsumme von Variablen, Zufallszahlen und Timestamps genutzt.
  • Der Client wird mit beiden Keys ausgestattet. Wie gesagt: Der unwiretapped Schluesselaustausch muss anders sichergestellt werden. Bei meinem System kann der Benutzer die Keys einsehen, wenn er sich zuvor mit seinen Zugangsdaten eingeloggt hat. Das ist auch gaengige Praxis.
  • Bei einer Anfragegenerierung werden die Variablen inkl. oeffentlichem Schluessel (die Bezeichner, nicht die Werte!) alphabetisch sortiert und dann mit ihrem Wert konkateniert. Dann werden die Key-Value-Strings konkateniert und der private Schluessel wird vorangestellt. Das Ganze wird jetzt gehasht (e.g. MD5). Nun werden alle Variablen und die zusaetzlich generierte signature-Variable uebertragen.
  • Der Service Provider empfaengt alle Variablen, nimmt davon den oeffentlichen Schluessel und sucht in seiner Datenbank nach dem dazu passenden privaten Schluessel. Jetzt kann der Service Provider das selbe Spiel spielen, das der Client schon durchgemacht hat: Variablen sortieren, Key-Value-Strings bauen, konkatenieren, den privaten Schluessel voranstellen und hashen. Der Vergleich der uebermittelten Signatur und der generierten Signatur erlaubt die Authentifizierung des Zugriffs.

Beispiel

Der API Key ist fd40e3589bbb58ec358122c5cd32fcc6481707bb, das Geheimnis ist 162c9d446beb754b804b904772ff87b6. Die Variablen sind (Bezeichner = Wert):

  • method = deleteEntries
  • rangeFrom = 99
  • rangeTo = 101

Die Anfrage wird nun wie folgt Client-seitig generiert:
Sortieren:

apiKey vor method vor rangeFrom vor rangeTo

Konkatenieren:

apiKeyfd40e3589bbb58ec358122c5cd32fcc6481707bbmethoddeleteEntriesrangeFrom99rangeTo101

Private Key voranstellen:

162c9d446beb754b804b904772ff87b6apiKeyfd40e3589bbb58ec358122c5cd32fcc6481707bbmethoddeleteEntriesrangeFrom99rangeTo101

Hashen:

9ad5100448f0549472b0e70722aa06bb

Variablen fuer die Anfrage zusammensetzen:

http://example.com/rest/?apiKey=fd40e3589bbb58ec358122c5cd32fcc6481707bb&method=deleteEntries&rangeFrom=99&rangeTo=101&signature=9ad5100448f0549472b0e70722aa06bb

Das wird nun ausgefuehrt und auf der Service Provider Seite geht es dann so weiter:
API Key auslesen:

fd40e3589bbb58ec358122c5cd32fcc6481707bb

In der Datenbank nach dem passenden privaten Schluessel suchen:

162c9d446beb754b804b904772ff87b6

Sortieren, Konkatenieren, Private Key voranstellen, Hashen (s.o.):

9ad5100448f0549472b0e70722aa06bb

Ergebnisse vergleichen:

9ad5100448f0549472b0e70722aa06bb = 9ad5100448f0549472b0e70722aa06bb

That’s it. Ist sehr einfach zu implementieren und ist dafuer extrem sicher.

2 Kommentare zu “Identifikation und Authentifikation in RESTful APIs”

  1. Shiruba

    Moment. Du generierst pro API-Nutzer einen API-Key und einen privaten Schl?ssel? Und warum kennen beide den privaten Schl?ssel?

  2. visus

    Der oeffentliche Schluessel ist dazu da den privaten Schluessel herauszufinden. Der private Schluessel ist das gemeinsame Geheimnis, was zur Signierung verwendet wird. Das ist keine PKI im eigentlichen Sinne! Der Service Provider hat die Faehigkeit zu signieren, aber da von ihm keine Anfragen ausgehen passiert das nicht. Um das System nicht mit einer PKI zu verwechseln sollte man vielleicht bei API Key und Secret bleiben statt bei oeffentlichem/privatem Schluessel.

Einen Kommentar schreiben: