Sieci reklamowe korzystające z 
Tagi JavaScript służące do wypełniania reklam przez Authorized Buyers mogą:
otrzymywać identyfikatory reklamodawców
na urządzeniach z Androidem i iOS.
Informacje są wysyłane przez %%EXTRA_TAG_DATA%% lub
Makro %%ADVERTISING_IDENTIFIER%% w zarządzanym tagu JavaScript
przez Authorized Buyers. Pozostała część tej sekcji dotyczy wyodrębniania
%%EXTRA_TAG_DATA%%, ale zobacz
Remarketing z wykorzystaniem identyfikatora IDFA lub identyfikatora wyświetlania reklam
w zaszyfrowanym buforze protokołu %%ADVERTISING_IDENTIFIER%%
MobileAdvertisingId, które można odszyfrować analogicznie.
Oś czasu
- Sieć reklamowa aktualizuje swoje tagi JavaScript w aplikacji
za pomocą interfejsu Authorized Buyers,
w makrze %%EXTRA_TAG_DATA%%w sposób opisany poniżej.
- W momencie wyświetlenia aplikacja wysyła żądanie reklamy od Authorized Buyers za pomocą pakietu SDK do reklam mobilnych Google, bezpiecznie przekazując identyfikator reklamodawcy.
- Aplikacja odbiera z powrotem tag JavaScript, z parametrem %%EXTRA_TAG_DATA%%wypełnione zaszyfrowanym buforem protokołów sieci reklamowej, który zawiera ten identyfikator.
- Aplikacja uruchamia ten tag, wysyłając wywołanie do zwycięskiej sieci reklamowej. reklama.
- Aby korzystać z tych informacji (zarabiać na nich), sieć reklamowa musi przetworzyć
bufor protokołu:
    - Zdekoduj ciąg znaków bezpiecznego w internecie z powrotem do ciągu bajtów za pomocą WebSafeBase64.
- Odszyfruj go zgodnie ze schematem opisanym poniżej.
- Deserializuj protokół i uzyskaj identyfikator reklamodawcy z ExtraTagData.advertising_id lub ExtraTagData.hashed_idfa.
 
