Entschlüsseln von Werbetreibenden-IDs für Werbenetzwerke

Werbenetzwerke mit JavaScript-Tags zum Füllen von Anzeigen über Authorized Buyers sind zulässig für Werbetreibende-IDs sowohl für Android- als auch für iOS-Geräte empfangen. Die Informationen werden über %%EXTRA_TAG_DATA%% oder %%ADVERTISING_IDENTIFIER%%-Makro im verwalteten JavaScript-Tag von Authorized Buyers. Im weiteren Verlauf dieses Abschnitts geht es um das Extrahieren %%EXTRA_TAG_DATA%% – sehen Sie sich <ph type="x-smartling-placeholder"></ph> Remarketing mit IDFA oder Werbe-ID. im verschlüsselten %%ADVERTISING_IDENTIFIER%%-Proto-Zwischenspeicher MobileAdvertisingId, das analog entschlüsselt werden kann.

Zeitachse

  1. Im Werbenetzwerk werden die JavaScript-In-App-Tags aktualisiert. über die Authorized Buyers-Benutzeroberfläche wie unten erläutert das %%EXTRA_TAG_DATA%%-Makro ein.
  2. Zum Zeitpunkt der Auslieferung fordert die App über das Google Mobile Ads SDK und die Werbetreibenden-ID sicher übergeben.
  3. Die App empfängt das JavaScript-Tag mit dem %%EXTRA_TAG_DATA%% -Makro in den verschlüsselten Werbenetzwerk-Protokollpuffer eingetragen, der diese ID enthält.
  4. Die App führt dieses Tag aus und sendet einen Aufruf an das Werbenetzwerk für den Gewinner. Anzeige.
  5. Um diese Informationen nutzen (monetarisieren) zu können, muss das Werbenetzwerk Protokollpuffer: <ph type="x-smartling-placeholder">
      </ph>
    1. Decodieren Sie den websicheren String mit WebSafeBase64 wieder in einen Bytestring.
    2. Entschlüsseln Sie sie nach dem unten beschriebenen Schema.
    3. Deserialisieren Sie das Protokoll und rufen Sie die Werbetreibenden-ID ab von ExtraTagData.advertising_id oder ExtraTagData.hashed_idfa.

Abhängigkeiten

  1. Die WebSafeBase64 Encoder hinzufügen.
  2. Eine Kryptobibliothek, die SHA-1 HMAC unterstützt, z. B. Openssl.
  3. Das Google-Protokoll Puffer-Compiler.

Websicheren String decodieren

Da die über das %%EXTRA_TAG_DATA%%-Makro gesendeten Informationen über URL gesendet werden muss, codieren die Google-Server sie mit websicherem Base64 (RFC 3548).

Bevor Sie versuchen, müssen Sie die ASCII-Zeichen daher wieder in ein bytestring an. Der folgende C++-Beispielcode basiert auf dem OpenSSL BIO_f_base64() des Projekts und ist Teil eines Beispiels von Google Entschlüsselungscode.

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

Struktur verschlüsselter Bytestrings

Nachdem Sie die ASCII-Zeichen wieder in einen Bytestring decodiert haben, können Sie um sie zu entschlüsseln. Der verschlüsselte Bytestring besteht aus drei Abschnitten:

  • initialization_vector: 16 Byte.
  • ciphertext: Reihe von 20-Byte-Abschnitten.
  • integrity_signature: 4 Byte.
{initialization_vector (16 bytes)}{ciphertext (20-byte sections)}{integrity_signature (4 bytes)}

Das Byte-Array ciphertext wird in mehrere 20-Byte- mit der Ausnahme, dass der letzte Abschnitt zwischen 1 und 20 Byte (einschließlich). Für jeden Abschnitt des Originals byte_array, die entsprechende 20-Byte-ciphertext wird generiert als:

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

wobei || die Verkettung ist.

Definitionen

Variable Details
initialization_vector 16 Byte – eindeutig für die Impression.
encryption_key 32 Byte – bei Kontoeinrichtung bereitgestellt
integrity_key 32 Byte – bei Kontoeinrichtung bereitgestellt
byte_array Ein serialisiertes ExtraTagData-Objekt in 20-Byte-Abschnitten.
counter_bytes Bytewert, der die Ordinalzahl des Abschnitts anzeigt, siehe unten.
final_message Gesamtes Byte-Array, das über das %%EXTRA_TAG_DATA%%-Makro gesendet wurde (minus WebSafeBase64-Codierung).
Operatoren Details
hmac(key, data) SHA-1 HMAC, mit key zum Verschlüsseln von data
a || b Der String a ist mit dem String b verkettet.

