विज्ञापन नेटवर्क के लिए, विज्ञापन देने वाले के आइडेंटिफ़ायर को डिक्रिप्ट करना

Authorized Buyers की मदद से विज्ञापन भरने के लिए JavaScript टैग का इस्तेमाल करने वाली विज्ञापन नेटवर्क कंपनियां, Android और iOS, दोनों डिवाइस के लिए विज्ञापन देने वाले के आइडेंटिफ़ायर पा सकती हैं. यह जानकारी Authorized Buyers मैनेज किए जाने वाले JavaScript टैग में मौजूद %%EXTRA_TAG_DATA%% या %%ADVERTISING_IDENTIFIER%% मैक्रो से भेजी जाती है. इस सेक्शन के बाकी हिस्से में, %%EXTRA_TAG_DATA%% एक्सट्रैक्ट करने पर फ़ोकस किया गया है. %%ADVERTISING_IDENTIFIER%% एन्क्रिप्ट (सुरक्षित) किए गए प्रोटो बफ़र MobileAdvertisingId के बारे में ज़्यादा जानकारी के लिए, IDFA या विज्ञापन आईडी के साथ रीमार्केटिंग देखें. इस प्रोटो बफ़र को उसी हिसाब से डिक्रिप्ट किया जा सकता है.

टाइमलाइन

  1. Ad Network, Authorized Buyers यूज़र इंटरफ़ेस (यूआई) की मदद से, अपने JavaScript इन-ऐप्लिकेशन टैग को अपडेट करता है. इसके बारे में नीचे बताए गए तरीके से, %%EXTRA_TAG_DATA%% मैक्रो में जोड़ा जा सकता है.
  2. विज्ञापन दिखाते समय, ऐप्लिकेशन, विज्ञापन देने वाले के आइडेंटिफ़ायर को सुरक्षित तरीके से पास करते हुए, Google Mobile Ads SDK के ज़रिए Authorized Buyers से विज्ञापन का अनुरोध करता है.
  3. ऐप्लिकेशन को JavaScript टैग वापस मिल जाता है और उसके साथ %%EXTRA_TAG_DATA%% मैक्रो भरा हुआ होता है, जो एन्क्रिप्ट किए गए विज्ञापन नेटवर्क प्रोटोकॉल बफ़र से भरा होता है, जिसमें वह पहचानकर्ता होता है.
  4. यह ऐप्लिकेशन इस टैग को चलाता है, जिससे सबसे अच्छे विज्ञापन को विज्ञापन नेटवर्क कंपनी को कॉल करती है.
  5. इस जानकारी का इस्तेमाल (कमाई करने) के लिए, विज्ञापन नेटवर्क को प्रोटोकॉल बफ़र प्रोसेस करना होगा:
    1. WebSafeBase64 की मदद से, websafe स्ट्रिंग को वापस बाइटस्ट्रिंग में डिकोड करें.
    2. नीचे बताई गई स्कीम का इस्तेमाल करके इसे डिक्रिप्ट करें.
    3. प्रोटो को डीसीरियलाइज़ करें और ExtraTagData.advertising_id या ExtraTagData.hashed_idfa से विज्ञापन देने वाले का आईडी पाएं.

डिपेंडेंसी

  1. WebSafeBase64 एन्कोडर.
  2. ऐसी क्रिप्टो लाइब्रेरी जो SHA-1 एचएमएसी के साथ काम करती हो, जैसे कि Openएसएसएल.
  3. Google प्रोटोकॉल का बफ़र कंपाइलर.

websafe स्ट्रिंग को डिकोड करें

%%EXTRA_TAG_DATA%% मैक्रो से भेजी गई जानकारी, यूआरएल से भेजी जानी चाहिए. इस वजह से, Google के सर्वर इसे वेब के हिसाब से सुरक्षित base64 (RFC 3548) का इस्तेमाल करके कोड में बदल देते हैं.

इसलिए, डिक्रिप्शन की कोशिश करने से पहले, आपको ASCII वर्णों को वापस बाइटस्ट्रिंग में डिकोड करना होगा. नीचे दिया गया C++ कोड, OpenSSL Project के BIO_f_base64() पर आधारित है. यह Google के सैंपल डिक्रिप्शन कोड का हिस्सा है.

string AddPadding(const string& b64_string) {
  if (b64_string.size() % 4 == 3) {
    return b64_string + "=";
  } else if (b64_string.size() % 4 == 2) {
    return b64_string + "==";
  }
  return b64_string;
}