Zależności
- WebSafeBase64 .
- Biblioteka kryptograficzna obsługująca protokół SHA-1 HMAC, na przykład Openssl.
- Protokół Google kompilatora bufora.
Dekodowanie ciągu znaków bezpiecznego w internecie
Ponieważ informacje wysyłane przez makro %%EXTRA_TAG_DATA%%
musi być przesyłany za pośrednictwem adresu URL, a serwery Google kodują go za pomocą protokołu base64 przeznaczonego do bezpiecznego przesyłania w internecie (RFC 3548).
Przed podjęciem próby w takim przypadku należy zdekodować znaki ASCII z powrotem ciąg bajtów. Poniższy przykładowy kod w C++ jest oparty na interfejsie OpenSSL Funkcja BIO_f_base64() projektu i jest częścią przykładu Google do odszyfrowywania.
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); }
Struktura zaszyfrowanego ciągu bajtów
Po odkodowaniu znaków ASCII z powrotem na ciąg bajtowy możesz w celu jego odszyfrowania. Zaszyfrowany ciąg bajtów składa się z 3 sekcji:
- initialization_vector: 16 bajtów.
- ciphertext: seria sekcji 20-bajtowych.
- integrity_signature: 4 bajty.
{initialization_vector (16 bytes)}{ciphertext (20-byte sections)}{integrity_signature (4 bytes)}Tablica bajtów ciphertext jest dzielona na kilka 20-bajtowych
z wyjątkiem tego, że ostatnia sekcja może zawierać
1–20 bajtów włącznie. Dla każdej sekcji oryginału
byte_array, odpowiednie 20-bajtowe ciphertext
jest generowany jako:
<byte_array <xor> HMAC(encryption_key, initialization_vector || counter_bytes)>
gdzie || to konkatenacja.
Definicje
| Zmienna | Szczegóły | 
|---|---|
| initialization_vector | 16 bajtów – unikalne dla wyświetlenia. | 
| encryption_key | 32 bajty – podane podczas zakładania konta. | 
| integrity_key | 32 bajty – podane podczas zakładania konta. | 
| byte_array | Zserializowany obiekt ExtraTagDataw 20-bajtowych sekcjach. | 
| counter_bytes | Wartość w bajtach wskazujący liczbę porządkową sekcji, patrz poniżej. | 
| final_message | Łączna tablica bajtów wysłana za pomocą makra %%EXTRA_TAG_DATA%%(minus kodowanie WebSafeBase64). | 
| Operatory | Szczegóły | 
|---|---|
| hmac(key, data) | Szyfrowanie HMAC SHA-1 z użyciem keydo szyfrowaniadata. | 
| a || b | ciąg apołączony z ciągiem znakówb. | 
Oblicz liczniki_bajtów
counter_bytes oznacza kolejność każdej 20-bajtowej sekcji
ciphertext Uwaga: ostatnia sekcja może zawierać od 1 do
20 bajtów (włącznie). Aby wypełnić pole counter_bytes prawidłową wartością
przy uruchamianiu funkcji hmac() policz sekcje 20-bajtowe
(łącznie z pozostałymi częściami) i skorzystaj z poniższej tabeli:
| Numer sekcji | Wartość: counter_bytes | 
|---|---|
| 0 | Brak | 
| 1 ... 256 | 1 bajt. Wartość zwiększa się sekwencyjnie od 0 do 255. | 
| 257 ... 512 | 2 bajty. Wartość pierwszego bajtu wynosi 0, wartość drugiego bajtu zwiększa się kolejno od 0 do 255. | 
| 513 ... 768 | 3 bajty. Wartość pierwszych 2 bajtów wynosi 0 – wartość ostatniego bajtu zwiększa się kolejno od 0 do 255. | 
Schemat szyfrowania
Schemat szyfrowania jest oparty na tym samym schemacie, który jest używany do odszyfrowywania sygnał kierowania hiperlokalnego.
- Serialization – wystąpienie obiektu ExtraTagData jako zdefiniowane w buforze protokołu są najpierw serializowane przez - SerializeAsString()do tablicy bajtów.
- Szyfrowanie: tablica bajtów jest następnie szyfrowana przy użyciu niestandardowy schemat szyfrowania zaprojektowany z myślą o zminimalizowaniu rozmiaru, przy jednoczesnym zapewnieniu odpowiednie zabezpieczenia. Schemat szyfrowania wykorzystuje algorytm HMAC z kluczem do generowania tajną funkcję wykorzystującą - initialization_vector, która jest unikalna dla zdarzenie wyświetlenia.
Pseudokod szyfrowania
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
Schemat odszyfrowywania
Twój kod odszyfrowywania musi: 1) odszyfrować bufor protokołu przy użyciu szyfrowania i 2) zweryfikować bity za pomocą tego klucza. Klucze będą podane podczas zakładania konta. Nie ma żadnych ograniczeń strukturę implementacji. Powinieneś być w stanie wykonać przykładowy kod i dostosuj go do swoich potrzeb.
- Wygeneruj pad: HMAC(encryption_key, initialization_vector || counter_bytes)
- XOR: użyj tego wyniku i <xor>za pomocą funkcji tekst szyfrowany w celu odwrócenia szyfrowania.
- Weryfikacja: podpis integralności przekazuje 4 bajty
HMAC(integrity_key, byte_array || initialization_vector)
Pseudokod odszyfrowywania
// 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)
Przykładowy kod w C++
Oto kluczowa funkcja z pełnego odszyfrowywanie przykładowy kod.
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');
    }
  }
Pobierz dane z bufora protokołów sieci reklamowej
Po zdekodowaniu i odszyfrowaniu danych przekazanych
%%EXTRA_TAG_DATA%%, możesz przeprowadzić deserializację bufora protokołu
i uzyskać identyfikator reklamodawcy na potrzeby kierowania.
Jeśli nie wiesz, czym są bufory protokołów, zapoznaj się z naszą dokumentacją.
Definicja
Bufor protokołu sieci reklamowej jest zdefiniowany tak:
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;
}Musisz poddać deserializację za pomocą parametru ParseFromString(), jak opisano w
Dokumentacja bufora protokołu C++.
Więcej informacji na temat Androida advertising_id i iOS
Pola: hashed_idfa – patrz Odszyfrowywanie
Identyfikator wyświetlania reklam i Kierowanie na aplikacje mobilne
zasobów reklamowych z identyfikatorem IDFA.
Biblioteka Java
Zamiast implementować algorytmy kryptograficzne do kodowania i dekodowania identyfikatorów reklamodawców dla sieci reklamowych, DoubleClickCrypto.java. Więcej informacji: Kryptografia.