हाइपरलोकल टारगेटिंग सिग्नल डिक्रिप्ट करें

अगर प्रकाशक ऐसे खरीदार को मोबाइल लोकेशन डेटा पास करते हैं जो एक पिन कोड के मुकाबले ज़्यादा खास हैं, तो Authorized Buyers, खरीदारों को नए एन्क्रिप्ट (सुरक्षित) किए गए फ़ील्ड में 'हाइपरलोकल' जियोफ़ेंस भेजेगा: BidRequest.encrypted_hyperlocal_set.

टाइमलाइन

  1. उपयोगकर्ता, विज्ञापन के साथ काम करने वाला मोबाइल ऐप्लिकेशन इंस्टॉल करता है और ऐप्लिकेशन को तीसरे पक्ष के साथ डिवाइस की जगह की जानकारी ऐक्सेस करने और शेयर करने के लिए सहमति देता है. यह ऐप्लिकेशन, Google Ads SDK टूल से भी जुड़ा हुआ है. साथ ही, यह डिवाइस की जगह की जानकारी, Google को भेजता है.
  2. Google सर्वर, डिवाइस की जगह के आस-पास के जियोफ़ेंस को दिखाने वाला एक खास हाइपरलोकल टारगेटिंग सिग्नल जनरेट करते हैं, जैसे कि उपयोगकर्ता की निजता की सुरक्षा करने के लिए.
  3. Google सर्वर, हर खरीदार के लिए खास सुरक्षा कुंजी का इस्तेमाल करके, हाइपरलोकल टारगेटिंग सिग्नल को सीरियल और एन्क्रिप्ट (सुरक्षित) करता है. ध्यान दें कि बोली लगाने वाला व्यक्ति WINNING_PRICE मैक्रो को डिक्रिप्ट करने के लिए, उसी कुंजी पर निर्भर करता है.
  4. बोली लगाने वाला आपका व्यक्ति, हाइपरलोकल टारगेटिंग सिग्नल को डिक्रिप्ट करता है. साथ ही, उसे प्रोटोकॉल बफ़र में बदल देता है. इसके बाद, बोली लगाने वाला व्यक्ति उस सिग्नल का विश्लेषण करके उसके मुताबिक बोली लगा सकता है.

डिपेंडेंसी

आपको एक ऐसी क्रिप्टो लाइब्रेरी की ज़रूरत होगी जिस पर SHA-1 HMAC की सुविधा हो, जैसे कि Openssel.

परिभाषा

प्रोटोरियल टारगेटिंग सिग्नल को इस तरह परिभाषित किया गया है:

// A hyperlocal targeting location when available.
//
message Hyperlocal {
  // A location on the Earth's surface.
  //
  message Point {
    optional float latitude = 1;
    optional float longitude = 2;
  }

  // The mobile device can be at any point inside the geofence polygon defined
  // by a list of corners.  Currently, the polygon is always a parallelogram
  // with 4 corners.
  repeated Point corners = 1;
}

message HyperlocalSet {
  // This field currently contains at most one hyperlocal polygon.
  repeated Hyperlocal hyperlocal = 1;

  // The approximate geometric center of the geofence area.  It is calculated
  // exclusively based on the geometric shape of the geofence area and in no
  // way indicates the mobile device's actual location within the geofence
  // area. If multiple hyperlocal polygons are specified above then
  // center_point is the geometric center of all hyperlocal polygons.
  optional Hyperlocal.Point center_point = 2;
}

// Hyperlocal targeting signal when available, encrypted as described at
// https://developers.google.com/authorized-buyers/rtb/response-guide/decrypt-hyperlocal
optional bytes encrypted_hyperlocal_set = 40;

हर हाइपरलोकल टारगेटिंग सिग्नल में एक या उससे ज़्यादा पॉलीगॉन और बीच में एक पॉइंट होता है. हर पॉलीगॉन के लिए, हाइपरलोकल टारगेटिंग सिग्नल में ये शामिल होते हैं:

  • पॉलीगॉन के हर कोने के अक्षांश और देशांतर को, दोहराए गए corners फ़ील्ड के तौर पर पास किया गया है.
  • जियोफ़ेंस एरिया का अनुमानित ज्यामितीय केंद्र, जो वैकल्पिक center_point फ़ील्ड में पास किया गया है.

