Desencriptar confirmaciones de precio

Cuando su creatividad gana una subasta, Google puede informarle cuál es el resultado si la creatividad incluye la macro relevante.

Si el ofertante está configurado para usar el protocolo OpenRTB, la creatividad incluidos con su oferta deben usar el ${AUCTION_PRICE} de IAB o la macro.

Si su ofertante usa el protocolo de RTB de Google obsoleto, la creatividad debe usa el %%WINNING_PRICE%% de Google o la macro.

Cuando estas macros se expanden, muestran el precio ganador en un formulario encriptado. Pueden incluirse en una creatividad, por ejemplo, con una solicitud de píxel invisible dibujada como parte del anuncio:

<div>
  <script language='JavaScript1.1' src='https://example.com?creativeID=5837243'/>
  <img src='https://example.com/t.gif?price=${AUCTION_PRICE}' width='1' height='1'/>
</div>

La macro ${AUCTION_PRICE} también se puede incluir en la URL de VAST de en una creatividad de video, pero no en la URL de impresión en la plantilla VAST:

https://example.com/vast/v?price=${AUCTION_PRICE}

Situación

  1. Tu aplicación de licitación de OpenRTB incluye ${AUCTION_PRICE} en el fragmento HTML o la URL de VAST que muestra a Google.
  2. Google sustituye el precio ganador por la macro en formato seguro para la Web sin rellenar codificación en Base64 (RFC 3548).
  3. El fragmento pasa la confirmación en el formato que elegiste. Para ejemplo, la confirmación podría pasarse en la URL de un píxel invisible solicitud renderizada como parte del anuncio.
  4. En el servidor, tu aplicación en Base64 seguro para la Web decodifica el precio ganador información y desencripta el resultado.

Dependencias

Necesitarás una biblioteca criptográfica que admita SHA-1 HMAC, como Openssl

Código de muestra

El código de muestra se proporciona en Java y C++, y se puede descargar desde el privatedatacomunprotocol. proyecto.

  • El código de muestra de Java utiliza el decodificador en base64 de la clase Apache Commons. No es necesario que descargues el código de Apache Commons, ya que la implementación de referencia incluye la pieza necesaria y, por lo tanto, está independientes.

  • El código de muestra de C++ usa la biblioteca OpenSSL método BIO en base64. Toma una string codificada en base64 segura para la Web (RFC 3548) y la decodifica. Por lo general, las cadenas base64 seguras para la Web reemplazan "=" relleno con “.” (ten en cuenta que se agregan comillas para mayor claridad de lectura y no se incluyen en el protocolo), pero la sustitución de macros no rellena el precio encriptado. El la implementación de referencia agrega padding, ya que OpenSSL tiene problemas sin rellenar.

Codificación

Para ganar la encriptación y desencriptación de precios, se necesitan dos secretos, pero se comparten. claves. Una clave de integridad y una clave de encriptación, denominada i_key, y e_key respectivamente. Ambas claves se proporcionan durante la configuración de la cuenta como cadenas base64 seguras para la Web, y se pueden encontrar en la página de Authorized Buyers en Ofertante Configuración > Configuración de RTB > Claves de encriptación.

Ejemplo de claves de integridad y encriptación:

skU7Ax_NL5pPAFyKdkfZjZz2-VhIN8bjj1rVFOaJ_5o=  // Encryption key (e_key)
arO23ykdNqUQ5LEoQ0FVmPkBd7xB5CO89PDZlSjpFxo=  // Integrity key (i_key)

Las claves se deben decodificar con seguridad para la Web y, luego, en Base64 por el aplicación:

e_key = WebSafeBase64Decode('skU7Ax_NL5pPAFyKdkfZjZz2-VhIN8bjj1rVFOaJ_5o=')
i_key = WebSafeBase64Decode('arO23ykdNqUQ5LEoQ0FVmPkBd7xB5CO89PDZlSjpFxo=')

Esquema de encriptación

El precio está encriptado con un esquema de encriptación personalizado y minimizar la sobrecarga de tamaño, a la vez que garantiza la seguridad adecuada. El esquema de encriptación usa un algoritmo HMAC con clave para generar un módulo secreto basado en la ID del evento de impresión.

