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 ExtraTagData w 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 key do szyfrowania data . |
a || b |
ciąg a połączony z ciągiem znaków b . |
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.