Mendekripsi ID Pengiklan untuk Jaringan Iklan

Jaringan Iklan yang menggunakan Tag JavaScript untuk mengisi iklan melalui Authorized Buyers memenuhi syarat untuk menerima ID pengiklan untuk perangkat Android dan iOS. Informasi dikirim melalui %%EXTRA_TAG_DATA%% atau Makro %%ADVERTISING_IDENTIFIER%% di tag JavaScript yang dikelola oleh Authorized Buyers. Selanjutnya, bagian ini berfokus pada ekstraksi %%EXTRA_TAG_DATA%% tetapi lihat Pemasaran ulang dengan IDFA atau ID Iklan untuk mengetahui detailnya di buffer proto terenkripsi %%ADVERTISING_IDENTIFIER%% MobileAdvertisingId yang dapat didekripsi.

Linimasa

  1. Jaringan Iklan memperbarui tag dalam aplikasi JavaScript melalui UI Authorized Buyers, menambahkan makro %%EXTRA_TAG_DATA%% seperti yang dijelaskan di bawah ini.
  2. Pada waktu penayangan, aplikasi akan meminta iklan dari Authorized Buyers melalui Google Mobile Ads SDK, sedangkan meneruskan ID pengiklan dengan aman.
  3. Aplikasi menerima kembali tag JavaScript, dengan %%EXTRA_TAG_DATA%% yang diisi dengan penyangga protokol Jaringan Iklan terenkripsi yang berisi ID tersebut.
  4. Aplikasi menjalankan tag ini dan melakukan panggilan ke Jaringan Iklan untuk iklan pemenang .
  5. Untuk menggunakan (memonetisasi) informasi ini, Jaringan Iklan harus memproses buffering protokol:
    1. Mendekode string websafe kembali menjadi bytestring dengan WebSafeBase64.
    2. Lakukan dekripsi menggunakan skema yang diuraikan di bawah ini.
    3. Lakukan deserialisasi proto dan dapatkan ID pengiklan dari ExtraTagData.advertising_id atau ExtraTagData.hashed_idfa.

Dependensi

  1. WebSafeBase64 encoder-decoder.
  2. Library kripto yang mendukung SHA-1 HMAC, seperti Openssl.
  3. Protokol Google compiler buffer.

Mendekode string websafe

Karena informasi dikirim melalui makro %%EXTRA_TAG_DATA%% harus dikirim melalui URL, server Google mengenkodenya dengan base64 yang aman bagi web (RFC 3548).

Sebelum mencoba dekripsi oleh karena itu, Anda harus mendekode karakter ASCII kembali ke {i>bytestring<i}. Contoh kode C++ di bawah ini didasarkan pada OpenSSL BIO_f_base64() project, dan merupakan bagian dari sampel Google kode dekripsi.

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<char*>(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);
}

Struktur bytestring terenkripsi

Setelah Anda mendekode kembali karakter ASCII ke dalam {i>bytestring<i}, Anda siap untuk mendekripsinya. Bytestring terenkripsi berisi 3 bagian:

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

Array byte ciphertext dibagi menjadi beberapa byte 20 byte dengan pengecualian bahwa bagian terakhir mungkin berisi antara 1 dan 20 byte inklusif. Untuk setiap bagian dokumen asli byte_array, 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 - disediakan saat pembuatan akun.
integrity_key 32 byte - disediakan saat pembuatan akun.
byte_array Objek ExtraTagData serial, dalam bagian 20 byte.
counter_bytes Nilai byte yang menunjukkan nomor ordinal bagian, lihat di bawah.
final_message Total array byte yang dikirim melalui makro %%EXTRA_TAG_DATA%% (tanpa encoding WebSafeBase64).
Operator Detail
hmac(key, data) SHA-1 HMAC, menggunakan key untuk mengenkripsi data.
a || b string a yang 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. 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 Tidak ada
1 ... 256 1 byte. Nilai bertambah dari 0 hingga 255 secara berurutan.
257 ... 512 2 byte. Nilai byte pertama adalah 0, nilai byte kedua peningkatan dari 0 hingga 255 secara berurutan.
513 ... 768 3 byte. Nilai dua byte pertama adalah 0, nilai byte terakhir peningkatan dari 0 hingga 255 secara berurutan.

Kembali ke atas

Skema enkripsi

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

  1. Serialisasi: Instance objek ExtraTagData sebagai yang ditentukan dalam buffering protokol pertama kali diserialisasi melalui SerializeAsString() ke array byte.

  2. Enkripsi: Array byte kemudian dienkripsi menggunakan skema enkripsi khusus yang dirancang untuk meminimalkan overhead ukuran sekaligus memastikan keamanan yang memadai. Skema enkripsi menggunakan algoritma HMAC berkunci untuk menghasilkan pad rahasia berdasarkan initialization_vector, yang bersifat unik untuk peristiwa tayangan.

Kode semu enkripsi

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

Skema dekripsi

Kode dekripsi Anda harus 1) mendekripsi buffering protokol menggunakan enkripsi kunci, dan 2) memverifikasi bit integritas dengan kunci integritas. Kunci tersebut akan menjadi yang diberikan kepada Anda selama pembuatan akun. Tidak ada batasan bagaimana Anda menyusun implementasi Anda. Secara keseluruhan, Anda harus dapat mengambil kode contoh dan menyesuaikannya sesuai kebutuhan Anda.

  1. Buat pad: HMAC(encryption_key, initialization_vector || counter_bytes)
  2. XOR: Ambil hasil ini dan <xor> dengan teks tersandi{i> <i}untuk membalikkan enkripsi.
  3. Verifikasi: Tanda tangan integritas melewati 4 byte HMAC(integrity_key, byte_array || initialization_vector)

Kode semu dekripsi

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

Contoh kode C++

Fungsi kunci dari {i>spreadsheet<i} dekripsi kode contoh Anda.

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

Dapatkan data dari buffering protokol Jaringan Iklan

Setelah Anda mendekode dan membongkar enkripsi data yang diteruskan %%EXTRA_TAG_DATA%%, Anda siap melakukan deserialisasi buffer protokol dan dapatkan ID pengiklan untuk penargetan.

Jika Anda tidak terbiasa dengan buffering protokol, mulai dengan dokumentasi kami.

Definisi

Buffering protokol Jaringan Iklan kami ditetapkan sebagai berikut:

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

Anda harus melakukan deserialisasi menggunakan ParseFromString() seperti yang dijelaskan dalam Dokumentasi buffering protokol C++.

Untuk mengetahui detail tentang Android advertising_id dan iOS hashed_idfa kolom, lihat Mendekripsi ID Iklan dan Menargetkan aplikasi seluler inventaris Anda dengan IDFA.

Library Java

Alih-alih menerapkan algoritma kripto untuk mengenkode dan mendekode ID Pengiklan untuk jaringan iklan, Anda dapat menggunakan DoubleClickCrypto.java. Untuk informasi selengkapnya, lihat Kriptografi.