Fiyat Onaylarının Şifresini Çözün

Reklam öğeniz bir açık artırmayı kazandığında Google, reklam öğesi ${AUCTION_PRICE} makrosunu içeriyorsa kazanan fiyatı size bildirebilir.

Makro genişletildiğinde, kazanan fiyatı şifrelenmiş biçimde döndürür. Örneğin, reklamın bir parçası olarak oluşturulan görünmez bir piksel isteğiyle reklam öğesine dahil edilebilir:

<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>

${AUCTION_PRICE} makrosu, bir video reklam öğesinin VAST URL'sine de dahil edilebilir ancak VAST'teki gösterim URL'sine dahil edilemez:

https://example.com/vast/v?price=${AUCTION_PRICE}

Senaryo

  1. OpenRTB teklifli sistem uygulamanız, Google'a döndürdüğü HTML snippet'inde veya VAST URL'sinde ${AUCTION_PRICE} makrosunu içeriyor.
  2. Google, kazanan fiyatı makronun yerine doldurulmamış web güvenli base64 kodlamasıyla (RFC 3548) yerleştirir.
  3. Sana Özel snippet'i, seçtiğiniz biçimde onay alır. Örneğin, onay, reklamın bir parçası olarak oluşturulan görünmez bir piksel isteğinin URL'sinde iletilebilir.
  4. Sunucudaki uygulamanız, web'de güvenli base64 kullanarak kazanan fiyat bilgilerinin ve sonucun şifresini çözer.

Bağımlılıklar

Openssl gibi SHA-1 HMAC'yi destekleyen bir şifreleme kitaplığınız olmalıdır.

Örnek kod

Java ve C++'da sağlanan örnek kodu privatedatacommunicationprotocol projesinden indirebilirsiniz.

  • Java örnek kodu, Apache Commons projesindeki base64 kod çözücüyü kullanır. Referans uygulama gerekli kısmı içerdiğinden ve bu nedenle kendi kendine yeterli olduğundan Apache commons kodunu indirmeniz gerekmez.

  • C++ örnek kodunda OpenSSL base64 BIO yöntemi kullanılmaktadır. Web için güvenli base64 kodlu bir dize (RFC 3548) alır ve bu dizenin kodunu çözer. Normalde web'de güvenli base64 dizeleri, "=" dolgusunu "." ile değiştirir (tırnak işaretlerinin okunabilirliği artırmak için eklendiğini ve protokole dahil edilmediğini unutmayın). Ancak makro değiştirme, şifrelenmiş fiyatı doldurmaz. OpenSSL, doldurulmamış dizelerle ilgili sorun yaşadığından referans uygulamada doldurma işlemi eklenir.

Kodlama

Kazanan fiyat şifreleme ve şifre çözme işlemi için iki gizli ancak paylaşılan anahtar gerekir. Sırasıyla i_key ve e_key olarak adlandırılan bir bütünlük anahtarı ve şifreleme anahtarı. Her iki anahtar da hesap kurulumunda web'de güvenli base64 dizesi olarak sağlanır ve Authorized Buyers sayfasındaki Teklif veren ayarları > GZT ayarları > Şifreleme anahtarları bölümünde bulunabilir.

Örnek bütünlük ve şifreleme anahtarları:

skU7Ax_NL5pPAFyKdkfZjZz2-VhIN8bjj1rVFOaJ_5o=  // Encryption key (e_key)
arO23ykdNqUQ5LEoQ0FVmPkBd7xB5CO89PDZlSjpFxo=  // Integrity key (i_key)

Anahtarlar, uygulamanız tarafından web için güvenli şekilde kod çözülmeli ve ardından base64 olarak kod çözülmelidir:

e_key = WebSafeBase64Decode('skU7Ax_NL5pPAFyKdkfZjZz2-VhIN8bjj1rVFOaJ_5o=')
i_key = WebSafeBase64Decode('arO23ykdNqUQ5LEoQ0FVmPkBd7xB5CO89PDZlSjpFxo=')

Şifreleme şeması

