Se os editores passarem dados de local para dispositivos móveis ao Authorized Buyers mais específicos que um código postal, o Authorized Buyers enviará uma fronteira geográfica virtual aos compradores em um novo campo criptografado: BidRequest.encrypted_hyperlocal_set
.
Cronograma
- Um usuário instala um app para dispositivos móveis com anúncios e permite que ele acesse e compartilhe o local do dispositivo com terceiros. Esse app também é integrado ao SDK do Google Ads e envia essa localização de dispositivo ao Google.
- Os servidores do Google geram um sinal de segmentação hiperlocal especial que representa uma fronteira geográfica virtual ao redor da localização do dispositivo, por exemplo, para proteger a privacidade do usuário.
- Os servidores do Google serializam e criptografam o sinal de segmentação hiperlocal usando a chave de segurança específica de cada comprador. O bidder usa a mesma chave para descriptografar a macro WINNING_PRICE.
- O bidder descriptografa e desserializa o sinal de segmentação hiperlocal em um buffer de protocolo. Em seguida, o bidder pode analisar o sinal e dar lances adequadamente.
Dependências
Você precisará de uma biblioteca de criptografia compatível com o SHA-1 HMAC, como Openssl.
Definição
Um sinal de segmentação hiperlocal é definido no protocolo da seguinte forma:
// A hyperlocal targeting location when available. // message Hyperlocal { // A location on the Earth's surface. // message Point { optional float latitude = 1; optional float longitude = 2; } // The mobile device can be at any point inside the geofence polygon defined // by a list of corners. Currently, the polygon is always a parallelogram // with 4 corners. repeated Point corners = 1; } message HyperlocalSet { // This field currently contains at most one hyperlocal polygon. repeated Hyperlocal hyperlocal = 1; // The approximate geometric center of the geofence area. It is calculated // exclusively based on the geometric shape of the geofence area and in no // way indicates the mobile device's actual location within the geofence // area. If multiple hyperlocal polygons are specified above then // center_point is the geometric center of all hyperlocal polygons. optional Hyperlocal.Point center_point = 2; } // Hyperlocal targeting signal when available, encrypted as described at // https://developers.google.com/authorized-buyers/rtb/response-guide/decrypt-hyperlocal optional bytes encrypted_hyperlocal_set = 40;
Cada indicador de segmentação por hiperlocal contém um ou mais polígonos e um ponto central. Para cada polígono, o sinal de segmentação por hiperlocal contém:
- A latitude e a longitude de cada canto do polígono em sequência, transmitidas como um campo
corners
repetido. - O centro geométrico aproximado da área de fronteira geográfica virtual, transmitido no
campo opcional
center_point
.
Estrutura do indicador de segmentação
O sinal de segmentação hiperlocal criptografado contido em
BidRequest.encrypted_hyperlocal_set
contém três seções:
initialization_vector
: 16 bytes.ciphertext
: série de seções de 20 bytes.integrity_signature
: 4 bytes.
{initialization_vector (16 bytes)}{ciphertext (20-byte sections)}{integrity_signature (4 bytes)}
A matriz de bytes ciphertext
é dividida em várias seções de 20 bytes, exceto que a última seção pode conter de 1 a 20 bytes inclusivos. Para cada seção do byte_array
original, o ciphertext
de 20 bytes correspondente é
gerado da seguinte forma:
<byte_array <xor> HMAC(encryption_key, initialization_vector || counter_bytes)>
Em que ||
é concatenação.
Definições
Variável | Detalhes |
---|---|
initialization_vector |
16 bytes - exclusivos à impressão. |
encryption_key |
32 bytes - fornecidos na configuração da conta. |
integrity_key |
32 bytes - fornecidos na configuração da conta. |
byte_array |
Um objeto HyperlocalSet serializado, em seções de 20 bytes. |
counter_bytes |
Valor de byte mostrando o número ordinal da seção, veja abaixo. |
final_message |
Matriz de bytes enviada pelo campo BidRequest.encrypted_hyperlocal_set . |
Operadores | Detalhes |
---|---|
hmac(key, data) |
HMAC SHA-1, usando key para criptografar data . |
a || b |
String a concatenada com a string b . |
Calcular contador_bytes
counter_bytes
marca a ordem de cada seção de 20 bytes da
ciphertext
. A última seção pode conter de 1 a
20 bytes. Para preencher counter_bytes
com o valor correto
ao executar a função hmac()
, conte as seções de 20 bytes
(incluindo o restante) e use a tabela de referência a seguir:
Número da seção | Valor counter_bytes |
---|---|
0 | Nenhum |
1 ... 256 | 1 byte O valor incrementa de 0 a 255 em sequência. |
257...512 | 2 bytes O valor do primeiro byte é 0. O valor do segundo byte incrementa de 0 a 255 em sequência. |
513... 768 | 3 bytes O valor dos dois primeiros bytes são 0, o valor do último byte incrementa de 0 a 255 em sequência. |
Não esperamos que o comprimento de
BidRequest.encrypted_hyperlocal_set
exceda um kilobyte, mesmo
considerando mais crescimento. No entanto,
counter_bytes
pode ter o tempo necessário para oferecer compatibilidade com um sinal de
segmentação hiperlocal de comprimento arbitrário.
Esquema de criptografia
O esquema de criptografia para sinais de segmentação hiperlocal é baseado no mesmo esquema usado para descriptografar confirmações de preços.
Serialização: o sinal de segmentação por hiperlocal, que é uma instância do objeto HyperlocalSet, conforme definido no proto, é primeiro serializado por
SerializeAsString()
para uma matriz de bytes.Criptografia: a matriz de bytes é criptografada usando um esquema de criptografia personalizado projetado para minimizar a sobrecarga de tamanho, garantindo a segurança adequada. O esquema de criptografia usa um algoritmo HMAC com chave para gerar um painel secreto com base no
initialization_vector
, que é exclusivo para o evento de impressão.
Pseudocódigo de criptografia
byte_array = SerializeAsString(HyperlocalSet 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 descriptografia
O código de descriptografia precisa 1) descriptografar o sinal de segmentação hiperlocal usando a chave de criptografia e 2) verificar os bits de integridade com a chave de integridade. As chaves serão fornecidas a você durante a configuração da conta. Não há restrições sobre como você estrutura sua implementação. Na maioria das vezes, você poderá adaptar o exemplo de código e adaptá-lo de acordo com suas necessidades.
- Gere seu bloco:
HMAC(encryption_key, initialization_vector || counter_bytes)
- XOR: veja este resultado e
<xor>
com o texto criptografado para inverter a criptografia. - Verificação: a assinatura da integridade transmite quatro bytes de
HMAC(integrity_key, byte_array || initialization_vector)
.
Pseudocódigo de descriptografia
(initialization_vector, ciphertext, integrity_signature) = final_message // split up according to length rules pad = hmac(encryption_key, initialization_vector || counter_bytes) // for each 20-byte section of ciphertext byte_array = ciphertext <xor> pad // for each 20-byte section of ciphertext confirmation_signature = hmac(integrity_key, byte_array || initialization_vector) success = (confirmation_signature == integrity_signature)
Exemplo de código em C++
Aqui está uma função-chave do nosso código de exemplo de descriptografia completo.
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'); } } }
Exemplo de chaves e sinais hiperlocais
Para testar e verificar seu código, faça o seguinte:
- Converta uma string contendo 308 caracteres hexadecimais em uma matriz de 154 bytes. Por exemplo, considerando a seguinte string:
E2014EA201246E6F6E636520736F7572636501414243C0ADF6B9B6AC17DA218FB50331EDB376701309CAAA01246E6F6E636520736F7572636501414243C09ED4ECF2DB7143A9341FDEFD125D96844E25C3C202466E6F6E636520736F7572636502414243517C16BAFADCFAB841DE3A8C617B2F20A1FB7F9EA3A3600256D68151C093C793B0116DB3D0B8BE9709304134EC9235A026844F276797
converta-o para uma matriz de 154 bytes da seguinte maneira:const char serialized_result[154] = { 0xE2, 0x01, 0x4E, ... };
- Chame o método
BidRequest.ParsePartialFromString()
para desserializar a matriz de 154 bytes em um buffer de protocoloBidRequest
.BidRequest bid_req; bid_req.ParsePartialFromString(serialzed_result);
- Verifique se o
BidRequest
tem apenas três campos:encrypted_hyperlocal_set
Declarado na mensagemBidReqeust
.encrypted_advertising_id
Declarado na mensagemBidReqeust.Mobile
.encrypted_hashed_idfa
Declarado na mensagemBidReqeust.Mobile
.
Exemplo:
encrypted_hyperlocal_set:( { 100, 100 }, { 200, -300 }, { -400, 500 }, { -600, -700 },) encrypted_advertising_id: { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11 } encrypted_hashed_idfa : { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0xF1 }
- Use os seguintes
encryption_key
eintegrity_key
para descriptografar os três campos e verificar se eles foram descriptografados corretamente.encryption_key = {0x02, 0xEE, 0xa8, 0x3c, 0x6c, 0x12, 0x11, 0xe1, 0x0b, 0x9f, 0x88, 0x96, 0x6c, 0xee, 0xc3, 0x49, 0x08, 0xeb, 0x94, 0x6f, 0x7e, 0xd6, 0xe4, 0x41, 0xaf, 0x42, 0xb3, 0xc0, 0xf3, 0x21, 0x81, 0x40}; integrity_key = {0xbf, 0xFF, 0xec, 0x55, 0xc3, 0x01, 0x30, 0xc1, 0xd8, 0xcd, 0x18, 0x62, 0xed, 0x2a, 0x4c, 0xd2, 0xc7, 0x6a, 0xc3, 0x3b, 0xc0, 0xc4, 0xce, 0x8a, 0x3d, 0x3b, 0xbd, 0x3a, 0xd5, 0x68, 0x77, 0x92};
Detectar ataques de resposta desatualizadas
Para detectar ataques de resposta desatualizados, recomendamos filtrar as respostas com um carimbo de data/hora que seja significativamente diferente do horário do sistema, depois de considerar as diferenças de fuso horário. Nossos servidores estão configurados para o horário PST/PDT.
Para detalhes sobre implementação, consulte "Como detectar ataques de resposta desatualizada" no artigo Descriptografia das confirmações de preço.
Biblioteca Java
Em vez de implementar os algoritmos de criptomoedas para codificar e decodificar os sinais de segmentação hiperlocal, você pode usar DoubleClickCrypto.java. Para mais informações, consulte Criptografia.