פענוח של אישורי מחיר

אם הקריאייטיב שלכם זוכה במכרז, Google יכולה להודיע לכם מה היה המחיר הזוכה אם הקריאייטיב כולל את המאקרו ${AUCTION_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}

תרחיש

  1. בקשת הבידינג ב-OpenRTB כוללת את המאקרו ${AUCTION_PRICE} בקטע ה-HTML או בכתובת ה-URL של ה-VAST שהיא מחזירה ל-Google.
  2. Google מחליפה את המחיר המנצח במאקרו בקידוד Base64 ללא תוספת שטח (padding) שבטוח לשימוש באינטרנט (RFC 3548).
  3. קטע הקוד מעביר את האישור בפורמט שבחרתם. לדוגמה, האישור עשוי לעבור בכתובת ה-URL של בקשה של פיקסל בלתי נראה שעבר רינדור כחלק מהמודעה.
  4. בשרת, ה-base64 של האפליקציה שמתאים לאינטרנט מפענח את פרטי המחיר הזוכה ומפענח את התוצאה.

יחסי תלות

תצטרכו ספריית קריפטוגרפיה שתומכת ב-SHA-1 HMAC, כמו Openssl.

קוד לדוגמה

קוד לדוגמה זמין ב-Java וב-C++‎, וניתן להוריד אותו מפרויקט privatedatacommunicationprotocol.

  • בקוד לדוגמה ב-Java נעשה שימוש במפענח base64 מפרויקט Apache commons. לא תצטרכו להוריד את הקוד של Apache commons, כי ההטמעה לדוגמה כוללת את החלק הנדרש, ולכן היא עצמאית.

  • בקוד לדוגמה ב-C++‎ נעשה שימוש בשיטת BIO של base64 ב-OpenSSL. הפונקציה מקבלת מחרוזת בקידוד Base64 שבטוח לשימוש באינטרנט (RFC 3548) ומפענחת אותה. בדרך כלל, מחרוזות base64 לשימוש באינטרנט מחליפות את המילוי '="' ב-'.' (שימו לב שמוסיפים מירכאות כדי להקל על הקריאה, והן לא נכללות בפרוטוקול), אבל החלפת המאקרו לא ממלאת את המחיר המוצפן. הטמעת העזרה מוסיפה מילוי כי ל-OpenSSL יש בעיות עם מחרוזות ללא מילוי.

קידוד

כדי להצפין ולפענח את המחיר הזוכה, נדרשים שני מפתחות סודיים, אבל משותפים. מפתח תקינות ומפתח הצפנה, שנקראים i_key ו-e_key, בהתאמה. שני המפתחות ניתנים במהלך הגדרת החשבון כמחרוזות base64 ללא סיכון לאינטרנט, וניתן למצוא אותם בדף Authorized Buyers בקטע Bidder settings > RTB settings > Encryption keys.

דוגמאות למפתחות תקינות והצפנה:

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 בייטים. הוא מורכב מוקטור אתחול (IV) באורך 16 בייטים, מ-8 בייטים של טקסט מוצפן ומחתימה על תקינות באורך 4 בייטים. המחיר המוצפן מקודד ב-Base64 לשימוש באינטרנט, בהתאם ל-RFC 3548, בלי תווי מילוי. לכן, המחיר המוצפן באורך 28 בייטים מקודד כמחרוזת Base64 בטוחה לאינטרנט באורך 38 תווים, ללא קשר למחיר הזוכה ששולם.

דוגמה למחירים מוצפנים:

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 בייטים – ב-micros של מטבע החשבון)
תווים
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. למידע נוסף, ראו קריפטוגרפיה.