Mendekripsi Sinyal Penargetan Hiperlokal

Jika penayang meneruskan data lokasi seluler ke Authorized Buyers yang lebih spesifik daripada kode pos, Authorized Buyers akan mengirimkan 'hyperlocal'pembatasan wilayah kepada pembeli dalam kolom terenkripsi baru: BidRequest.encrypted_hyperlocal_set.

Linimasa

  1. Pengguna menginstal aplikasi seluler yang didukung iklan dan mengizinkan aplikasi mengakses dan membagikan lokasi perangkat kepada pihak ketiga. Aplikasi ini juga terintegrasi dengan Google Ads SDK dan mengirimkan lokasi perangkat ini ke Google.
  2. Server Google membuat sinyal penargetan hiperlokal khusus yang mewakili pembatasan wilayah di sekitar lokasi perangkat, seperti untuk melindungi privasi pengguna.
  3. Server Google melakukan serialisasi dan enkripsi sinyal penargetan hiperlokal menggunakan kunci keamanan khusus untuk setiap pembeli. Perhatikan bahwa bidder Anda bergantung pada kunci yang sama untuk mendekripsi makro WINNING_PRICE.
  4. Bidder mendekripsi dan membatalkan serialisasi sinyal penargetan hiperlokal ke dalam buffering protokol. Bidder Anda selanjutnya dapat menganalisis sinyal dan bid yang sesuai.

Dependensi

Anda memerlukan library kripto yang mendukung HMAC SHA-1, seperti Openssl.

Definisi

Sinyal penargetan hiperlokal didefinisikan dalam proto seperti ini:

// 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;

Setiap sinyal penargetan hiperlokal berisi satu atau beberapa poligon dan satu titik tengah. Untuk setiap poligon, sinyal penargetan hiperlokal berisi:

  • Lintang dan bujur setiap sudut poligon secara berurutan, diteruskan sebagai kolom corners berulang.
  • Perkiraan pusat geometris area pembatasan wilayah, yang diteruskan dalam kolom center_point opsional.

Struktur sinyal penargetan

Sinyal penargetan hiperlokal terenkripsi yang terdapat di BidRequest.encrypted_hyperlocal_set berisi 3 bagian:

  • initialization_vector: 16 byte.
  • ciphertext: rangkaian bagian 20 byte.
  • integrity_signature: 4 byte.
{initialization_vector (16 bytes)}{ciphertext (20-byte sections)}{integrity_signature (4 bytes)}

Array byte ciphertext dibagi menjadi beberapa bagian 20 byte, dengan pengecualian bahwa bagian terakhir dapat berisi antara 1 dan 20 byte inklusif. Untuk setiap bagian byte_array asli, ciphertext 20 byte yang sesuai dihasilkan sebagai:

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

Dengan || merupakan penyambungan.

Definisi

Variabel Detail
initialization_vector 16 byte - unik untuk tayangan.
encryption_key 32 byte - diberikan saat pembuatan akun.
integrity_key 32 byte - diberikan saat pembuatan akun.
byte_array Objek HyperlocalSet yang diserialisasi, dalam bagian 20 byte.
counter_bytes Nilai byte yang menunjukkan nomor ordinal bagian, lihat di bawah ini.
final_message Array byte yang dikirim melalui kolom BidRequest.encrypted_hyperlocal_set.
Operator Detail
hmac(key, data) HMAC SHA-1, menggunakan key untuk mengenkripsi data.
a || b string a disambungkan dengan string b.

Menghitung penghitung_byte

counter_bytes menandai urutan setiap bagian 20 byte dari ciphertext. Perhatikan bahwa bagian terakhir dapat berisi antara 1 dan 20 byte inklusif. Untuk mengisi counter_bytes dengan nilai yang benar saat menjalankan fungsi hmac(), hitung bagian 20 byte (termasuk sisanya) dan gunakan tabel referensi berikut:

Nomor bagian Nilai counter_bytes
0 None
1 ... 256 1 byte. Nilai ini meningkat dari 0 hingga 255 secara berurutan.
257 ... 512 2 byte. Nilai byte pertama adalah 0, nilai byte kedua meningkat dari 0 menjadi 255 secara berurutan.
513 ... 768 3 byte. Nilai dua byte pertama adalah 0, nilai byte terakhir bertambah dari 0 hingga 255 secara berurutan.