टारगेटिंग सिग्नल का स्ट्रक्चर

BidRequest.encrypted_hyperlocal_set में मौजूद एन्क्रिप्ट किए गए हाइपरलोकल टारगेटिंग सिग्नल में तीन सेक्शन होते हैं:

  • initialization_vector: 16-बाइट.
  • ciphertext: 20-बाइट वाले सेक्शन की सीरीज़.
  • integrity_signature: 4-बाइट.
{initialization_vector (16 bytes)}{ciphertext (20-byte sections)}{integrity_signature (4 bytes)}

ciphertext बाइट कैटगरी को 20-बाइट वाले कई सेक्शन में बांटा जाता है. हालांकि, आखिरी सेक्शन में 1 से 20 बाइट के बीच हो सकते हैं. ओरिजनल byte_array के हर सेक्शन के लिए, 20-बाइट का ciphertext जनरेट किया जाता है:

<byte_array <xor> HMAC(encryption_key, initialization_vector || counter_bytes)>

जहां || जोड़ने की समस्या होती है.

परिभाषाएं

वैरिएबल जानकारी
initialization_vector 16 बाइट - इंप्रेशन के लिए खास.
encryption_key 32 बाइट - खाता सेट अप करते समय उपलब्ध कराया गया.
integrity_key 32 बाइट - खाता सेट अप करते समय उपलब्ध कराया गया.
byte_array 20-बाइट सेक्शन में, HyperlocalSet ऑब्जेक्ट क्रम से लगाया गया है.
counter_bytes बाइट वैल्यू, जो सेक्शन की क्रम संख्या बताती है, नीचे देखें.
final_message BidRequest.encrypted_hyperlocal_set फ़ील्ड से भेजी गई बाइट कैटगरी.
ऑपरेटर जानकारी
hmac(key, data) SHA-1 HMAC, data को एन्क्रिप्ट करने के लिए key का इस्तेमाल कर रहा है.
a || b स्ट्रिंग b के साथ a स्ट्रिंग जोड़ी गई.

काउंटर_बाइट का हिसाब लगाना

counter_bytes, ciphertext के हर 20-बाइट वाले सेक्शन का क्रम दिखाता है. ध्यान दें कि आखिरी सेक्शन में 1 से लेकर 20 बाइट तक हो सकते हैं. अपना hmac() फ़ंक्शन चलाते समय सही वैल्यू के साथ counter_bytes भरने के लिए, 20-बाइट सेक्शन की गिनती करें (बचे हुए हिस्से भी शामिल हैं) और नीचे दी गई रेफ़रंस टेबल का इस्तेमाल करें:

सेक्शन नंबर counter_bytes की कीमत का
0 कभी नहीं
1 ... 256 1 बाइट. वैल्यू, क्रम से 0 से बढ़कर 255 हो जाती है.
257 ... 512 दो बाइट. पहले बाइट की वैल्यू 0 होती है, जिससे दूसरी बाइट की वैल्यू, क्रम से 0 से बढ़कर 255 हो जाती है.
513 ... 768 तीन बाइट. पहले दो बाइट की वैल्यू 0 है, आखिरी बाइट की वैल्यू क्रम से 0 से बढ़कर 255 हो जाती है.

हमें लगता है कि BidRequest.encrypted_hyperlocal_set की लंबाई एक किलोबाइट से ज़्यादा नहीं होनी चाहिए. भले ही, हम इसे और आगे ले जा रहे हों. हालांकि, counter_bytes ज़रूरत के मुताबिक लंबे समय तक काम कर सकता है. ऐसा करने से, आर्बिट्रेरी लंबाई वाले हाइपरलोकल टारगेटिंग सिग्नल का इस्तेमाल किया जा सकेगा.

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