// Adapted from http://www.openssl.org/docs/man1.1.0/crypto/BIO_f_base64.html
// Takes a web safe base64 encoded string (RFC 3548) and decodes it.
// Normally, web safe base64 strings have padding '=' replaced with '.',
// but we will not pad the ciphertext. We add padding here because
// openssl has trouble with unpadded strings.
string B64Decode(const string& encoded) {
  string padded = AddPadding(encoded);
  // convert from web safe -> normal base64.
  int32 index = -1;
  while ((index = padded.find_first_of('-', index + 1)) != string::npos) {
    padded[index] = '+';
  }
  index = -1;
  while ((index = padded.find_first_of('_', index + 1)) != string::npos) {
    padded[index] = '/';
  }

  // base64 decode using openssl library.
  const int32 kOutputBufferSize = 256;
  char output[kOutputBufferSize];

  BIO* b64 = BIO_new(BIO_f_base64());
  BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
  BIO* bio = BIO_new_mem_buf(const_cast(padded.data()),
                             padded.length());
  bio = BIO_push(b64, bio);
  int32 out_length = BIO_read(bio, output, kOutputBufferSize);
  BIO_free_all(bio);
  return string(output, out_length);
}

एन्क्रिप्ट (सुरक्षित) की गई बाइट स्ट्रिंग का स्ट्रक्चर

ASCII वर्णों को वापस बाइट स्ट्रिंग में बदलने के बाद, उन्हें डिक्रिप्ट किया जा सकता है. एन्क्रिप्ट (सुरक्षित) की गई बाइट स्ट्रिंग में तीन सेक्शन होते हैं:

  • 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 सीरीज़ वाला ExtraTagData ऑब्जेक्ट, जो 20 बाइट वाले सेक्शन में मौजूद होता है.
counter_bytes बाइट की वैल्यू, सेक्शन की ऑर्डिनल संख्या दिखाती है. इसे नीचे देखें.
final_message %%EXTRA_TAG_DATA%% मैक्रो से भेजी गई कुल बाइट कलेक्शन (WebSafeBase64 एन्कोडिंग को छोड़कर).
ऑपरेटर जानकारी
hmac(key, data) SHA-1 HMAC, data को एन्क्रिप्ट करने के लिए key का इस्तेमाल कर रहा है.
a || b स्ट्रिंग a को स्ट्रिंग b के साथ जोड़ा गया.

काउंटर_बाइट की गिनती करना

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

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

वापस सबसे ऊपर जाएं

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

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

  1. क्रम से लगाना: प्रोटोकॉल बफ़र में बताए गए ExtraTagData ऑब्जेक्ट के इंस्टेंस को, सबसे पहले SerializeAsString() से बाइट कलेक्शन के ज़रिए क्रम से लगाया जाता है.

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

एन्क्रिप्ट (सुरक्षित) करने का pseudocode

byte_array = SerializeAsString(ExtraTagData 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 बाइट पास करता है

डिक्रिप्शन pseudocode

// split up according to length rules
(initialization_vector, ciphertext, integrity_signature) = final_message

// for each 20-byte section of ciphertext
pad = hmac(encryption_key, initialization_vector || counter_bytes)

// for each 20-byte section of ciphertext
byte_array = ciphertext <xor> pad

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');
    }
  }

विज्ञापन नेटवर्क प्रोटोकॉल बफ़र से डेटा हासिल करना

%%EXTRA_TAG_DATA%% में पास किए गए डेटा को डिकोड और डिक्रिप्ट करने के बाद, प्रोटोकॉल बफ़र को डीसीरियलाइज़ (पार्स) किया जा सकता है. साथ ही, टारगेटिंग के लिए, विज्ञापन देने वाले का आइडेंटिफ़ायर भी पाया जा सकता है.

अगर आप प्रोटोकॉल बफ़र के बारे में कुछ भी नहीं जानते, तो हमारे दस्तावेज़ देखें.

परिभाषा

हमारा विज्ञापन नेटवर्क प्रोटोकॉल बफ़र इस तरह से परिभाषित किया गया है:

message ExtraTagData {
  // advertising_id can be Apple's identifier for advertising (IDFA)
  // or Android's advertising identifier. When the advertising_id is an IDFA,
  // it is the plaintext returned by iOS's [ASIdentifierManager
  // advertisingIdentifier]. For hashed_idfa, the plaintext is the MD5 hash of
  // the IDFA.  Only one of the two fields will be available, depending on the
  // version of the SDK making the request.  Later SDKs provide unhashed values.
  optional bytes advertising_id = 1;
  optional bytes hashed_idfa = 2;
}

आपको C++ प्रोटोकॉल बफ़र दस्तावेज़ में बताए गए तरीके से ParseFromString() का इस्तेमाल करके, फ़ोन को डीसीरियलाइज़ (पार्स) करना होगा.

Android advertising_id और iOS hashed_idfa फ़ील्ड की जानकारी के लिए, डिक्रिप्ट विज्ञापन आईडी और IDFA की मदद से मोबाइल ऐप्लिकेशन इन्वेंट्री को टारगेट करना देखें.

Java लाइब्रेरी

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