Yerel Mesafe Hedefleme Sinyallerinin Şifresini Çöz

Yayıncılar mobil konum verilerini posta koduna göre daha ayrıntılı olan Authorized Buyers'a iletirse Authorized Buyers, şifrelenmiş yeni bir alanda alıcılara #&39;hyperlocal' coğrafi sınır bildirimi gönderir: BidRequest.encrypted_hyperlocal_set.

Zaman çizelgesi

  1. Kullanıcı reklam destekli bir mobil uygulama yükler ve uygulamanın cihaz konumuna erişip üçüncü taraflarla paylaşmasına izin verir. Bu uygulama ayrıca Google Ads SDK'sı ile entegre olup bu cihaz konumunu Google'a gönderir.
  2. Google sunucuları, kullanıcının gizliliğini korumak gibi, cihaz konumunun etrafındaki bir coğrafi çiti temsil eden özel bir hiper yerel hedefleme sinyali oluşturur.
  3. Google sunucuları, her alıcıya özel güvenlik anahtarını kullanarak hiper yerel hedefleme sinyalini serileştirir ve şifreler. Teklif vereninizin WINNING_PRICE makrosunun şifresini çözmek için aynı anahtarı kullandığını unutmayın.
  4. Teklif vereniniz, yerel mesafe hedefleme sinyalinin şifresini çözer ve bu protokolü bir protokol arabelleğine dönüştürür. Ardından, teklif vereniniz sinyali ve teklifi buna göre analiz edebilir.

Bağımlılıklar

Openssl gibi SHA-1 HMAC'yi destekleyen bir şifreleme kitaplığına ihtiyacınız olacaktır.

Tanım

Proto'da, aşağıdaki gibi bir yerel mesafe hedefleme sinyali tanımlanır:

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

Her bir yerel hedefleme sinyali, bir veya daha fazla poligon ve bir merkez noktası içerir. Her bir poligon için yerel çaplı hedefleme sinyali şunları içerir:

  • Poligona ait her köşenin enlem ve boylamı sırayla oluşturulur ve yinelenen bir corners alanı olarak aktarılır.
  • İsteğe bağlı center_point alanında iletilen coğrafi sınır çitinin yaklaşık geometrik merkezi.

Hedefleme sinyalinin yapısı

BidRequest.encrypted_hyperlocal_set içerisindeki şifrelenmiş yerel mesafe hedefleme sinyali 3 bölüm içerir:

  • initialization_vector: 16 bayt.
  • ciphertext: 20 baytlık bölümlerden oluşan dizi.
  • integrity_signature: 4 bayt.
{initialization_vector (16 bytes)}{ciphertext (20-byte sections)}{integrity_signature (4 bytes)}

ciphertext baytlık dizi, 20 baytlık birden fazla bölüme ayrılır. Bunun dışında, son bölümün 1 ila 20 bayt dahil olabilir. Orijinal byte_array öğesinin her bölümü için 20 baytlık ciphertext değeri şu şekilde oluşturulur:

<byte_array <xor> HMAC(encryption_key, initialization_vector || counter_bytes)>

|| birleştiriliyor.

Tanımlar

Değişken Ayrıntılar
initialization_vector 16 bayt - gösterime özel.
encryption_key 32 bayt - hesap kurulumu sırasında sağlanır.
integrity_key 32 bayt - hesap kurulumu sırasında sağlanır.
byte_array 20 baytlık bölümlerdeki serileştirilmiş HyperlocalSet nesnesi.
counter_bytes Bölümün sıra numarasını gösteren bayt değeri. Aşağıya bakın.
final_message BidRequest.encrypted_hyperlocal_set alanı üzerinden gönderilen bayt dizisi.
Operatörler Ayrıntılar
hmac(key, data) SHA-1 HMAC, key kullanılarak data şifreleniyor.
a || b a dizesi, b dizesiyle birleştirildi.

Sayaç_baytlarını hesapla

counter_bytes, ciphertext sütununun her 20 baytlık bölümünün sırasını belirtir. Son bölümün 1 ila 20 bayt dahil olabileceğini unutmayın. hmac() işlevinizi çalıştırırken counter_bytes öğesini doğru değerle doldurmak için 20 baytlık bölümleri (kalanlar dahil) sayın ve aşağıdaki referans tablosunu kullanın:

Bölüm numarası counter_bytes değer
0 Yok
1 ... 256 1 bayt. Değer, sırasıyla 0 ile 255 arasında artar.
257 ... 512 2 bayt. İlk baytın değeri 0'dır. İkinci baytın değeri de sırasıyla 0 ile 255 arasında artar.
513 ... 768 3 bayt. İlk iki baytın değeri 0'dır. Son baytın değeri de sırayla 0 ile 255 arasında artar.