हाइपरलोकल टारगेटिंग सिग्नल के लिए एन्क्रिप्शन स्कीम, डिक्रिप्टिंग प्राइस की पुष्टि करने में इस्तेमाल किए गए उसी स्कीम पर आधारित होती है.

  1. क्रम से लगाना: हाइपरलोकल टारगेटिंग सिग्नल, जो प्रोटो में बताए गए हाइपरलोकल सेट ऑब्जेक्ट का उदाहरण है, को पहले SerializeAsString() से बाइट श्रेणी में रखा जाता है.

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

एन्क्रिप्शन स्यूडोकोड

byte_array = SerializeAsString(HyperlocalSet object)
pad = hmac(encryption_key, initialization_vector || counter_bytes )  // for each 20-byte section of byte_array
ciphertext = pad <xor> byte_array // for each 20-byte section of byte_array
integrity_signature = hmac(integrity_key, byte_array || initialization_vector)  // first 4 bytes
final_message = initialization_vector || ciphertext || integrity_signature

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

आपके डिक्रिप्शन कोड में, 1) एन्क्रिप्ट (सुरक्षित) करने के तरीके वाली कुंजी का इस्तेमाल करके हाइपरलोकल टारगेटिंग सिग्नल को डिक्रिप्ट करना होगा और 2) पूरी सुरक्षा देने वाली कुंजी की पुष्टि करना होगा. आपको खाता सेट अप करने के दौरान कुंजियां दी जाएंगी. आपके लागू करने के तरीके पर कोई पाबंदी नहीं लगाई गई है. ज़्यादातर मामलों में, आपको नमूना कोड लेने और उसे अपनी ज़रूरत के हिसाब से बनाने में सक्षम होना चाहिए.

  1. अपना पैड जनरेट करें: HMAC(encryption_key, initialization_vector || counter_bytes)
  2. XOR: एन्क्रिप्ट (सुरक्षित) करने के तरीके को उलटने के लिए, साइफ़रटेक्स्ट का इस्तेमाल करके यह नतीजा और <xor> लें.
  3. पुष्टि करें: पूरी सुरक्षा देने की सुविधा का हस्ताक्षर, HMAC(integrity_key, byte_array || initialization_vector) की 4 बाइट से ज़्यादा नहीं होना चाहिए

डिक्रिप्शन स्यूडोकोड

(initialization_vector, ciphertext, integrity_signature) = final_message // split up according to length rules
pad = hmac(encryption_key, initialization_vector || counter_bytes)  // for each 20-byte section of ciphertext
byte_array = ciphertext <xor> pad // for each 20-byte section of ciphertext
confirmation_signature = hmac(integrity_key, byte_array || initialization_vector)
success = (confirmation_signature == integrity_signature)

नमूना C++ कोड

यहां डिक्रिप्शन के उदाहरण वाले कोड का एक मुख्य फ़ंक्शन दिया गया है.

bool DecryptByteArray(
    const string& ciphertext, const string& encryption_key,
    const string& integrity_key, string* cleartext) {
  // Step 1. find the length of initialization vector and clear text.
  const int cleartext_length =
      ciphertext.size() - kInitializationVectorSize - kSignatureSize;
  if (cleartext_length < 0) {
    // The length cannot be correct.
    return false;
  }

  string iv(ciphertext, 0, kInitializationVectorSize);

  // Step 2. recover clear text
  cleartext->resize(cleartext_length, '\0');
  const char* ciphertext_begin = string_as_array(ciphertext) + iv.size();
  const char* const ciphertext_end = ciphertext_begin + cleartext->size();
  string::iterator cleartext_begin = cleartext->begin();

  bool add_iv_counter_byte = true;
  while (ciphertext_begin < ciphertext_end) {
    uint32 pad_size = kHashOutputSize;
    uchar encryption_pad[kHashOutputSize];

    if (!HMAC(EVP_sha1(), string_as_array(encryption_key),
              encryption_key.length(), (uchar*)string_as_array(iv),
              iv.size(), encryption_pad, &pad_size)) {
      printf("Error: encryption HMAC failed.\n");
      return false;
    }

    for (int i = 0;
         i < kBlockSize && ciphertext_begin < ciphertext_end;
         ++i, ++cleartext_begin, ++ciphertext_begin) {
      *cleartext_begin = *ciphertext_begin ^ encryption_pad[i];
    }

    if (!add_iv_counter_byte) {
      char& last_byte = *iv.rbegin();
      ++last_byte;
      if (last_byte == '\0') {
        add_iv_counter_byte = true;
      }
    }

    if (add_iv_counter_byte) {
      add_iv_counter_byte = false;
      iv.push_back('\0');
    }
  }
}

