Saat materi iklan Anda memenangkan lelang, Google dapat memberitahukan harga
pemenang jika cuplikan HTML atau URL VAST yang menentukan materi iklan menyertakan
makro
WINNING_PRICE
. Google menampilkan harga pemenang dalam bentuk terenkripsi. Topik berikut
menjelaskan cara aplikasi Anda dapat mendekripsi informasi harga pemenang.
Makro WINNING_PRICE
dapat disertakan dalam materi iklan, misalnya, dengan permintaan piksel
tidak terlihat yang dirender sebagai bagian dari iklan:
<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>
Makro WINNING_PRICE
juga dapat disertakan dalam URL VAST materi iklan video (tetapi tidak dalam URL tayangan di
VAST):
https://example.com/vast/v?price=%%WINNING_PRICE%%
Skenario
- Aplikasi Anda menyertakan makro
WINNING_PRICE
di cuplikan HTML atau URL VAST yang ditampilkan ke Google. - Google mengganti harga yang unggul untuk makro dalam encoding base64 yang aman untuk web tanpa padding (RFC 3548).
- Cuplikan akan meneruskan konfirmasi dalam format yang telah Anda pilih. Misalnya, konfirmasi mungkin diteruskan di URL permintaan piksel tidak terlihat yang dirender sebagai bagian dari iklan.
- Di server, aplikasi Anda dalam base64 yang aman untuk web akan mendekode informasi harga pemenang dan mendekripsi hasilnya.
Dependensi
Anda akan memerlukan library kripto yang mendukung HMAC SHA-1, seperti Openssl.
Kode contoh
Kode contoh disediakan di Java dan C++ serta dapat didownload dari project privatedatacommunicationprotocol.
Kode contoh Java menggunakan decoder base64 dari project commons Apache. Anda tidak perlu mendownload kode Apache commons, karena implementasi referensi menyertakan bagian yang diperlukan sehingga bersifat mandiri.
Kode contoh C++ menggunakan metode BIO base64 OpenSSL. Diperlukan string berenkode base64 yang aman untuk web (RFC 3548) dan mendekodenya. Biasanya, string base64 yang aman untuk web menggantikan padding "=" dengan "." (perhatikan bahwa tanda kutip ditambahkan untuk kejelasan pembacaan dan tidak disertakan dalam protokol), tetapi penggantian makro tidak menambahkan harga yang dienkripsi. Implementasi referensi menambahkan padding karena OpenSSL mengalami masalah dengan string yang tidak diberi padding.
Encoding
Enkripsi dan dekripsi harga pemenang memerlukan dua kunci rahasia, tetapi
dibagikan. Kunci integritas dan kunci enkripsi, masing-masing disebut sebagai i_key
,
dan e_key
. Kedua kunci disediakan saat pembuatan akun sebagai string base64 yang aman untuk web, dan dapat ditemukan di halaman Authorized Buyers pada bagian Setelan bidder > Setelan RTB > Kunci enkripsi.
Contoh kunci integritas dan enkripsi:
skU7Ax_NL5pPAFyKdkfZjZz2-VhIN8bjj1rVFOaJ_5o= // Encryption key (e_key) arO23ykdNqUQ5LEoQ0FVmPkBd7xB5CO89PDZlSjpFxo= // Integrity key (i_key)
Kunci harus didekode dengan aman untuk web, lalu didekode dalam base64 oleh aplikasi Anda:
e_key = WebSafeBase64Decode('skU7Ax_NL5pPAFyKdkfZjZz2-VhIN8bjj1rVFOaJ_5o=') i_key = WebSafeBase64Decode('arO23ykdNqUQ5LEoQ0FVmPkBd7xB5CO89PDZlSjpFxo=')
Skema enkripsi
Harga dienkripsi menggunakan skema enkripsi kustom yang dirancang untuk meminimalkan overhead ukuran sekaligus memastikan keamanan yang memadai. Skema enkripsi ini menggunakan algoritma HMAC dengan kunci untuk membuat secret pad berdasarkan ID peristiwa tayangan yang unik.
Harga terenkripsi memiliki panjang tetap 28 byte. Kode ini terdiri dari vektor inisialisasi 16 byte, ciphertext 8 byte, dan tanda tangan integritas 4 byte. Harga yang dienkripsi dienkode menggunakan base64 yang aman untuk web, menurut RFC 3548, dengan karakter padding dihilangkan. Dengan demikian, harga terenkripsi 28 byte dienkode sebagai string base-64 yang aman untuk web dengan 38 karakter, terlepas dari harga unggul yang dibayarkan.
Contoh harga yang dienkripsi:
YWJjMTIzZGVmNDU2Z2hpN7fhCuPemCce_6msaw // 100 CPI micros YWJjMTIzZGVmNDU2Z2hpN7fhCuPemCAWJRxOgA // 1900 CPI micros YWJjMTIzZGVmNDU2Z2hpN7fhCuPemC32prpWWw // 2700 CPI micros
Format yang dienkripsi adalah:
{initialization_vector (16 bytes)}{encrypted_price (8 bytes)} {integrity (4 bytes)}
Harga dienkripsi sebagai <price xor HMAC(encryption_key,
initialization_vector)>
sehingga dekripsi menghitung
HMAC(encryption_key,initialization_vector)
dan xor dengan
harga terenkripsi untuk membalikkan enkripsi. Tahap integritas memerlukan 4 byte
<HMAC(integrity_key, price||initialization_vector)>
dengan
||
adalah penyambungan.
Input | |
---|---|
iv |
vektor inisialisasi (16 byte - unik untuk tayangan) |
e_key |
kunci enkripsi (32 byte - disediakan saat penyiapan akun) |
i_key |
kunci integritas (32 byte - disediakan saat penyiapan akun) |
price |
(8 byte - dalam mikro mata uang akun) |
Notasi | |
hmac(k, d) |
HMAC SHA-1 data d , menggunakan kunci k |
a || b |
string a disambungkan dengan string b |
Kode semu | |
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 ) |
Skema dekripsi
Kode dekripsi Anda harus mendekripsi harga menggunakan kunci enkripsi, dan memverifikasi bit integritas dengan kunci integritas. Kunci akan diberikan kepada Anda selama penyiapan. Tidak ada batasan terkait detail cara Anda menyusun implementasi. Secara umum, Anda harus dapat mengambil kode contoh dan menyesuaikannya sesuai dengan kebutuhan.
Input | |
---|---|
e_key |
kunci enkripsi, 32 byte - disediakan saat penyiapan akun |
i_key |
kunci integritas, 32 byte - disediakan saat penyiapan akun |
final_message |
38 karakter yang dienkode dalam base64 yang aman untuk web |
Kode semu | |
// 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) |
Mendeteksi serangan respons yang sudah tidak berlaku
Untuk mendeteksi serangan respons yang sudah tidak berlaku, atau replay, sebaiknya Anda memfilter respons dengan stempel waktu yang berbeda secara signifikan dari waktu sistem, setelah memperhitungkan perbedaan zona waktu.
Vektor inisialisasi berisi stempel waktu dalam 8 byte pertama. Tabel ini dapat dibaca oleh fungsi C++ berikut:
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) }
Stempel waktu dapat dikonversi ke bentuk yang dapat dibaca manusia menggunakan kode C++ berikut:
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);
Library Java
Daripada menerapkan algoritma kripto untuk mengenkode dan mendekode harga yang menang, Anda dapat menggunakan DoubleClickCrypto.java. Untuk informasi selengkapnya, lihat Kriptografi.