Descriptografar confirmações de preço

Quando o criativo vence um leilão, o Google pode informar qual é o vencedor era se o criativo incluísse a macro relevante.

Se o bidder estiver configurado para usar o protocolo OpenRTB, o criativo incluídos no seu lance devem usar os ${AUCTION_PRICE} .

Caso seu proponente use o protocolo descontinuado de RTB do Google, o criativo deverá usar o %%WINNING_PRICE%% do Google .

Quando essas macros são expandidas, elas retornam o preço vencedor em uma em formato criptografado. Eles podem ser incluídos em um criativo, por exemplo, com um solicitação de pixel invisível renderizada como parte do anúncio:

<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>

A macro ${AUCTION_PRICE} também pode ser incluída no URL VAST de um criativo em vídeo, mas não no URL de impressão no VAST:

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

Cenário

  1. Seu aplicativo de lances do OpenRTB inclui o ${AUCTION_PRICE} no snippet HTML ou no URL VAST que ela retorna para o Google.
  2. O Google substitui o preço vencedor pela macro em um campo seguro para a Web sem preenchimento codificação base64 (RFC 3548, link em inglês).
  3. O snippet passa a confirmação no formato escolhido. Para exemplo, a confirmação pode ser passada no URL de um pixel invisível solicitação processada como parte do anúncio.
  4. No servidor, o aplicativo base64 seguro para a Web decodifica o preço vencedor e descriptografa o resultado.

Dependências

Você vai precisar de uma biblioteca de criptografia compatível com SHA-1 HMAC, como Openssl.

Código de amostra

O exemplo de código é fornecido em Java e C++ e pode ser baixado do privatedatacommunicationprotocol projeto.

  • O exemplo de código em Java usa o decodificador base64 do Apache projeto commons. Não será necessário fazer o download do código Apache commons, já que a implementação de referência inclui a parte necessária e, portanto, autônomos.

  • O exemplo de código em C++ usa a OpenSSL método de BIO base64. Ele usa uma string codificada em base64 segura para a Web (RFC 3548) e a decodifica. Normalmente, strings base64 seguras para a Web substituem "=" preenchimento por "." (observe que aspas foram adicionadas para maior clareza de leitura e não estão incluídas no ), mas a substituição da macro não preenche o preço criptografado. O implementação de referência adiciona padding porque o OpenSSL tem problemas com strings sem preenchimento.

Codificação

Para ganhar a criptografia e a descriptografia de preço, é preciso ter dois secrets chaves. Uma chave de integridade e de criptografia, chamadas de i_key, e e_key, respectivamente. Ambas as chaves são fornecidas na configuração da conta como strings base64 seguras para a Web e podem ser encontradas na página do Authorized Buyers em Bidder configurações > Configurações de RTB > Chaves de criptografia.

Exemplos de chaves de integridade e criptografia:

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

As chaves devem ser decodificadas com segurança para a Web e, em seguida, decodificadas em base64 pelo seu aplicativo:

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

Esquema de criptografia

O preço é criptografado usando um esquema de criptografia personalizado projetado para minimizar a sobrecarga de tamanho e, ao mesmo tempo, garantir a segurança adequada. Esquema de criptografia usa um algoritmo HMAC de chave para gerar um bloco secreto com base no ID do evento de impressão.

O preço criptografado tem um comprimento fixo de 28 bytes. Ele é composto por vetor de inicialização de 16 bytes, 8 bytes de texto criptografado e integridade de 4 bytes assinatura. O preço criptografado é codificado em base64 seguro para a Web, de acordo com a RFC 3548, com caracteres de preenchimento omitidos. Assim, o preço criptografado de 28 bytes é codificado como uma string de base64 segura para a Web de 38 caracteres, independentemente do vencedor com o preço pago.

Exemplos de preços criptografados:

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

O formato criptografado é:

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

O preço está criptografado como <price xor HMAC(encryption_key, initialization_vector)>, então a descriptografia calcula HMAC(encryption_key,initialization_vector) e xor com o o preço criptografado para reverter a criptografia. O estágio de integridade usa 4 bytes de <HMAC(integrity_key, price||initialization_vector)> em que || é concatenação.

Entradas
iv vetor de inicialização (16 bytes - exclusivo da impressão)
e_key chave de criptografia (32 bytes - fornecida na configuração da conta)
i_key chave de integridade (32 bytes - fornecida na configuração da conta)
price (8 bytes - em micros da moeda da conta)
Notation
hmac(k, d) HMAC SHA-1 dos dados d, usando a chave k
a || b string a concatenada com a string 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 descriptografia

Seu código de descriptografia precisa descriptografar o preço usando a chave de criptografia. verificar os bits de integridade com a chave de integridade. As chaves serão fornecidas durante a configuração. Não há restrições quanto aos detalhes de como estruturar sua implementação. Na maioria das vezes, você deve ser capaz de o exemplo de código e adaptá-lo de acordo com suas necessidades.

Entradas
e_key chave de criptografia, 32 bytes - fornecida durante a configuração da conta
i_key chave de integridade, 32 bytes - fornecida na configuração da conta
final_message Codificação de 38 caracteres em base64 segura para a 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)

Detecte ataques de resposta desatualizada

Para detectar uma resposta desatualizada, ou repetição, ataques, é recomendado que você filtrar as respostas com um carimbo de data/hora que é muito diferente do usado no sistema momento, após considerar as diferenças de fuso horário.

O vetor de inicialização contém um carimbo de data/hora nos primeiros 8 bytes. Ela pode ser lida pela seguinte função 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)
}

O carimbo de data/hora pode ser convertido em um formato legível por humanos usando o seguinte 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 Java

Em vez de implementar os algoritmos de criptografia para codificar e decodificar o preço vencedor, você pode usar DoubleClickCrypto.java. Para mais informações, consulte Criptografia.