हाइपरलोकल सिग्नल और कुंजियों का सैंपल

अपने कोड की जांच करने और उसकी पुष्टि करने के लिए:

  1. 308 हेक्स वर्णों वाली स्ट्रिंग को 154 बाइट की श्रेणी में बदलें. उदाहरण के लिए, यह स्ट्रिंग दें:
    E2014EA201246E6F6E636520736F7572636501414243C0ADF6B9B6AC17DA218FB50331EDB376701309CAAA01246E6F6E636520736F7572636501414243C09ED4ECF2DB7143A9341FDEFD125D96844E25C3C202466E6F6E636520736F7572636502414243517C16BAFADCFAB841DE3A8C617B2F20A1FB7F9EA3A3600256D68151C093C793B0116DB3D0B8BE9709304134EC9235A026844F276797
    
    उसे इस तरह 154-बाइट की श्रेणी में बदलें:
    const char serialized_result[154] = { 0xE2, 0x01, 0x4E, ... };
    
  2. 154-बाइट की श्रेणी को BidRequest प्रोटोकॉल बफ़र में बांटने के लिए, BidRequest.ParsePartialFromString() तरीके को कॉल करें.
    BidRequest bid_req;
    bid_req.ParsePartialFromString(serialzed_result);
    
  3. पुष्टि करें कि BidRequest में सिर्फ़ तीन फ़ील्ड हैं:
    • encrypted_hyperlocal_set
      BidReqeust मैसेज में बताया गया.
    • encrypted_advertising_id
      BidReqeust.Mobile मैसेज में बताया गया.
    • encrypted_hashed_idfa
      BidReqeust.Mobile मैसेज में बताया गया.

    उदाहरण के लिए:

    encrypted_hyperlocal_set:(
        {  100,  100 },
        {  200, -300 },
        { -400,  500 },
        { -600, -700 },)
    encrypted_advertising_id: { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11 }
    encrypted_hashed_idfa : { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0xF1 }
    
  4. तीनों फ़ील्ड को डिक्रिप्ट करने के लिए, इन encryption_key और integrity_key का इस्तेमाल करें और पुष्टि करें कि आपने उन्हें सही तरीके से डिक्रिप्ट किया हो.
    encryption_key = {0x02, 0xEE, 0xa8, 0x3c, 0x6c, 0x12, 0x11, 0xe1, 0x0b,
        0x9f, 0x88, 0x96, 0x6c, 0xee, 0xc3, 0x49, 0x08, 0xeb, 0x94, 0x6f, 0x7e,
        0xd6, 0xe4, 0x41, 0xaf, 0x42, 0xb3, 0xc0, 0xf3, 0x21, 0x81, 0x40};
    
    integrity_key = {0xbf, 0xFF, 0xec, 0x55, 0xc3, 0x01, 0x30, 0xc1, 0xd8,
        0xcd, 0x18, 0x62, 0xed, 0x2a, 0x4c, 0xd2, 0xc7, 0x6a, 0xc3, 0x3b, 0xc0,
        0xc4, 0xce, 0x8a, 0x3d, 0x3b, 0xbd, 0x3a, 0xd5, 0x68, 0x77, 0x92};
    

पुराने जवाब के हमलों का पता लगाना

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

लागू करने के बारे में ज़्यादा जानकारी के लिए, कीमतों को डिक्रिप्ट करने की पुष्टि करना लेख में, "स्टील रिस्पॉन्स के हमलों का पता लगाना" लेख देखें.

Java लाइब्रेरी

हाइपरलोकल टारगेटिंग सिग्नल को कोड में बदलने और डिकोड करने के बजाय, आप क्रिप्टो एल्गोरिदम लागू करने के बजाय DoubleClickCrypto.java का इस्तेमाल कर सकते हैं. ज़्यादा जानकारी के लिए, क्रिप्टोग्राफ़ी देखें.