Fiyat, yeterli güvenlik sağlarken boyut yükü en aza indirmek için tasarlanmış özel bir şifreleme şeması kullanılarak şifrelenir. Şifreleme şeması, benzersiz gösterim etkinliği kimliğine göre gizli bir blok oluşturmak için anahtarlanmış bir HMAC algoritması kullanır.

Şifrelenmiş fiyat 28 bayt uzunluğundadır. 16 baytlık bir başlatma vektörü, 8 bayt şifrelenmiş metin ve 4 baytlık bir bütünlük imzasından oluşur. Şifrelenmiş fiyat, RFC 3548'e göre web güvenli base64 kodlu ve dolgu karakterleri atlanmış şekildedir. Bu nedenle, 28 baytlık şifrelenmiş fiyat, ödenen kazanan fiyattan bağımsız olarak 38 karakterli web'de güvenli base64 dizesi olarak kodlanır.

Şifrelenmiş fiyatlar örneği:

YWJjMTIzZGVmNDU2Z2hpN7fhCuPemCce_6msaw  // 100 CPI micros
YWJjMTIzZGVmNDU2Z2hpN7fhCuPemCAWJRxOgA  // 1900 CPI micros
YWJjMTIzZGVmNDU2Z2hpN7fhCuPemC32prpWWw  // 2700 CPI micros

Şifrelenmiş biçim:

{initialization_vector (16 bytes)}{encrypted_price (8 bytes)}
{integrity (4 bytes)}

Fiyat <price xor HMAC(encryption_key, initialization_vector)> olarak şifrelenir. Bu nedenle şifre çözme işlemi, şifrelemeyi tersine çevirmek için HMAC(encryption_key,initialization_vector) değerini hesaplar ve şifrelenmiş fiyatla xor işlemi yapar. Bütünlük aşaması, || birleştirme işlemi olduğunda 4 bayt <HMAC(integrity_key, price||initialization_vector)> alır.

Girişler
iv başlatma vektörü (16 bayt - gösterime özgüdür)
e_key şifreleme anahtarı (32 bayt - hesap kurulumunda sağlanır)
i_key bütünlük anahtarı (32 bayt - hesap kurulumunda sağlanır)
price (8 bayt - hesap para biriminin mikro cinsinden değeri)
Nota
hmac(k, d) k anahtarını kullanarak d verilerinin SHA-1 HMAC'si
a || b a dizesi, b dizesiyle birleştirilmiştir
Sözde kod
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 )

Şifre çözme şeması

Şifre çözme kodunuz, şifreleme anahtarını kullanarak fiyatın şifresini çözmeli ve bütünlük bitlerini bütünlük anahtarıyla doğrulamalıdır. Anahtarlar kurulum sırasında size sağlanır. Uygulamanızı nasıl yapılandıracağınızla ilgili ayrıntılar konusunda herhangi bir kısıtlama yoktur. Çoğu durumda, örnek kodu alıp ihtiyaçlarınıza göre uyarlayabilirsiniz.

Girişler
e_key şifreleme anahtarı, 32 bayt - hesap kurulumunda sağlanır
i_key Bütünlük anahtarı, 32 bayt - hesap kurulumunda sağlanır
final_message 38 karakter, web güvenli base64 kodlu
Sözde kod
// 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)

Eski yanıt saldırılarını algılama

Eski yanıt veya yeniden oynatma saldırılarını tespit etmek için saat dilimi farklılıklarını hesaba katarak yanıtları, sistem zamanından önemli ölçüde farklı bir zaman damgasına sahip olanlarla filtrelemeniz önerilir.

İlk 8 bayt, başlatma vektöründe bir zaman damgası içerir. Aşağıdaki C++ işlevi tarafından okunabilir:

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)
}

Zaman damgası, aşağıdaki C++ kodu kullanılarak kullanıcı tarafından okunabilir bir forma dönüştürülebilir:

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 kitaplığı

Kazanan fiyatı kodlamak ve kodunu çözmek için kriptografik algoritmaları uygulamak yerine DoubleClickCrypto.java dosyasını kullanabilirsiniz. Daha fazla bilgi için Kriptografi bölümüne bakın.