Kami tidak memperkirakan panjang BidRequest.encrypted_hyperlocal_set melebihi satu kilobyte, bahkan memperhitungkan pertumbuhan lebih lanjut. Meskipun demikian, counter_bytes dapat sepanjang diperlukan untuk mendukung sinyal penargetan hiperlokal dengan panjang arbitrer.

Skema enkripsi

Skema enkripsi untuk sinyal penargetan hiperlokal didasarkan pada skema yang sama dengan yang digunakan untuk mendekripsi konfirmasi harga.

  1. Serialisasi: Sinyal penargetan hiperlokal, yang merupakan instance objek HyperlocalSet seperti yang ditentukan dalam proto, pertama kali diserialisasi melalui SerializeAsString() ke array byte.

  2. Enkripsi: Array byte kemudian dienkripsi menggunakan skema enkripsi kustom yang dirancang untuk meminimalkan overhead ukuran sambil memastikan keamanan yang memadai. Skema enkripsi menggunakan algoritme HMAC yang dikunci untuk menghasilkan pad rahasia berdasarkan initialization_vector, yang unik untuk peristiwa tayangan.

Kode semu enkripsi

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

Skema dekripsi

Kode dekripsi Anda harus 1) mendekripsi sinyal penargetan hiperlokal menggunakan kunci enkripsi, dan 2) memverifikasi bit integritas dengan kunci integritas. Kunci akan diberikan kepada Anda selama penyiapan akun. Tidak ada pembatasan terhadap cara Anda membuat struktur penerapan. Pada umumnya, Anda harus dapat mengambil kode contoh dan menyesuaikannya dengan kebutuhan Anda.

  1. Buat bantalan: HMAC(encryption_key, initialization_vector || counter_bytes)
  2. XOR: Ambil hasil ini dan <xor> dengan ciphertext untuk membalikkan enkripsi.
  3. Verifikasi: Tanda tangan integritas meneruskan 4 byte dari HMAC(integrity_key, byte_array || initialization_vector)

Kode semu dekripsi

(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)

Contoh kode C++

Berikut adalah fungsi utama dari kode contoh dekripsi lengkap kami.

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

Contoh sinyal dan kunci hiperlokal

Untuk menguji dan memverifikasi kode Anda:

  1. Konversikan string yang berisi 308 karakter hex menjadi array 154 byte. Misalnya, dengan string berikut:
    E2014EA201246E6F6E636520736F7572636501414243C0ADF6B9B6AC17DA218FB50331EDB376701309CAAA01246E6F6E636520736F7572636501414243C09ED4ECF2DB7143A9341FDEFD125D96844E25C3C202466E6F6E636520736F7572636502414243517C16BAFADCFAB841DE3A8C617B2F20A1FB7F9EA3A3600256D68151C093C793B0116DB3D0B8BE9709304134EC9235A026844F276797
    
    konversikan menjadi array 154 byte sebagai berikut:
    const char serialized_result[154] = { 0xE2, 0x01, 0x4E, ... };
    
  2. Panggil metode BidRequest.ParsePartialFromString() untuk melakukan deserialisasi array 154 byte ke buffering protokol BidRequest.
    BidRequest bid_req;
    bid_req.ParsePartialFromString(serialzed_result);
    
  3. Pastikan bahwa BidRequest hanya memiliki 3 kolom:
    • encrypted_hyperlocal_set
      Dideklarasikan di dalam pesan BidReqeust.
    • encrypted_advertising_id
      Dideklarasikan di dalam pesan BidReqeust.Mobile.
    • encrypted_hashed_idfa
      Dideklarasikan di dalam pesan BidReqeust.Mobile.

    Contoh:

    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. Gunakan encryption_key dan integrity_key berikut untuk mendekripsi 3 kolom dan verifikasi bahwa Anda mendekripsinya dengan benar.
    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};
    

Mendeteksi serangan respons yang usang

Untuk mendeteksi serangan respons usang, sebaiknya filter respons dengan stempel waktu yang berbeda secara signifikan dari waktu sistem, setelah memperhitungkan perbedaan zona waktu. Server kami disetel ke waktu PST/PDT.

Untuk mengetahui detail implementasi, lihat “Mendeteksi Serangan Respons yang Basi” di artikel Mendekripsi Informasi Harga.

Library Java

Daripada menerapkan algoritme kripto untuk mengenkode dan mendekode sinyal penargetan hiperlokal, Anda dapat menggunakan DoubleClickCrypto.java. Untuk informasi selengkapnya, lihat Kriptografi.