Büyümenin daha da dikkate alınmasının BidRequest.encrypted_hyperlocal_set uzunluğunun bir kilobaytı aşmasını beklemiyoruz. Bununla birlikte, counter_bytes rastgele bir yerel hedefleme sinyalini desteklemek için gereken süre kadar uzun olabilir.

Şifreleme şeması

Yerel mesafe hedefleme sinyali için şifreleme şeması, fiyat onaylarının şifresini çözmek için kullanılan şemaya dayanır.

  1. Serileme: Proto'da tanımlandığı gibi HyperlocalSet nesnesinin bir örneği olan hiper yerel hedefleme sinyali, ilk olarak SerializeAsString() aracılığıyla bir bayt dizisine serileştirilir.

  2. Şifreleme: Bayt dizisi, yeterli güvenlik sağlarken boyutun ek yükünü en aza indirmek için tasarlanmış özel bir şifreleme şeması kullanılarak şifrelenir. Şifreleme şeması, initialization_vector etkinliğini temel alan ve gösterim etkinliğine özgü bir gizli pad oluşturmak için anahtarlı bir HMAC algoritması kullanır.

Şifreleme sözde kodu

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

Şifre çözme düzeni

Şifre çözme kodunuz 1) şifreleme anahtarını kullanarak yerel mesafe hedefleme sinyalinin şifresini çözmelidir ve 2) bütünlük bitlerini bütünlük anahtarıyla doğrulamalıdır. Anahtarlar, hesap kurulumu sırasında size sağlanır. Uygulamanızı nasıl yapılandıracağınız konusunda herhangi bir kısıtlama yoktur. Çoğu durumda, örnek kodu alıp ihtiyaçlarınıza göre uyarlayabilmeniz gerekir.

  1. pad'inizi oluşturun: HMAC(encryption_key, initialization_vector || counter_bytes)
  2. XOR: Bu sonucu alın ve şifrelemeyi tersine çevirmek için şifre metniyle <xor> ekleyin.
  3. Doğrulama: Bütünlük imzası, 4 baytlık HMAC(integrity_key, byte_array || initialization_vector) değerini iletir

Şifre çözme sözde kodu

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

Örnek C++ kodu

Burada, eksiksiz şifre çözme örnek kodumuzdan temel bir işlev verilmiştir.

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');
    }
  }
}

Örnek yerel mesafe sinyali ve anahtarları

Kodunuzu test etmek ve doğrulamak için:

  1. 308 on altılık karakter içeren bir dizeyi 154 baytlık bir diziye dönüştürün. Örneğin, aşağıdaki dizeyi dikkate alın:
    E2014EA201246E6F6E636520736F7572636501414243C0ADF6B9B6AC17DA218FB50331EDB376701309CAAA01246E6F6E636520736F7572636501414243C09ED4ECF2DB7143A9341FDEFD125D96844E25C3C202466E6F6E636520736F7572636502414243517C16BAFADCFAB841DE3A8C617B2F20A1FB7F9EA3A3600256D68151C093C793B0116DB3D0B8BE9709304134EC9235A026844F276797
    
    kodu aşağıdaki gibi 154 baytlık bir diziye dönüştürün:
    const char serialized_result[154] = { 0xE2, 0x01, 0x4E, ... };
    
  2. 154 baytlık diziyi bir BidRequest protokol arabelleğine serileştirmek için BidRequest.ParsePartialFromString() yöntemini çağırın.
    BidRequest bid_req;
    bid_req.ParsePartialFromString(serialzed_result);
    
  3. BidRequest alanında yalnızca 3 alan olduğunu doğrulayın:
    • encrypted_hyperlocal_set
      BidReqeust mesajında tanımlandı.
    • encrypted_advertising_id
      BidReqeust.Mobile mesajında tanımlandı.
    • encrypted_hashed_idfa
      BidReqeust.Mobile mesajında tanımlandı.

    Örneğin:

    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 }
    
  4. 3 alanın şifresini çözmek ve bunların şifresinin doğru şekilde çözüldüğünü doğrulamak için aşağıdaki encryption_key ve integrity_key öğelerini kullanın.
    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};
    

Eski yanıt saldırılarını tespit etme

Eski yanıt saldırılarının algılanması için, saat dilimi farklarını hesaba kattıktan sonra, yanıtları sistem saatinden önemli ölçüde farklı bir zaman damgasıyla filtrelemenizi öneririz. Sunucularımız PST/PDT saatine ayarlandı.

Uygulama ayrıntıları için Fiyat Onaylarının Şifresini Çözme başlıklı makaledeki "Eski İletilerin Saldırılarını Tespit Etme" bölümüne göz atın.

Java kitaplığı

Yerel mesafe hedefleme sinyallerini kodlamak ve kodlarını çözmek için kriptografik algoritmaları uygulamak yerine DoubleClickCrypto.java'yı kullanabilirsiniz. Daha fazla bilgi için Kriptografi bölümüne bakın.