डिक्रिप्ट की गई कीमत की पुष्टि

अगर आपका क्रिएटिव नीलामी जीतता है, तो 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} मैक्रो को वीडियो क्रिएटिव के VAST यूआरएल में भी शामिल किया जा सकता है. हालांकि, इसे VAST के इंप्रेशन यूआरएल में शामिल नहीं किया जा सकता:

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

स्थिति

  1. आपके OpenRTB बिडिंग ऐप्लिकेशन में, Google को दिखाए जाने वाले एचटीएमएल स्निपेट या VAST यूआरएल में ${AUCTION_PRICE} मैक्रो शामिल है.
  2. Google, मैक्रो के लिए जीतने वाली कीमत को बिना पैड वाले वेब-सेफ़ Base64 कोड (आरएफ़सी 3548) में बदल देता है.
  3. स्निपेट, आपके चुने गए फ़ॉर्मैट में पुष्टि करता है. उदाहरण के लिए, पुष्टि, विज्ञापन के हिस्से के तौर पर रेंडर किए गए किसी ऐसे पिक्सल अनुरोध के यूआरएल में की जा सकती है जो न दिखता हो.
  4. सर्वर पर, आपका ऐप्लिकेशन वेब-सेफ़ base64, जीतने वाले की कीमत की जानकारी को डिकोड करता है और नतीजे को डिक्रिप्ट करता है.

डिपेंडेंसी

आपको ऐसी क्रिप्टो लाइब्रेरी की ज़रूरत होगी जो SHA-1 HMAC के साथ काम करती हो. जैसे, Openssl.

नमूना कोड

सैंपल कोड, Java और C++ में दिया गया है. इसे privatedatacommunicationprotocol प्रोजेक्ट से डाउनलोड किया जा सकता है.

  • Java सैंपल कोड, Apache commons प्रोजेक्ट के base64 डिकोडर का इस्तेमाल करता है. आपको Apache commons कोड डाउनलोड करने की ज़रूरत नहीं होगी, क्योंकि रेफ़रंस लागू करने में ज़रूरी हिस्सा शामिल होता है. इसलिए, यह अपने-आप काम करता है.

  • C++ सैंपल कोड में, OpenSSL base64 BIO तरीके का इस्तेमाल किया गया है. यह वेब-सेफ़ base64 कोड में बदली गई स्ट्रिंग (आरएफ़सी 3548) को लेता है और उसे डिकोड करता है. आम तौर पर, वेब-सेफ़ base64 स्ट्रिंग, "=" पैडिंग को "." से बदल देती हैं. ध्यान दें कि कोटेशन मार्क, पढ़ने में आसानी के लिए जोड़े जाते हैं और प्रोटोकॉल में शामिल नहीं होते. हालांकि, मैक्रो सबस्टिट्यूशन, एन्क्रिप्ट की गई कीमत को पैड नहीं करता. रेफ़रंस लागू करने पर पैडिंग जोड़ी जाती है, क्योंकि OpenSSL को बिना पैड वाली स्ट्रिंग से समस्या होती है.

एन्कोडिंग

जीतने वाले को मिलने वाली कीमत को एन्क्रिप्ट (सुरक्षित) और डिक्रिप्ट (अनचाहे बदलावों से सुरक्षित) करने के लिए, दो सीक्रेट कुंजियों की ज़रूरत होती है. हालांकि, ये कुंजियां शेयर की जाती हैं. इंटिग्रिटी कुंजी और एन्क्रिप्शन कुंजी, जिन्हें क्रमशः i_key और e_key कहा जाता है. खाता सेट अप करते समय, दोनों कुंजियों को वेब-सेफ़ बेस64 स्ट्रिंग के तौर पर दिया जाता है. इन्हें Authorized Buyers पेज पर, बिडर सेटिंग > आरटीबी सेटिंग > एन्क्रिप्शन कुंजियां में देखा जा सकता है.

इंटिग्रिटी और एन्क्रिप्शन पासकोड के उदाहरण:

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=')

एन्क्रिप्शन स्कीम

कीमत को कस्टम एन्क्रिप्शन स्कीम का इस्तेमाल करके एन्क्रिप्ट किया जाता है. इस स्कीम को इस तरह से डिज़ाइन किया गया है कि यह ज़रूरत के मुताबिक सुरक्षा देने के साथ-साथ, डेटा के साइज़ को कम से कम रखे. एन्क्रिप्शन स्कीम, यूनीक इंप्रेशन इवेंट आईडी के आधार पर एक सीक्रेट पैड जनरेट करने के लिए, पासकोड वाले एचएमएसी एल्गोरिदम का इस्तेमाल करती है.

एन्क्रिप्ट की गई कीमत की लंबाई 28 बाइट होती है. इसमें 16 बाइट का इनिशलाइज़ेशन वेक्टर, 8 बाइट का एन्क्रिप्ट किया गया टेक्स्ट, और चार बाइट का इंटिग्रिटी हस्ताक्षर शामिल होता है. एन्क्रिप्ट की गई कीमत, RFC 3548 के मुताबिक वेब-सेफ़ base64 कोड में बदली गई होती है. इसमें पैडिंग कैरेक्टर शामिल नहीं होते. इसलिए, एन्क्रिप्ट की गई 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 का इस्तेमाल कर सके. इंटिग्रिटी स्टेज में <HMAC(integrity_key, price||initialization_vector)> के चार बाइट लगते हैं, जहां || को जोड़ा जाता है.

इनपुट
iv इनिशलाइज़ेशन वेक्टर (16 बाइट - इंप्रेशन के हिसाब से यूनीक)
e_key एन्क्रिप्शन पासकोड (32 बाइट - खाता सेट अप करते समय दिया जाता है)
i_key इंटिग्रिटी कुंजी (32 बाइट - खाता सेट अप करते समय दी जाती है)
price (8 बाइट - खाते की मुद्रा के माइक्रो में)
नोटेशन
hmac(k, d) कुंजी k का इस्तेमाल करके, डेटा d का SHA-1 एचएमएसी
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)

पुराने रिस्पॉन्स वाले हमलों का पता लगाना

पुराने रिस्पॉन्स या फिर से होने वाले हमलों का पता लगाने के लिए, हमारा सुझाव है कि आप टाइमज़ोन के अंतर को ध्यान में रखते हुए, रिस्पॉन्स को ऐसे टाइमस्टैंप के हिसाब से फ़िल्टर करें जो सिस्टम के टाइम से काफ़ी अलग हो.

शुरुआती वेक्टर के पहले आठ बाइट में टाइमस्टैंप होता है. इसे 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 का इस्तेमाल किया जा सकता है. ज़्यादा जानकारी के लिए, क्रिप्टोग्राफ़ी देखें.