ถอดรหัสสัญญาณการกําหนดเป้าหมายแบบเจาะจงพื้นที่

หากผู้เผยแพร่โฆษณาส่งข้อมูลตําแหน่งของอุปกรณ์เคลื่อนที่ไปยัง Authorized Buyers ซึ่งมีความเจาะจงมากกว่ารหัสไปรษณีย์ Authorized Buyers จะส่งเขตพื้นที่เสมือน ##39;hyperlocal' ไปยังผู้ซื้อในช่องที่เข้ารหัสใหม่: BidRequest.encrypted_hyperlocal_set

ไทม์ไลน์

  1. ผู้ใช้ติดตั้งแอปบนอุปกรณ์เคลื่อนที่ที่มีโฆษณาสนับสนุน และให้ความยินยอมแก่แอปในการเข้าถึงและแชร์ตําแหน่งของอุปกรณ์กับบุคคลที่สาม แอปนี้ยังผสานรวมกับ SDK โฆษณา Google และส่งตําแหน่งอุปกรณ์นี้ไปยัง 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;

สัญญาณการกําหนดเป้าหมายแบบเจาะจงพื้นที่แต่ละรายการประกอบด้วยรูปหลายเหลี่ยมอย่างน้อย 1 จุดและจุดศูนย์กลาง สําหรับแต่ละรูปหลายเหลี่ยม สัญญาณการกําหนดเป้าหมายแบบเจาะจงพื้นที่จะประกอบด้วยข้อมูลต่อไปนี้

  • ละติจูดและลองจิจูดของมุมแต่ละมุมของรูปหลายเหลี่ยมตามลําดับจะส่งผ่านช่อง 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 ไบต์ ciphertext ขนาด 20 ไบต์ที่เกี่ยวข้องจะสร้างแต่ละส่วนของ byte_array ต้นฉบับ ในรูปแบบต่อไปนี้

<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 ใช้ key เพื่อเข้ารหัส data
a || b สตริง a ที่ต่อด้วยสตริง b

คํานวณจํานวนตัวนับ

counter_bytes กํากับลําดับของส่วน 20 ไบต์แต่ละรายการของ ciphertext โปรดทราบว่าส่วนสุดท้ายอาจประกอบด้วยข้อมูลขนาด 1 ถึง 20 ไบต์ หากต้องการใส่ counter_bytes ด้วยค่าที่ถูกต้อง เมื่อเรียกใช้ฟังก์ชัน hmac() ให้นับส่วน 20 ไบต์ (รวมทั้งที่เหลือ) และใช้ตารางอ้างอิงต่อไปนี้

หมายเลขส่วน มูลค่า counter_bytes
0 ไม่มี
1 ... 256 1 ไบต์ ค่าจะเพิ่มขึ้นจาก 0 ถึง 255 ตามลําดับ
257 ... 512 2 ไบต์ ค่าไบต์แรกคือ 0 ค่าไบต์ที่ 2 เพิ่มขึ้นจาก 0 ถึง 255 ตามลําดับ
513 ... 768 3 ไบต์ ค่า 2 ไบต์แรกคือ 0 และค่าของไบต์สุดท้ายเพิ่มขึ้นจาก 0 เป็น 255 ตามลําดับ

เราไม่คาดหวังความยาวของ BidRequest.encrypted_hyperlocal_set ที่เกิน 1 กิโลไบต์ แม้แต่ในการขยายธุรกิจให้เติบโตยิ่งขึ้นไปอีก แต่ counter_bytes อาจมีความยาวเท่าที่จําเป็นเพื่อรองรับสัญญาณการกําหนดเป้าหมายแบบเจาะจงพื้นที่ที่มีระยะเวลาจํากัด

รูปแบบการเข้ารหัส

รูปแบบการเข้ารหัสสําหรับสัญญาณการกําหนดเป้าหมายแบบเจาะจงพื้นที่จะขึ้นอยู่กับแบบแผนเดียวกับที่ใช้สําหรับการถอดรหัสการยืนยันราคา

  1. Serialization: สัญญาณการกําหนดเป้าหมายแบบเจาะจงพื้นที่ซึ่งเป็นอินสแตนซ์ของออบเจ็กต์ HyperlocalSet ตามที่กําหนดไว้ในโปรโตคอล จะได้รับการจัดลําดับผ่าน SerializeAsString() ไปยังอาร์เรย์ไบต์ก่อน

  2. การเข้ารหัส: อาร์เรย์ไบต์จะได้รับการเข้ารหัสโดยใช้รูปแบบการเข้ารหัสที่กําหนดเองซึ่งออกแบบมาเพื่อลดขนาดค่าใช้จ่ายให้เหลือน้อยที่สุด พร้อมทั้งรักษาความปลอดภัยให้เพียงพอ สคีมการเข้ารหัสจะใช้อัลกอริทึม HMAC ที่มีคีย์ในการสร้างแพดข้อมูลลับโดยอิงตาม 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 ไบต์

การถอดรหัสแบบ Pseudocode

(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. ใช้ encryption_key และ integrity_key ต่อไปนี้เพื่อถอดรหัส 3 ช่องและยืนยันว่าคุณถอดรหัสอย่างถูกต้อง
    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

โปรดดูรายละเอียดการนําไปใช้งานใน "การตรวจหาการโจมตีในการตอบกลับที่ไม่มีการอัปเดต" ในบทความการถอดรหัสการยืนยันราคา

ไลบรารี Java

แทนที่จะใช้อัลกอริทึมคริปโตเพื่อเข้ารหัสและถอดรหัสสัญญาณการกําหนดเป้าหมายแบบเจาะจงพื้นที่ คุณสามารถใช้ DoubleClickCrypto.java ดูข้อมูลเพิ่มเติมได้ที่การเข้ารหัสลับ