Reti pubblicitarie che utilizzano
I tag JavaScript per riempire gli annunci tramite Authorized Buyers sono idonei a
ricevere identificatori dell'inserzionista per i dispositivi Android e iOS.
Le informazioni vengono inviate tramite il %%EXTRA_TAG_DATA%%
oppure
Macro %%ADVERTISING_IDENTIFIER%%
nel tag JavaScript gestito
da Authorized Buyers. Il resto di questa sezione si concentra sull'estrazione
%%EXTRA_TAG_DATA%%
ma vedi
Remarketing con IDFA o ID pubblicità per maggiori dettagli
sul buffer di protocollo criptato %%ADVERTISING_IDENTIFIER%%
MobileAdvertisingId
che possono essere decriptati analogamente.
Cronologia
- La rete pubblicitaria aggiorna i propri tag in-app JavaScript
tramite l'interfaccia utente di Authorized Buyers,
aggiungendo la macro
%%EXTRA_TAG_DATA%%
come spiegato di seguito. - Al momento della pubblicazione, l'app richiede un annuncio ad Authorized Buyers tramite la Google Mobile Ads SDK e trasmettere in modo sicuro l'identificatore dell'inserzionista.
- L'app riceve il tag JavaScript, con
%%EXTRA_TAG_DATA%%
compilata con il buffer di protocollo della rete pubblicitaria criptato contenente questo identificatore. - L'app esegue questo tag, effettuando una chiamata alla rete pubblicitaria per annuncio.
- Per utilizzare (monetizzare) queste informazioni, la rete pubblicitaria deve elaborare
il buffer di protocollo:
- Decodifica la stringa websafe di nuovo in una bytestring con WebSafeBase64.
- Decriptalo utilizzando lo schema descritto di seguito.
- Deserializza il protocollo e ottieni l'ID inserzionista da ExtraTagData.advertising_id o ExtraTagData.hashed_idfa.
Dipendenze
- Lo strumento WebSafeBase64 dell'architettura.
- Una libreria crittografica che supporta HMAC SHA-1, ad esempio Openssl.
- Il protocollo Google compilatore del buffer.
Decodifica la stringa websafe
Poiché le informazioni inviate tramite la macro %%EXTRA_TAG_DATA%%
Deve essere inviato tramite URL, i server di Google lo codificano con la tecnologia sicura per il web Base64 (RFC 3548).
Prima di tentare pertanto, è necessario decodificare i caratteri ASCII in un bytestring. Il codice C++ di esempio riportato di seguito si basa sul protocollo OpenSSL BIO_f_base64() del progetto e fa parte dell'esempio di Google il codice di decrittografia.
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); }
Struttura della stringa di byte criptata
Dopo aver decodificato i caratteri ASCII in una bytestring, sei pronto per decriptarlo. La bytestringa criptata contiene tre sezioni:
initialization_vector
: 16 byte.ciphertext
: serie di sezioni da 20 byte.integrity_signature
: 4 byte.
{initialization_vector (16 bytes)}{ciphertext (20-byte sections)}{integrity_signature (4 bytes)}
L'array di ciphertext
byte è diviso in multipli da 20 byte
specifiche, ad eccezione del fatto che l'ultima sezione può contenere tra
1 e 20 byte (inclusi). Per ogni sezione dell'originale
byte_array
, il valore corrispondente per ciphertext
da 20 byte
viene generato come segue:
<byte_array <xor> HMAC(encryption_key, initialization_vector || counter_bytes)>
dove ||
è una concatenazione.
Definizioni
Variabile | Dettagli |
---|---|
initialization_vector |
16 byte: univoci per l'impressione. |
encryption_key |
32 byte - forniti al momento della creazione dell'account. |
integrity_key |
32 byte - forniti al momento della creazione dell'account. |
byte_array |
Un oggetto ExtraTagData serializzato, in sezioni da 20 byte. |
counter_bytes |
Il valore del byte che mostra il numero ordinale della sezione, vedi di seguito. |
final_message |
Matrice di byte totali inviati tramite la macro %%EXTRA_TAG_DATA%% (meno la codifica WebSafeBase64). |
Operatori | Dettagli |
---|---|
hmac(key, data) |
HMAC SHA-1, utilizzando key per criptare data . |
a || b |
stringa a concatenata con la stringa b . |
Calcolare contatori_byte
counter_bytes
contrassegna l'ordine di ogni sezione da 20 byte della
ciphertext
. Tieni presente che l'ultima sezione può contenere tra 1 e 1
20 byte inclusi. Per inserire il valore corretto in counter_bytes
quando esegui la funzione hmac()
, conta le sezioni da 20 byte
(incluso il resto) e utilizza la seguente tabella di riferimento:
Numero sezione | Valore counter_bytes |
---|---|
0 | Nessuno |
1...256 | 1 byte. Il valore viene incrementato da 0 a 255 in sequenza. |
257...512 | 2 byte. Il valore del primo byte è 0, il valore del secondo byte incrementi da 0 a 255 in sequenza. |
513...768 | 3 byte. Il valore dei primi due byte è pari a 0, il valore dell'ultimo byte incrementi da 0 a 255 in sequenza. |
Schema di crittografia
Lo schema di crittografia si basa sullo stesso schema utilizzato per decriptare il indicatore di targeting iperlocale.
Serializzazione: un'istanza dell'oggetto ExtraTagData come definita nel buffer di protocollo viene prima serializzato
SerializeAsString()
a un array di byte.Crittografia: l'array di byte viene quindi criptato tramite una schema di crittografia personalizzato progettato per ridurre al minimo l'overhead delle dimensioni garantendo al contempo una sicurezza adeguata. Lo schema di crittografia utilizza un algoritmo HMAC con chiave per generare un secret pad basato su
initialization_vector
, che è l'esclusivo l'evento di impressione.
Pseudocodice di crittografia
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
Schema di decriptazione
Il codice di decriptazione deve 1) decriptare il buffer di protocollo utilizzando e 2) verificare i bit di integrità con la chiave di integrità. Le chiavi saranno forniti durante la creazione dell'account. Non sono previste limitazioni a strutturare la tua implementazione. Per la maggior parte, dovresti essere in grado di codice campione e adattarlo alle tue esigenze.
- Genera il tuo pad:
HMAC(encryption_key, initialization_vector || counter_bytes)
- XOR: prendi questo risultato e
<xor>
con testo crittografato per invertire la crittografia. - Verifica: la firma dell'integrità trasmette 4 byte di
HMAC(integrity_key, byte_array || initialization_vector)
Pseudocodice di decrittografia
// 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)
Codice C++ di esempio
Qui c'è una funzione chiave del nostro decrittografia esempio di codice.
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'); } }
Ottieni dati dal buffer di protocollo della rete pubblicitaria
Una volta decodificati e decriptati i dati trasmessi
%%EXTRA_TAG_DATA%%
, puoi deserializzare il buffer di protocollo
e ottieni l'identificatore dell'inserzionista
per il targeting.
Se non hai dimestichezza con i buffer di protocollo, consulta la nostra documentazione.
Definizione
Il nostro buffer di protocollo della rete pubblicitaria è definito come segue:
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; }
Dovrai deserializzarlo utilizzando ParseFromString()
come descritto in
Documentazione relativa al buffer di protocollo C++.
Per informazioni dettagliate sull'advertising_id
per Android e iOS
hashed_idfa
campi; consulta Decriptare
ID pubblicità e targeting per app mobile
inventario con IDFA.
Libreria Java
Anziché implementare gli algoritmi di crittografia per codificare e decodificare gli identificatori degli inserzionisti per le reti pubblicitarie, puoi usare DoubleClickCrypto.java. Per ulteriori informazioni, vedi Crittografia.