Counter_bytes berechnen

counter_bytes definiert die Reihenfolge der einzelnen 20-Byte-Abschnitte im ciphertext. Der letzte Abschnitt kann zwischen 1 und 20 Byte (einschließlich). Zum Füllen von counter_bytes mit dem richtigen Wert zählen Sie beim Ausführen der hmac()-Funktion die 20-Byte-Abschnitte (einschließlich der übrigen) und verwenden Sie die folgende Referenztabelle:

Abschnittsnummer counter_bytes Wert
0 Keine
1 ... 256 1 Byte. Der Wert wird sequenziell von 0 bis 255 erhöht.
257 ... 512 2 Byte. Der Wert des ersten Bytes ist 0, der Wert des zweiten Bytes. schrittweise von 0 auf 255 zu erhöhen.
513 ... 768 3 Byte. Der Wert der ersten beiden Byte ist 0, also der Wert des letzten Byte schrittweise von 0 auf 255 zu erhöhen.

Nach oben

Verschlüsselungsschema

Das Verschlüsselungsschema basiert auf demselben Schema, das auch für die Entschlüsselung des eines hyperlokalen Targeting-Signals.

  1. Serialisierung: Eine Instanz des ExtraTagData-Objekts als die im Protokollpuffer definiert sind, SerializeAsString() zu einem Byte-Array.

  2. Verschlüsselung: Das Byte-Array wird dann mit einem ein benutzerdefiniertes Verschlüsselungsschema, das den Größen-Overhead minimiert und gleichzeitig sicherstellt, angemessene Sicherheit zu gewährleisten. Das Verschlüsselungsschema verwendet einen verschlüsselten HMAC-Algorithmus, ein geheimes Pad basierend auf dem initialization_vector, das nur für das Impressionsereignis.

Verschlüsselungs-Pseudocode

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

Entschlüsselungsschema

Der Entschlüsselungscode muss 1) den Protokollzwischenspeicher mithilfe der Verschlüsselung entschlüsseln Schlüssel und 2) Überprüfen Sie die Integritätsbits mit dem Integritätsschlüssel. Die Schlüssel sind die Sie bei der Kontoeinrichtung erhalten haben. Es gibt keine Einschränkungen dafür, wie Sie Strukturierung Ihrer Implementierung. Sie sollten größtenteils in der Lage sein, Beispielcode erstellen und an Ihre Anforderungen anpassen.

  1. Pad generieren: HMAC(encryption_key, initialization_vector || counter_bytes)
  2. XOR: Dieses Ergebnis und <xor> mit dem Geheimtext umzukehren.
  3. Überprüfen: Die Integritätssignatur hat vier Byte HMAC(integrity_key, byte_array || initialization_vector)

Pseudocode zur Entschlüsselung

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

C++-Beispielcode

Hier ist eine Schlüsselfunktion aus der vollständigen Entschlüsselung Beispielcode.

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

Daten aus dem Protokollzwischenspeicher des Werbenetzwerks abrufen

Nachdem Sie die übergebenen Daten %%EXTRA_TAG_DATA%%, Sie können den Protokollzwischenspeicher deserialisieren. und die Werbetreibenden-ID für das Targeting abrufen.

Wenn Sie mit Protokollpuffern nicht vertraut sind, lesen Sie unsere Dokumentation.

Definition

Unser Werbenetzwerk-Protokollzwischenspeicher ist folgendermaßen definiert:

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

Sie müssen ihn mit ParseFromString() deserialisieren, wie in der Dokumentation zum C++-Protokollpuffer.

Weitere Informationen zu Android advertising_id und iOS hashed_idfa-Felder, siehe Entschlüsseln Werbe-ID und Ausrichtung auf mobile Apps Inventar mit IDFA

Java-Bibliothek

Anstatt Kryptoalgorithmen zum Codieren und Decodieren zu implementieren, die Werbetreibenden-IDs für Werbenetzwerke, können Sie <ph type="x-smartling-placeholder"></ph> DoubleClickCrypto.java. Weitere Informationen finden Sie unter Kryptografie: