使用 的廣告聯播網
透過 Authorized Buyers 供應廣告的 JavaScript 代碼
接收 Android 和 iOS 裝置的廣告主 ID。
資訊是透過 %%EXTRA_TAG_DATA%%
或
受管理 JavaScript 代碼中的 %%ADVERTISING_IDENTIFIER%%
巨集
買方出價本節其餘部分著重於擷取
%%EXTRA_TAG_DATA%%
,但請參閱
使用廣告識別碼或廣告 ID 進行再行銷瞭解詳情
位於 %%ADVERTISING_IDENTIFIER%%
加密的 Proto 緩衝區
可類似解密的 MobileAdvertisingId
。
時間軸
- 廣告聯播網更新 JavaScript 應用程式內代碼
透過 Authorized Buyers UI
在
%%EXTRA_TAG_DATA%%
巨集中新增,如下所述。 - 放送時,應用程式會透過 Google Mobile Ads SDK 以安全的方式傳送廣告主 ID
- 應用程式收到 JavaScript 標記,並加上
%%EXTRA_TAG_DATA%%
巨集填入包含該 ID 的加密廣告聯播網通訊協定緩衝區。 - 應用程式執行這個廣告代碼,然後呼叫廣告聯播網以贏得廣告 廣告。
- 如要使用 (營利) 這類資訊,廣告聯播網必須
通訊協定緩衝區:
- 使用 WebSafeBase64 將網路安全字串解碼回位元組字串
- 請採用下列的配置進行解密。
- 將通訊協定反序列化,並從中取得廣告主 ID ExtraTagData.ads_id 或 ExtraTagData.hashed_idfa。
依附元件
- WebSafeBase64 編碼器。
- 支援 SHA-1 HMAC 的加密編譯程式庫,例如 Openssl。
- Google 通訊協定 緩衝區編譯器 -
將網路安全字串解碼
因為透過 %%EXTRA_TAG_DATA%%
巨集傳送的資訊
必須透過網址傳送,Google 伺服器則會以網路安全 Base64 編碼 (RFC 3548)。
嘗試前的準備 因此,您必須將 ASCII 字元解碼回 位元組字串。下列 C++ 程式碼範例是以 OpenSSL 為基礎 專案的 BIO_f_base64(),屬於 Google 樣本的一部分 解密程式碼) 即可。
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); }
加密位元組字串的結構
將 ASCII 字元解碼回位元組字串後,即可開始 才能解密。加密的位元組字串包含 3 個部分:
initialization_vector
:16 個位元組。ciphertext
:一系列 20 位元組區段。integrity_signature
:4 個位元組。
{initialization_vector (16 bytes)}{ciphertext (20-byte sections)}{integrity_signature (4 bytes)}
ciphertext
位元組陣列分為多個 20 位元組
但最後一部分可能包含
1 至 20 位元組 (含首尾)。對於原始的
byte_array
,對應的 20 位元組 ciphertext
產生為:
<byte_array <xor> HMAC(encryption_key, initialization_vector || counter_bytes)>
其中 ||
是串連的。
定義
變數 | 詳細資料 |
---|---|
initialization_vector |
16 個位元組 - 專屬於曝光。 |
encryption_key |
32 個位元組 - 在帳戶設定期間提供。 |
integrity_key |
32 個位元組 - 在帳戶設定期間提供。 |
byte_array |
序列化的 ExtraTagData 物件,位於 20 位元組區段中。 |
counter_bytes |
顯示該區段序數的位元組值,如下所示。 |
final_message |
透過 %%EXTRA_TAG_DATA%% 巨集傳送的位元組陣列總數 (減去 WebSafeBase64 編碼)。 |
運算子 | 詳細資料 |
---|---|
hmac(key, data) |
SHA-1 HMAC,使用 key 加密 data 。 |
a || b |
字串 a 與字串 b 串連。 |
計算計數器_位元組
counter_bytes
會標記
ciphertext
。請注意,最後一部分可能介於 1 到 1 之間
20 個位元組 (含首尾)。將正確值填入 counter_bytes
執行 hmac()
函式時,請計算 20 位元組的區段
並使用下表參照表:
單元編號 | counter_bytes 值 |
---|---|
0 分 | 無 |
1 ... 256 | 1 個位元組值會從 0 依序遞增至 255。 |
257 ... 512 | 2 個位元組。第一個位元組的值為 0,第二個位元組的值 值則從 0 到 255 |
513 ... 768 | 3 個位元組。前兩個位元組的值為 0,也就是最後一個位元組的值 值則從 0 到 255 |
加密配置
加密配置使用的配置與解密 超本地指定目標信號。
序列化:ExtraTagData 物件的例項 系統會透過 將
SerializeAsString()
轉換為位元組陣列。Encryption:接著,系統會使用 採用自訂加密機制,可將大小負擔降至最低,同時 且具備足夠的安全性加密配置會使用金鑰的 HMAC 演算法來產生 擁有專屬於
initialization_vector
的秘密鍵盤 定義曝光事件
加密虛擬程式碼
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
解密機制
您的解密程式碼必須 1) 使用加密機制將通訊協定緩衝區解密 金鑰,以及 2) 使用完整性金鑰驗證完整性位元。關鍵在於 我們在設定帳戶時提供給你。您的做法沒有任何限制 建構實作項目絕大部分的情況下,您應該能夠 再視需求修改程式碼
- 產生鍵盤:
HMAC(encryption_key, initialization_vector || counter_bytes)
- XOR:取得這筆結果和
<xor>
, 來反向加密。 - 驗證:完整性簽章傳遞 4 個位元組的
HMAC(integrity_key, byte_array || initialization_vector)
解密虛擬程式碼
// 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++ 程式碼範例
這裡所提的功能是 解密 範例程式碼
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'); } }
從廣告聯播網通訊協定緩衝區取得資料
您解碼並解密傳入的資料後
%%EXTRA_TAG_DATA%%
,您現在可以將通訊協定緩衝區還原序列化了
並取得廣告主 ID 以便指定目標
如果您對通訊協定緩衝區不熟悉,請參閱我們的說明文件。
定義
廣告聯播網通訊協定緩衝區的定義如下:
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; }
您需要使用 ParseFromString()
進行還原序列化,詳情請見
C++ 通訊協定緩衝區說明文件。
進一步瞭解 Android advertising_id
和 iOS
hashed_idfa
欄位,請參閱「解密
廣告 ID和指定行動應用程式
對應的廣告空間
Java 程式庫
比起實作加密演算法來編碼及解碼 廣告聯播網的廣告客戶 ID DoubleClickCrypto.java.若需更多資訊,請參閲 密碼學。