হাইপারলোকাল টার্গেটিং সিগন্যাল ডিক্রিপ্ট করুন

যদি প্রকাশকরা মোবাইল অবস্থানের ডেটা অনুমোদিত ক্রেতাদের কাছে পাঠান যা পোস্টাল কোডের চেয়ে বেশি নির্দিষ্ট, অনুমোদিত ক্রেতারা একটি নতুন এনক্রিপ্ট করা ক্ষেত্রে ক্রেতাদের কাছে একটি 'হাইপারলোকাল' জিওফেন্স পাঠাবে: BidRequest.encrypted_hyperlocal_set

টাইমলাইন

  1. একজন ব্যবহারকারী একটি বিজ্ঞাপন-সমর্থিত মোবাইল অ্যাপ ইনস্টল করেন এবং তৃতীয় পক্ষের সাথে ডিভাইসের অবস্থান অ্যাক্সেস এবং শেয়ার করার অ্যাপে সম্মতি দেন। এই অ্যাপটি Google বিজ্ঞাপন SDK-এর সাথেও একত্রিত এবং Google-কে এই ডিভাইসের লোকেশন পাঠায়।
  2. Google সার্ভারগুলি একটি বিশেষ হাইপারলোকাল টার্গেটিং সিগন্যাল তৈরি করে যা ডিভাইসের অবস্থানের চারপাশে থাকা একটি জিওফেন্সকে প্রতিনিধিত্ব করে, যেমন ব্যবহারকারীর গোপনীয়তা রক্ষা করতে।
  3. Google সার্ভারগুলি প্রতিটি ক্রেতার জন্য নির্দিষ্ট নিরাপত্তা কী ব্যবহার করে হাইপারলোকাল টার্গেটিং সিগন্যালকে সিরিয়ালাইজ এবং এনক্রিপ্ট করে৷ মনে রাখবেন যে আপনার দরদাতা WINNING_PRICE ম্যাক্রো ডিক্রিপ্ট করতে একই কী-এর উপর নির্ভর করে।
  4. আপনার বিডার একটি প্রোটোকল বাফারে হাইপারলোকাল টার্গেটিং সিগন্যাল ডিক্রিপ্ট করে এবং ডি-সিরিয়ালাইজ করে। আপনার দরদাতা তারপর সংকেত বিশ্লেষণ করতে পারেন এবং সেই অনুযায়ী বিড করতে পারেন।

নির্ভরতা

আপনার একটি ক্রিপ্টো লাইব্রেরি প্রয়োজন যা SHA-1 HMAC সমর্থন করে, যেমন Openssl

সংজ্ঞা

একটি হাইপারলোকাল টার্গেটিং সিগন্যাল প্রোটোতে এভাবে সংজ্ঞায়িত করা হয়েছে:

// 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 এ থাকা এনক্রিপ্ট করা হাইপারলোকাল টার্গেটিং সিগন্যালে 3টি বিভাগ রয়েছে:

  • 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 একটি ক্রমিক HyperlocalSet অবজেক্ট, 20-বাইট বিভাগে।
counter_bytes বাইট মান বিভাগটির ক্রমিক সংখ্যা দেখাচ্ছে, নীচে দেখুন।
final_message BidRequest.encrypted_hyperlocal_set ফিল্ডের মাধ্যমে বাইট অ্যারে পাঠানো হয়েছে।
অপারেটর বিস্তারিত
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 পর্যন্ত বৃদ্ধি পায়।

আমরা আশা করি না যে BidRequest.encrypted_hyperlocal_set এর দৈর্ঘ্য এক কিলোবাইটের বেশি হবে, এমনকি আরও বৃদ্ধি বিবেচনায় নিয়ে। তবুও, counter_bytes যতটা দীর্ঘ হতে পারে যতটা প্রয়োজন নির্বিচারে দৈর্ঘ্যের হাইপারলোকাল টার্গেটিং সিগন্যালকে সমর্থন করার জন্য।

এনক্রিপশন স্কিম

হাইপারলোকাল টার্গেটিং সিগন্যালের জন্য এনক্রিপশন স্কিমটি মূল্য নিশ্চিতকরণ ডিক্রিপ্ট করার জন্য ব্যবহৃত একই স্কিমের উপর ভিত্তি করে।

  1. সিরিয়ালাইজেশন : হাইপারলোকাল টার্গেটিং সিগন্যাল, যা প্রোটোতে সংজ্ঞায়িত হাইপারলোকালসেট অবজেক্টের একটি উদাহরণ, প্রথমে SerializeAsString() এর মাধ্যমে একটি বাইট অ্যারেতে সিরিয়াল করা হয়।

  2. এনক্রিপশন : পর্যাপ্ত নিরাপত্তা নিশ্চিত করার সময় ওভারহেডের আকার ছোট করার জন্য ডিজাইন করা একটি কাস্টম এনক্রিপশন স্কিম ব্যবহার করে বাইট অ্যারে এনক্রিপ্ট করা হয়। এনক্রিপশন স্কিমটি initialization_vector উপর ভিত্তি করে একটি গোপন প্যাড তৈরি করতে একটি কীড HMAC অ্যালগরিদম ব্যবহার করে, যা ইমপ্রেশন ইভেন্টের জন্য অনন্য।

এনক্রিপশন সিউডোকোড

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. BidRequest.ParsePartialFromString() পদ্ধতিতে 154-বাইট অ্যারেকে একটি BidRequest প্রোটোকল বাফারে ডিসিরিয়ালাইজ করতে কল করুন।
    BidRequest bid_req;
    bid_req.ParsePartialFromString(serialzed_result);
    
  3. যাচাই করুন যে BidRequest এর শুধুমাত্র 3টি ক্ষেত্র রয়েছে:
    • 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. 3টি ক্ষেত্র ডিক্রিপ্ট করতে এবং আপনি সঠিকভাবে ডিক্রিপ্ট করেছেন কিনা তা যাচাই করতে নিম্নলিখিত 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};
    

বাসি প্রতিক্রিয়া আক্রমণ সনাক্ত করুন

পুরানো প্রতিক্রিয়া আক্রমণ সনাক্ত করতে, আমরা টাইমস্ট্যাম্প সহ প্রতিক্রিয়াগুলি ফিল্টার করার সুপারিশ করেছি যা টাইমজোন পার্থক্যগুলির জন্য অ্যাকাউন্টিংয়ের পরে সিস্টেমের সময়ের থেকে উল্লেখযোগ্যভাবে আলাদা। আমাদের সার্ভারগুলি PST/PDT সময় সেট করা আছে।

বাস্তবায়নের বিশদ বিবরণের জন্য, ডিক্রিপ্টিং প্রাইস কনফার্মেশন নিবন্ধে "স্টেল রেসপন্স অ্যাটাক সনাক্ত করা" দেখুন।

জাভা লাইব্রেরি

হাইপারলোকাল টার্গেটিং সিগন্যাল এনকোড এবং ডিকোড করার জন্য ক্রিপ্টো অ্যালগরিদম প্রয়োগ করার পরিবর্তে, আপনি DoubleClickCrypto.java ব্যবহার করতে পারেন। আরও তথ্যের জন্য, ক্রিপ্টোগ্রাফি দেখুন।