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 aus 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
Wenn Sie zum Beispiel diesen Request senden:
POST https://gateway.seven.io/api/sms
{"to": "49170123456789", "text": "Hello World! :-)", "from": "seven"}
Wäre der zu signierende String wie folgt aufgebaut:
STRING_TO_SIGN =
1634641200
fpPRhAd1s8GXacfR39mWqKPynmmXfJnc
POST
https://gateway.seven.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.seven.io/api/sms | Die Ziel URL |
62dd06ffb3101dc2456517b177b744ae | MD5( {"to": "49170123456789", "text": "Hello World! :-)", "from": "seven"} ) |
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.
- Name
X-Signature
- Type
- string
- Description
Die von Ihnen generierte Signatur
- Name
X-Timestamp
- Type
- integer
- Description
Der Zeitstempel, zu dem die Signatur erstellt wurde
- Name
X-Nonce
- Type
- string
- Description
Der von Ihnen erstelle Nonce
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.seven.io/api/sms"
CONTENT_BODY="{ \"to\": \"0170123456789\", \"text\": \"Hello World! :-)\", \"from\": \"seven.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' => 'seven.io',
]);
$url = 'https://gateway.seven.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;