1. Home
  2. Gateway
  3. HTTP API
  4. Signierung von Requests

Signierung von Requests

Als zusätzliche Sicherheit können Sie bei allen Anfragen an und von unserer API Signaturen verwenden. Die Verwendung von Signaturen ist optional. Wenn allerdings eine Signatur gesendet wird, muss diese valide sein.

Beim Senden von Anfragen an unsere API erzeugen Sie eine Signatur, die Sie mit Ihren Daten versenden. Beim Empfang enthält der eingehende Webhook die Signatur und alle Felder, die Sie zur Erstellung der Signatur in Ihrer Anwendung benötigen, um die Übereinstimmung der beiden Signaturen und damit die Richtigkeit des Webhooks zu überprüfen.

Mittels dieser Signatur kann sichergestellt werden, dass

  • der Request tatsächlich von der richtigen Quelle stammt,
  • der Request unterwegs nicht verfälscht wurde,
  • Requests nicht abgefangen und später wiederholt werden.

Die Signatur enthält dabei zwingend einige Daten wie unter anderem den Zeitstempel, die Ziel URL, einen sogenannten Nonce und die gesendeten Daten.

Aufbau der Signatur

Zur Erstellung einer Signatur werden folgende Daten benötigt:

Wert Beschreibung
Nonce Ein zufälliger String, bestehend 32 alphanumerischen Zeichen. Dieser muss einzigartig für jeden Request sein.
Zeitstempel Der Zeitpunkt des Requests als Unix Timestamp, darf maximal 30 Sekunden zurückliegen
HTTP Methode Die HTTP Request Methode, z.B. POST oder GET
Ziel URL Die vollständige URL, an die der Request gesendet wird
Content des Requests MD5 Hash des Inhalts des Requests

Zur Generierung der Signatur wird der SHA256 HMAC Algorithmus mit dem Signierschlüssel Ihres Accounts verwendet. Den Schlüssel finden Sie in Ihrem Login im Bereich Entwickler in den API Einstellungen.

Struktur der zu signierenden Zeichenfolge

Folgendermaßen muss der zu signierende String aufgebaut werden:

STRING_TO_SIGN =
  Zeitstempel + \n +
  Nonce + \n +
  HTTPMethode + \n +
  ZielURL + \n + 
  ContentBodyMD5

Beispiel Request

POST https://gateway.sms77.io/api/sms

{ "to": "49170123456789", "text": "Hello World! :-)", "from": "sms77.io" }

Der zu signierende String wäre wie folgt aufgebaut:

STRING_TO_SIGN =
  1634641200
  fpPRhAd1s8GXacfR39mWqKPynmmXfJnc
  POST
  https://gateway.sms77.io/api/sms
  62dd06ffb3101dc2456517b177b744ae
Wert Erklärung
1634641200 der aktuelle Zeitstempel zum Zeitpunkt des Absendens des Requests, hier der 19.10.2021 um 13:00:00 Uhr
fpPRhAd1s8GXacfR39mWqKPynmmXfJnc ein zufällig generierter String mit 32 Zeichen
POST die verwendete HTTP Methode
https://gateway.sms77.io/api/sms die Ziel URL
62dd06ffb3101dc2456517b177b744ae MD5( { “to”: “49170123456789”, “text”: “Hello World! :-)”, “from”: “sms77.io” } )

Erstellung der Signatur

Um nun die Signatur zu erstellen, verwenden Sie den SHA256 HMAC Algorithmus in Verbindung mit Signierschlüssel Ihres Accounts.

printf "${STRING_TO_SIGN}" | openssl dgst -sha256 -hmac "${SIGNING_SECRET}"

Ähnliche Implementierungen sind in den meisten gängigen Programmiersprachen gegeben, so zum Beispiel in PHP:

$signature = hash_hmac('sha256', $STRING_TO_SIGN, $SIGNING_SECRET);

Senden der Signatur

