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

Reklam öğeniz bir açık artırmayı kazandığında, reklam öğesini tanımlayan HTML snippet'i veya VAST URL'si WINNING_PRICE makrosunu içeriyorsa Google, kazanan fiyatın ne olduğunu size bildirebilir. Google, kazanan fiyatı şifrelenmiş biçimde döndürür. Aşağıdaki konularda, uygulamanızın kazanan fiyat bilgilerinin şifresini nasıl çözebileceği açıklanmaktadır.

WINNING_PRICE makrosu bir reklam öğesine eklenebilir. Örneğin, reklamın parçası olarak görünmez bir piksel isteği oluşturulabilir:

<div>
  <script language='JavaScript1.1' src='https://example.com?creativeID=5837243'/>
  <img src='https://example.com/t.gif?price=%%WINNING_PRICE%%' width='1' height='1'/>
</div>

WINNING_PRICE makrosu, bir video reklam öğesinin VAST URL'sine de dahil edilebilir (ancak VAST'taki gösterim URL'sine dahil edilemez):

https://example.com/vast/v?price=%%WINNING_PRICE%%

Senaryo

  1. Uygulamanız, WINNING_PRICE makrosunu HTML snippet'inde veya Google'a döndürdüğü VAST URL'sinde içeriyor.
  2. Google, makronun kazanan fiyatını doldurulmamış web için güvenli base64 kodlamasıyla (RFC 3548) değiştirir.
  3. Snippet, onayı seçtiğiniz biçimde iletir. Örneğin, onay, reklamın parçası olarak oluşturulan görünmez bir piksel isteğinin URL'sinde iletilebilir.
  4. Sunucuda, web güvenli base64 uygulamanız kazanan fiyat bilgilerinin kodunu çözer ve sonucun şifresini çözer.

Bağımlılıklar

SHA-1 HMAC'yi destekleyen Openssl gibi bir şifreleme kitaplığına ihtiyacınız olacaktır.

Örnek kod

Örnek kod, Java ve C++'ta sağlanır ve privatedatacommunicationprotocol projesinden indirilebilir.

  • Java örnek kodu, Apache Commons projesindeki base64 kod çözücüyü kullanır. Referans uygulaması gerekli bölümü içerdiğinden ve bu nedenle bağımsız olduğundan Apache Commons kodunu indirmeniz gerekmez.

  • C++ örnek kodu, OpenSSL base64 BIO yöntemini kullanır. Web güvenli base64 kodlu bir dize (RFC 3548) alır ve kodunu çözer. Normalde web güvenli base64 dizeleri, "=" dolgusunu "." ile değiştirir (okumanın daha kolay anlaşılması için tırnak işaretleri eklendiğini ve protokole dahil edilmediğini unutmayın) ancak makro değişikliği, şifrelenmiş fiyatı doldurmaz. Referans uygulaması, OpenSSL doldurulmamış dizelerle ilgili sorun yaşadığından dolgu ekler.

Kodlama

Fiyat şifreleme ve şifre çözmeyi kazanmak 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 kurulumu sırasında web için güvenli base64 dizeleri olarak sağlanır ve Authorized Buyers sayfasında Teklif veren ayarları > RTB ayarları > Şifreleme anahtarları altında bulunabilir.

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

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

Anahtarların kodu web'de şifrelenmeli ve uygulamanız tarafından base64 kodu çözilmelidir:

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

Şifreleme şeması

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

Şifrelenmiş fiyatın 28 bayt sabit uzunluğu vardır. 16 baytlık bir başlatma vektörü, 8 baytlık şifrelenmiş metin ve 4 baytlık bütünlük imzasından oluşur. Şifrelenmiş fiyat, RFC 3548'e göre web için güvenli base64 kodludur ve dolgu karakterleri atlanır. Bu nedenle 28 bayt şifreli fiyat, ödenen fiyattan bağımsız olarak 38 karakterli web için güvenli base 64 dizesi olarak kodlanır.

Şifrelenmiş fiyatlara örnek:

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 şifrelendiğinden şifre çözme işlemi, şifrelemeyi tersine çevirmek için şifrelenmiş fiyatı HMAC(encryption_key,initialization_vector) ve xor'u hesaplar. Bütünlük aşaması, <HMAC(integrity_key, price||initialization_vector)> boyutunda 4 baytlık alanı kaplar. Burada ||, birleştirme işlemidir.

Girişler
iv başlatma vektörü (16 bayt - gösterime özel)
e_key şifreleme anahtarı (32 bayt, hesap kurulumu sırasında sağlanır)
i_key bütünlük anahtarı (32 bayt, hesap kurulumu sırasında sağlanır)
price (8 bayt: hesap para biriminin mikro cinsinden ifadesi)
Notasyon
hmac(k, d) d verilerinin SHA-1 HMAC'si (k anahtarı kullanılarak)
a || b a dizesi b dizesiyle birleştirildi
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 verilir. Uygulamanızı nasıl yapılandıracağınızla ilgili ayrıntılara dair herhangi bir kısıtlama yoktur. Çoğunlukla, örnek kodu alıp ihtiyaçlarınıza göre uyarlamanız gerekir.

Girişler
e_key şifreleme anahtarı, 32 bayt (hesap kurulumu sırasında sağlanır)
i_key bütünlük anahtarı, 32 bayt (hesap kurulumu sırasında sağlanır)
final_message 38 karakter uzunluğunda 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ı tespit etme

Eski yanıtları veya tekrar saldırıları tespit etmek için, saat dilimi farklarını hesaba kattıktan sonra, sistem saatinden önemli ölçüde farklı bir zaman damgasına sahip yanıtları filtrelemeniz önerilir.

Başlatma vektörü, ilk 8 baytta bir zaman damgası içerir. Aşağıdaki C++ işleviyle 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 insanların okuyabileceği 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 kripto algoritmalarını uygulamak yerine DoubleClickCrypto.java'yı kullanabilirsiniz. Daha fazla bilgi için Kriptografi konusuna bakın.