Wenn Ihr Creative eine Auktion gewinnt, kann Google Sie über den Gewinnerpreis informieren, wenn das Creative das Makro ${AUCTION_PRICE}
enthält.
Wenn das Makro maximiert wird, gibt es den Gewinnerpreis in verschlüsselter Form zurück. Sie kann in einem Creative enthalten sein, z. B. mit einer Anfrage für ein unsichtbares Pixel, das als Teil der Anzeige gerendert wird:
<div> <script language='JavaScript1.1' src='https://example.com?creativeID=5837243'/> <img src='https://example.com/t.gif?price=${AUCTION_PRICE}' width='1' height='1'/> </div>
Das ${AUCTION_PRICE}
-Makro kann auch in der VAST-URL eines Video-Creatives enthalten sein, jedoch nicht in der Impressions-URL im VAST-Dokument:
https://example.com/vast/v?price=${AUCTION_PRICE}
Szenario
- Ihre OpenRTB-Gebotsanwendung enthält das Makro
${AUCTION_PRICE}
im HTML-Snippet oder in der VAST-URL, die an Google zurückgegeben wird. - Google ersetzt den Gewinnerpreis durch das Makro in ungepolsterter, websicherer Base64-Codierung (RFC 3548).
- Das Snippet gibt die Bestätigung im von Ihnen ausgewählten Format zurück. Die Bestätigung kann beispielsweise in der URL einer Anfrage für ein unsichtbares Pixel übergeben werden, das im Rahmen der Anzeige gerendert wird.
- Auf dem Server decodiert Ihre Anwendung die Informationen zum Gewinnerpreis mit websicherem Base64 und entschlüsselt das Ergebnis.
Abhängigkeiten
Sie benötigen eine Krypto-Bibliothek, die SHA-1 HMAC unterstützt, z. B. Openssl.
Beispielcode
Beispielcode ist in Java und C++ verfügbar und kann aus dem privatedatacommunicationprotocol-Projekt heruntergeladen werden.
Im Java-Beispielcode wird der Base64-Decodierer aus dem Apache Commons-Projekt verwendet. Sie müssen den Apache Commons-Code nicht herunterladen, da die Referenzimplementierung den erforderlichen Teil enthält und daher in sich geschlossen ist.
Im C++-Beispielcode wird die OpenSSL-Base64-BIO-Methode verwendet. Er decodiert einen websicheren Base64-codierten String (RFC 3548). Normalerweise wird bei websicheren Base64-Strings das Padding „="“ durch „.“ ersetzt. Anführungszeichen werden nur zur besseren Lesbarkeit hinzugefügt und sind nicht im Protokoll enthalten. Durch die Makrosubstitution wird der verschlüsselte Preis jedoch nicht aufgefüllt. Die Referenzimplementierung fügt Padding hinzu, da OpenSSL Probleme mit nicht gepaddeten Strings hat.
Codierung
Für die Verschlüsselung und Entschlüsselung des Preises für erfolgreiche Gebote sind zwei geheime, aber freigegebene Schlüssel erforderlich. Einen Integritätsschlüssel und einen Verschlüsselungsschlüssel, die jeweils als i_key
und e_key
bezeichnet werden. Beide Schlüssel werden bei der Kontoeinrichtung als websichere Base64-Strings angegeben und sind auf der Authorized Buyers-Seite unter Gebotsfunktionseinstellungen > RTB-Einstellungen > Verschlüsselungsschlüssel zu finden.
Beispiel für Integritäts- und Verschlüsselungsschlüssel:
skU7Ax_NL5pPAFyKdkfZjZz2-VhIN8bjj1rVFOaJ_5o= // Encryption key (e_key) arO23ykdNqUQ5LEoQ0FVmPkBd7xB5CO89PDZlSjpFxo= // Integrity key (i_key)
Schlüssel sollten von Ihrer Anwendung websicher und dann Base64-decodiert werden:
e_key = WebSafeBase64Decode('skU7Ax_NL5pPAFyKdkfZjZz2-VhIN8bjj1rVFOaJ_5o=') i_key = WebSafeBase64Decode('arO23ykdNqUQ5LEoQ0FVmPkBd7xB5CO89PDZlSjpFxo=')
Verschlüsselungsschema
Der Preis wird mit einem benutzerdefinierten Verschlüsselungsschema verschlüsselt, das den Größenoverhead minimiert und gleichzeitig für ausreichende Sicherheit sorgt. Beim Verschlüsselungsschema wird ein HMAC-Algorithmus mit Schlüssel verwendet, um einen geheimen Puffer basierend auf der eindeutigen Ereignis-ID der Impression zu generieren.
Der verschlüsselte Preis hat eine feste Länge von 28 Byte. Sie besteht aus einem 16-Byte-Initialisierungsvektor, 8 Byte Geheimtext und einer 4-Byte-Integritätssignatur. Der verschlüsselte Preis ist gemäß RFC 3548 websicher base64-codiert, wobei Füllzeichen weggelassen werden. Der verschlüsselte Preis mit 28 Byte wird unabhängig vom gezahlten Gewinnerpreis als 38-stelliger websicherer Base64-String codiert.
Beispiel für verschlüsselte Preise:
YWJjMTIzZGVmNDU2Z2hpN7fhCuPemCce_6msaw // 100 CPI micros YWJjMTIzZGVmNDU2Z2hpN7fhCuPemCAWJRxOgA // 1900 CPI micros YWJjMTIzZGVmNDU2Z2hpN7fhCuPemC32prpWWw // 2700 CPI micros
Das verschlüsselte Format ist:
{initialization_vector (16 bytes)}{encrypted_price (8 bytes)} {integrity (4 bytes)}
Der Preis wird als <price xor HMAC(encryption_key,
initialization_vector)>
verschlüsselt. Bei der Entschlüsselung wird HMAC(encryption_key,initialization_vector)
berechnet und mit dem verschlüsselten Preis XOR-verknüpft, um die Verschlüsselung rückgängig zu machen. Die Integritätsstufe benötigt 4 Byte <HMAC(integrity_key, price||initialization_vector)>
, wobei ||
die Konkatenierung ist.
Eingaben | |
---|---|
iv |
Initialisierungsvektor (16 Byte – eindeutig für die Impression) |
e_key |
Verschlüsselungsschlüssel (32 Byte, bei der Kontoeinrichtung angegeben) |
i_key |
Integritätsschlüssel (32 Byte, bei der Kontoeinrichtung angegeben) |
price |
(8 Byte – in Mikroeinheiten der Kontowährung) |
Notation | |
hmac(k, d) |
SHA-1-HMAC der Daten d mit Schlüssel k |
a || b |
String a mit String b verkettet |
Pseudocode | |
pad = hmac(e_key, iv) // first 8 bytes enc_price = pad <xor> price signature = hmac(i_key, price || iv) // first 4 bytes final_message = WebSafeBase64Encode( iv || enc_price || signature ) |
Entschlüsselungsschema
Ihr Entschlüsselungscode muss den Preis mit dem Verschlüsselungsschlüssel entschlüsseln und die Integritätsbits mit dem Integritätsschlüssel überprüfen. Die Schlüssel werden Ihnen während der Einrichtung zur Verfügung gestellt. Die Implementierung kann dabei ganz nach Ihren Wünschen gestaltet werden. Sie sollten den Beispielcode größtenteils an Ihre Anforderungen anpassen können.
Eingaben | |
---|---|
e_key |
Verschlüsselungsschlüssel, 32 Byte – bei der Kontoeinrichtung angegeben |
i_key |
Integritätsschlüssel, 32 Byte – bei der Kontoeinrichtung angegeben |
final_message |
38 Zeichen, websicher mit Base64 codiert |
Pseudocode | |
// Base64 padding characters are omitted. // Add any required base64 padding (= or ==). final_message_valid_base64 = AddBase64Padding(final_message) // Web-safe decode, then base64 decode. enc_price = WebSafeBase64Decode(final_message_valid_base64) // Message is decoded but remains encrypted. (iv, p, sig) = enc_price // Split up according to fixed lengths. price_pad = hmac(e_key, iv) price = p <xor> price_pad conf_sig = hmac(i_key, price || iv) success = (conf_sig == sig) |
Stale-Response-Angriffe erkennen
Um Angriffe mit veralteten Antworten oder Replay-Angriffen zu erkennen, sollten Sie Antworten mit einem Zeitstempel filtern, der sich deutlich von der Systemzeit unterscheidet, nachdem Sie die Zeitzonenunterschiede berücksichtigt haben.
Der Initialisierungsvektor enthält in den ersten 8 Byte einen Zeitstempel. Sie kann mit der folgenden C++-Funktion gelesen werden:
void GetTime(const char* iv, struct timeval* tv) { uint32 val; memcpy(&val, iv, sizeof(val)); tv->tv_sec = htonl(val); memcpy(&val, iv+sizeof(val), sizeof(val)); tv->tv_usec = htonl(val) }
Der Zeitstempel kann mit dem folgenden C++-Code in eine für Menschen lesbare Form konvertiert werden:
struct tm tm; localtime_r(&tv->tv_sec, &tm); printf("%04d-%02d-%02d|%02d:%02d:%02d.%06ld", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, tv_.tv_usec);
Java-Bibliothek
Anstatt die Kryptoalgorithmen zum Codieren und Decodieren des Gewinnerpreises zu implementieren, können Sie DoubleClickCrypto.java verwenden. Weitere Informationen finden Sie unter Kryptografie.