El precio encriptado tiene una longitud fija de 28 bytes. Consta de un Vector de inicialización de 16 bytes, 8 bytes de texto cifrado y una integridad de 4 bytes firma. El precio encriptado está codificado en base64 seguro para la Web, según el RFC 3,548, con caracteres de padding omitidos. Por lo tanto, el precio encriptado por 28 bytes se codificada como una cadena de 38 caracteres en base 64 segura para la Web, independientemente del resultado Precio pagado.

Ejemplos de precios encriptados:

YWJjMTIzZGVmNDU2Z2hpN7fhCuPemCce_6msaw  // 100 CPI micros
YWJjMTIzZGVmNDU2Z2hpN7fhCuPemCAWJRxOgA  // 1900 CPI micros
YWJjMTIzZGVmNDU2Z2hpN7fhCuPemC32prpWWw  // 2700 CPI micros

El formato encriptado es el siguiente:

{initialization_vector (16 bytes)}{encrypted_price (8 bytes)}
{integrity (4 bytes)}

El precio está encriptado como <price xor HMAC(encryption_key, initialization_vector)>, por lo que la desencriptación calcula HMAC(encryption_key,initialization_vector) y xor con el precio encriptado para revertir la encriptación. La etapa de integridad toma 4 bytes de <HMAC(integrity_key, price||initialization_vector)> donde || es una concatenación.

Entradas
iv vector de inicialización (16 bytes, único para la impresión)
e_key clave de encriptación (32 bytes, proporcionada en la configuración de la cuenta)
i_key clave de integridad (32 bytes, proporcionada al configurar la cuenta)
price (8 bytes en micros de la moneda de la cuenta)
Notation
hmac(k, d) HMAC SHA-1 de datos d, con la clave k
a || b cadena a concatenada con la cadena b
Pseudocódigo
pad = hmac(e_key, iv)  // first 8 bytes
enc_price = pad <xor> price
signature = hmac(i_key, price || iv)  // first 4 bytes

final_message = WebSafeBase64Encode( iv || enc_price || signature )

Esquema de desencriptación

Tu código de desencriptación debe desencriptar el precio con la clave de encriptación. verificar los bits de integridad con la clave de integridad. Las claves se proporcionarán a durante la configuración. No hay restricciones en los detalles de cómo estructurar tu implementación. En su mayoría, deberías poder tomar el código de muestra y adáptalo según tus necesidades.

Entradas
e_key clave de encriptación de 32 bytes, proporcionada en la configuración de la cuenta
i_key clave de integridad, 32 bytes (proporcionada durante la configuración de la cuenta)
final_message 38 caracteres codificados en Base64 seguro para la Web
Pseudocódigo
// Base64 padding characters are omitted.
// Add any required base64 padding (= or ==).
final_message_valid_base64 = AddBase64Padding(final_message)

// Web-safe decode, then base64 decode.
enc_price = WebSafeBase64Decode(final_message_valid_base64)

// Message is decoded but remains encrypted.
(iv, p, sig) = enc_price // Split up according to fixed lengths.
price_pad = hmac(e_key, iv)
price = p <xor> price_pad

conf_sig = hmac(i_key, price || iv)
success = (conf_sig == sig)

Detecta ataques de respuesta inactivos

Para detectar ataques de respuesta inactiva o de repetición, te recomendamos filtrar respuestas con una marca de tiempo que difiere significativamente del sistema la fecha y hora, después de considerar las diferencias horarias.

El vector de inicialización contiene una marca de tiempo en los primeros 8 bytes. Puede ser leído con la siguiente función de C++:

void GetTime(const char* iv, struct timeval* tv) {
    uint32 val;
    memcpy(&val, iv, sizeof(val));
    tv->tv_sec = htonl(val);
    memcpy(&val, iv+sizeof(val), sizeof(val));
    tv->tv_usec = htonl(val)
}

La marca de tiempo se puede convertir en un formato legible por humanos de la siguiente manera: Código C++:

struct tm tm;
localtime_r(&tv->tv_sec, &tm);

printf("%04d-%02d-%02d|%02d:%02d:%02d.%06ld",
       tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
       tm.tm_hour, tm.tm_min, tm.tm_sec,
       tv_.tv_usec);

Biblioteca de Java

En lugar de implementar algoritmos criptográficos para codificar y decodificar el precio ganador, puedes usar DoubleClickCrypto.java. Para obtener más información, consulta Criptografía.