Когда ваш креатив выигрывает аукцион, Google может сообщить вам выигрышную цену, если креатив содержит соответствующий макрос.
Если ваша система назначения ставок настроена на использование протокола OpenRTB, креатив, включенный в вашу ставку, должен использовать макрос ${AUCTION_PRICE}
IAB.
Если ваша система назначения ставок использует устаревший протокол Google RTB, в креативе должен использоваться макрос Google %%WINNING_PRICE%%
.
Когда эти макросы развернуты, они возвращают выигрышную цену в зашифрованном виде. Их можно включить в креатив, например, с помощью запроса невидимого пикселя, отображаемого как часть объявления:
<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}
также можно включить в URL-адрес VAST видеообъявления, но не в URL-адрес показа в VAST:
https://example.com/vast/v?price=${AUCTION_PRICE}
Сценарий
- Ваше приложение для назначения ставок OpenRTB включает макрос
${AUCTION_PRICE}
во фрагмент HTML или URL-адрес VAST, который он возвращает в Google. - Google заменяет выигрышную цену макроса недополненной веб-безопасной кодировкой Base64 ( RFC 3548 ).
- Фрагмент передает подтверждение в выбранном вами формате. Например, подтверждение может быть передано в URL-адресе запроса невидимого пикселя, отображаемого как часть объявления.
- На сервере ваше веб-приложение base64 декодирует информацию о выигрышной цене и расшифровывает результат.
Зависимости
Вам понадобится криптобиблиотека, поддерживающая SHA-1 HMAC, например Openssl.
Пример кода
Пример кода предоставляется на Java и C++, его можно загрузить из проекта Privatedatacommunicationprotocol .
В примере кода Java используется декодер base64 из проекта Apache commons . Вам не потребуется загружать общий код Apache, поскольку эталонная реализация включает необходимую часть и, следовательно, является автономной.
В примере кода C++ используется метод OpenSSL base64 BIO . Он принимает веб-безопасную строку в кодировке Base64 ( RFC 3548 ) и декодирует ее. Обычно в веб-безопасных строках Base64 заполнение "=" заменяется на "." (обратите внимание, что кавычки добавлены для ясности чтения и не включены в протокол), но макроподстановка не дополняет зашифрованную цену. Эталонная реализация добавляет заполнение, поскольку у OpenSSL возникают проблемы с незаполненными строками.
Кодирование
Для выигрышного шифрования и дешифрования требуются два секретных, но общих ключа. Ключ целостности и ключ шифрования, называемые i_key
и e_key
соответственно. Оба ключа предоставляются при настройке учетной записи в виде веб-безопасных строк в формате Base64. Их можно найти на странице «Авторизованные покупатели» в разделе «Настройки участника аукциона» > «Настройки RTB» > «Ключи шифрования» .
Пример ключей целостности и шифрования:
skU7Ax_NL5pPAFyKdkfZjZz2-VhIN8bjj1rVFOaJ_5o= // Encryption key (e_key) arO23ykdNqUQ5LEoQ0FVmPkBd7xB5CO89PDZlSjpFxo= // Integrity key (i_key)
Ключи должны быть декодированы в веб-безопасности, а затем декодированы в Base64 вашим приложением:
e_key = WebSafeBase64Decode('skU7Ax_NL5pPAFyKdkfZjZz2-VhIN8bjj1rVFOaJ_5o=') i_key = WebSafeBase64Decode('arO23ykdNqUQ5LEoQ0FVmPkBd7xB5CO89PDZlSjpFxo=')
Схема шифрования
Цена шифруется с использованием специальной схемы шифрования, которая предназначена для минимизации накладных расходов на размер при обеспечении адекватной безопасности. Схема шифрования использует алгоритм HMAC с ключом для создания секретной панели на основе уникального идентификатора события показа.
Зашифрованная цена имеет фиксированную длину 28 байт. Он состоит из 16-байтового вектора инициализации, 8-байтового зашифрованного текста и 4-байтовой подписи целостности. Зашифрованная цена имеет веб-безопасную кодировку Base64 в соответствии с RFC 3548, без дополнительных символов. Таким образом, 28-байтовая зашифрованная цена кодируется как 38-символьная веб-безопасная строка Base-64 независимо от уплаченной выигрышной цены.
Пример зашифрованных цен:
YWJjMTIzZGVmNDU2Z2hpN7fhCuPemCce_6msaw // 100 CPI micros YWJjMTIzZGVmNDU2Z2hpN7fhCuPemCAWJRxOgA // 1900 CPI micros YWJjMTIzZGVmNDU2Z2hpN7fhCuPemC32prpWWw // 2700 CPI micros
Зашифрованный формат:
{initialization_vector (16 bytes)}{encrypted_price (8 bytes)} {integrity (4 bytes)}
Цена зашифрована как <price xor HMAC(encryption_key, initialization_vector)>
поэтому при расшифровке вычисляется HMAC(encryption_key,initialization_vector)
и xor с зашифрованной ценой для отмены шифрования. Этап целостности занимает 4 байта <HMAC(integrity_key, price||initialization_vector)>
где ||
является конкатенация.
Входы | |
---|---|
iv | вектор инициализации (16 байт — уникальный для показа) |
e_key | ключ шифрования (32 байта — предоставляется при настройке учетной записи) |
i_key | ключ целостности (32 байта — предоставляется при настройке учетной записи) |
price | (8 байт - в микронах валюты счета) |
Обозначения | |
hmac(k, d) | SHA-1 HMAC данных d с использованием ключа k |
a || b | строка a объединена со строкой b |
Псевдокод | |
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 ) |
Схема расшифровки
Ваш код дешифрования должен расшифровать цену с помощью ключа шифрования и проверить биты целостности с помощью ключа целостности. Ключи будут предоставлены вам во время установки. Нет никаких ограничений на детали структурирования вашей реализации. По большей части вы сможете взять пример кода и адаптировать его в соответствии со своими потребностями.
Входы | |
---|---|
e_key | ключ шифрования, 32 байта — предоставляется при настройке учетной записи |
i_key | ключ целостности, 32 байта — предоставляется при настройке учетной записи |
final_message | 38 символов в веб-безопасной кодировке Base64 |
Псевдокод | |
// 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) |
Обнаружение устаревших ответных атак
Чтобы обнаружить атаки устаревшего ответа или повторного воспроизведения, рекомендуется фильтровать ответы по временной метке, которая значительно отличается от системного времени, после учета различий в часовых поясах.
Вектор инициализации содержит временную метку в первых 8 байтах. Его можно прочитать следующей функцией C++:
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) }
Временную метку можно преобразовать в удобочитаемую форму с помощью следующего кода C++:
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-библиотека
Вместо реализации криптоалгоритмов для кодирования и декодирования выигрышной цены вы можете использовать DoubleClickCrypto.java . Дополнительные сведения см. в разделе Криптография .