Redes de publicidad que utilizan
Son aptas las etiquetas de JavaScript para rellenar anuncios mediante Authorized Buyers
Recibir identificadores de anunciante para dispositivos iOS y Android
La información se envía a través de %%EXTRA_TAG_DATA%%
.
Macro %%ADVERTISING_IDENTIFIER%%
en la etiqueta de JavaScript administrada
por Authorized Buyers. El resto de esta sección se centra en la extracción
%%EXTRA_TAG_DATA%%
pero ver
Remarketing con IDFA o ID de publicidad para obtener más detalles
en el búfer de proto encriptado %%ADVERTISING_IDENTIFIER%%
MobileAdvertisingId
que se puede desencriptar de forma análoga.
Cronograma
- La red de publicidad actualiza sus etiquetas de JavaScript en la aplicación
a través de la IU de Authorized Buyers
agregando la macro
%%EXTRA_TAG_DATA%%
como se explica a continuación. - En el momento de la publicación, la app solicita un anuncio a Authorized Buyers a través de la SDK de anuncios de Google para dispositivos móviles, mientras que y pasar de forma segura el identificador del anunciante.
- La app vuelve a recibir la etiqueta de JavaScript con el
%%EXTRA_TAG_DATA%%
. completa completa con el búfer de protocolo de red de publicidad encriptado que contiene ese identificador. - La app ejecuta esta etiqueta y llama a la red de publicidad para que el usuario gane. anuncio.
- Para usar (monetizar) esta información, la red de publicidad debe procesar
el búfer de protocolo:
- Decodifica la cadena websafe en una cadena de bytes con WebSafeBase64.
- Para desencriptarla, usa el esquema que se indica a continuación.
- Deserializa el proto y obtén el ID del anunciante de ExtraTagData.advertising_id o ExtraTagData.hashed_idfa.
Dependencias
- El WebSafeBase64 codificador-decodificador.
- Una biblioteca criptográfica compatible con HMAC de SHA-1, como Openssl.
- El protocolo de Google compilador de búfer.
Decodifica strings de seguridad para la Web
Debido a que la información enviada a través de la macro %%EXTRA_TAG_DATA%%
debe enviarse a través de una URL, los servidores de Google lo codifican con base64 segura para la Web (RFC 3548).
Antes de intentar desencriptación, debes volver a decodificar los caracteres ASCII en un de bytes. El siguiente código C++ de muestra se basa en la biblioteca OpenSSL BIO_f_base64() del proyecto y es parte de la muestra de Google de encriptación.
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); }
Estructura de una cadena de bytes encriptada
Una vez que hayas codificado los caracteres ASCII en una cadena de bytes, estarás listo para desencriptarlo. La cadena de bytes encriptada contiene 3 secciones:
initialization_vector
: 16 bytesciphertext
: serie de secciones de 20 bytesintegrity_signature
: 4 bytes.
{initialization_vector (16 bytes)}{ciphertext (20-byte sections)}{integrity_signature (4 bytes)}
El array de ciphertext
bytes se divide en múltiples de 20 bytes
secciones, con la excepción de que la última puede contener entre
de 1 a 20 bytes, ambos incluidos. Para cada sección del documento
byte_array
, el ciphertext
de 20 bytes correspondiente
se genera de la siguiente manera:
<byte_array <xor> HMAC(encryption_key, initialization_vector || counter_bytes)>
En el ejemplo anterior, ||
es la concatenación.
Definiciones
Variable | Detalles |
---|---|
initialization_vector |
16 bytes: únicos para la impresión |
encryption_key |
32 bytes, se proporciona en la configuración de la cuenta. |
integrity_key |
32 bytes, se proporciona en la configuración de la cuenta. |
byte_array |
Un objeto ExtraTagData serializado, en secciones de 20 bytes. |
counter_bytes |
Valor de bytes que muestra el número ordinal de la sección, consulta a continuación. |
final_message |
Total de array de bytes enviado a través de la macro %%EXTRA_TAG_DATA%% (menos la codificación WebSafeBase64). |
Operadores | Detalles |
---|---|
hmac(key, data) |
HMAC de SHA-1 que usa key para encriptar data . |
a || b |
la cadena a concatenada con la cadena b . |
Calcular count_bytes
counter_bytes
marca el orden de cada sección de 20 bytes de la
ciphertext
Ten en cuenta que la última sección puede contener entre 1 y
20 bytes inclusive. Para completar counter_bytes
con el valor correcto
Cuando ejecutes la función hmac()
, cuenta las secciones de 20 bytes
(incluido el resto) y utiliza la siguiente tabla de referencia:
Número de sección | Valor counter_bytes |
---|---|
0 | Ninguno |
1 ... 256 | 1 byte. El valor se incrementa de 0 a 255 de forma secuencial. |
257 ... 512 | 2 bytes. El valor del primer byte es 0, el valor del segundo byte aumenta de 0 a 255 en secuencia. |
513 ... 768 | 3 bytes. El valor de los dos primeros bytes es 0, el valor del último byte. aumenta de 0 a 255 en secuencia. |
Esquema de encriptación
El esquema de encriptación se basa en el mismo esquema utilizado para desencriptar la indicador de segmentación hiperlocal.
Serialización: una instancia del objeto ExtraTagData definidos en el búfer de protocolo se serializan primero
SerializeAsString()
a un array de bytes.Encriptación: Luego, el array de bytes se encripta con un de encriptación personalizado diseñado para minimizar la sobrecarga de tamaño, a la vez que garantiza con una seguridad adecuada. El esquema de encriptación usa un algoritmo HMAC con clave para generar un módulo secreto basado en el
initialization_vector
, que es exclusivo para el evento de impresión.
Pseudocódigo de encriptación
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
Esquema de desencriptación
Tu código de desencriptación 1) debe desencriptar el búfer de protocolo con la encriptación y 2) verificar los bits de integridad con la clave de integridad. Las claves serán que se te proporcionaron durante la configuración de la cuenta. No hay restricciones en la forma estructurar tu implementación. En su mayoría, deberías poder aprovechar y adáptalo a tus necesidades.
- Genera tu pad:
HMAC(encryption_key, initialization_vector || counter_bytes)
- XOR: Muestra este resultado y
<xor>
con el el texto cifrado para revertir la encriptación. - Verificar: La firma de integridad pasa 4 bytes de
HMAC(integrity_key, byte_array || initialization_vector)
Pseudocódigo de desencriptación
// 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)
Ejemplo de código de C++
Aquí se incluye una función clave de nuestra desencriptación código de ejemplo.
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'); } }
Cómo obtener datos del búfer de protocolo de la red de publicidad
Una vez que decodificaste y desencriptaste los datos que se pasaron
%%EXTRA_TAG_DATA%%
, está todo listo para deserializar el búfer de protocolo
y obtener el identificador de anunciante
para la segmentación.
Si no conoces los búferes de protocolo, comienza con nuestra documentación.
Definición
Nuestro búfer de protocolo de la red de publicidad se define de la siguiente manera:
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; }
Deberás deserializarlo con ParseFromString()
como se describe en
Documentación del búfer de protocolo C++.
Para obtener detalles sobre Android advertising_id
y iOS,
hashed_idfa
campos, consulta Desencriptar
ID de publicidad y Segmentación de aplicaciones para dispositivos móviles
inventario con IDFA.
Biblioteca de Java
En lugar de implementar algoritmos criptográficos para codificar y decodificar los identificadores de anunciantes para redes de publicidad, puedes usar DoubleClickCrypto.java. Para obtener más información, consulta Criptografía.