Die Signatur, das Nonce und der Zeitstempel müssen in den HTTP Headern der Anfrage gesendet werden.

Header Erklärung
X-Signature Die von Ihnen generierte Signatur
X-Timestamp Der Zeitstempel, zu dem die Signatur erstellt wurde
X-Nonce Der von Ihnen erstelle Nonce

Im Falle eines Fehlers, falls wir die Signatur nicht abgleichen können, der Zeitstempel zu alt ist oder der Nonce / die Signatur bereits gesendet wurde, erhalten Sie den HTTP Code 401 und eine detailliertere Beschreibung des Fehler in der Antwort auf Ihren Request.

Beispiele

Bash Script mit curl und openssl:

#!/bin/bash

# Ihre API Daten
API_KEY="IHR_API_SCHLÜSSEL"
SIGNING_SECRET="IHR_SIGNIER_SCHLÜSSEL"

# Zufälligen Nonce erstellen
NONCE=$(openssl rand -hex 32)

# Zeitstempel
TIMESTAMP=$(date +%s)

# Daten des Requests
HTTP_VERB="POST"
URL="https://gateway.sms77.io/api/sms"
CONTENT_BODY="{ \"to\": \"0170123456789\", \"text\": \"Hello World! :-)\", \"from\": \"sms77.io\" }"

# Signatur erstellen
CONTENT_BODY_MD5=$(printf "${CONTENT_BODY}" | md5sum | awk '{print $1}')
STRING_TO_SIGN=$(printf "${TIMESTAMP}\n${NONCE}\n${HTTP_VERB}\n${URL}\n${CONTENT_BODY_MD5}")
SIGNATURE=$(printf "${STRING_TO_SIGN}" | openssl dgst -sha256 -hmac "${SIGNING_SECRET}" | sed 's/^.*= //')

# Request absenden
curl -X $HTTP_VERB $URL \
  -H "X-Api-Key: $API_KEY" \
  -H "X-Nonce: $NONCE" \
  -H "X-Timestamp: $TIMESTAMP" \
  -H "X-Signature: $SIGNATURE" \
  -H "Content-type: application/json" \
  -H "Accept: application/json" \
  -d "${CONTENT_BODY}"

PHP Script:

# Ihre API Daten
$key = 'IHR_API_SCHLÜSSEL';
$secret = 'IHR_SIGNIER_SCHLÜSSEL';

# Zufälligen Nonce erstellen 
$nonce = bin2hex(random_bytes(16)); 

# Zeitstempel
$timestamp = time();

# Daten des Requests
$http_verb = 'POST';

$content_body = json_encode([
  'to' => '49170123456789',
  'text' => 'Hello World! :-)',
  'from' => 'sms77.io',
]);

$url = 'https://gateway.sms77.io/api/sms';

# Signatur erstellen
$StringToSign = $timestamp . "\n" .
  $nonce . "\n" .
  $http_verb . "\n" .
  $url . "\n" .
  md5($content_body);

$hash = hash_hmac('sha256', $StringToSign, $secret);

# Header setzen
$headers = [
  'X-Signature: ' . $hash,
  'X-Api-Key: ' . $key,
  'X-Timestamp:' . $timestamp,
  'X-Nonce:' . $nonce,
  'Content-type: application/json',
  'Accept: application/json'
];

# Request absenden
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POSTFIELDS, $content_body);

curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($ch);
curl_close($ch);

echo $result;

 

Webhooks

Analog zur oben beschriebenen Weise senden signieren wir Webhooks an Ihren Server entsprechend mit dem Signierschlüssel Ihres Accounts.

Folgende Header senden wir Ihnen in jedem Webhook:

Header Erklärung
X-Signature Die von uns generierte Signatur
X-Timestamp Zeitstempel, zu dem die Signatur von uns erstellt wurde
X-Nonce Zufällig generierter String mit 32 Zeichen

Anhand dieser Daten können Sie bei jedem empfangenen Webhook die Echtheit der Requests von uns validieren.