Mạng quảng cáo sử dụng
Các thẻ JavaScript để điền quảng cáo thông qua Authorized Buyers đủ điều kiện để
nhận giá trị nhận dạng nhà quảng cáo cho cả thiết bị Android và iOS.
Thông tin được gửi qua %%EXTRA_TAG_DATA%%
hoặc
Macro %%ADVERTISING_IDENTIFIER%%
trong thẻ JavaScript được quản lý
của Authorized Buyers. Phần còn lại của phần này tập trung vào việc trích xuất
%%EXTRA_TAG_DATA%%
nhưng hãy xem
Tái tiếp thị bằng IDFA hoặc Mã nhận dạng cho quảng cáo để biết thông tin chi tiết
trên vùng đệm proto đã mã hoá %%ADVERTISING_IDENTIFIER%%
MobileAdvertisingId
có thể được giải mã theo cách tương tự.
Dòng thời gian
- Mạng quảng cáo cập nhật các thẻ trong ứng dụng JavaScript
thông qua giao diện người dùng Authorized Buyers,
thêm vào macro
%%EXTRA_TAG_DATA%%
như được giải thích bên dưới. - Tại thời điểm phân phát, ứng dụng yêu cầu một quảng cáo từ Authorized Buyers thông qua SDK Quảng cáo của Google trên thiết bị di động, trong khi chuyển mã nhận dạng nhà quảng cáo một cách an toàn.
- Ứng dụng sẽ nhận lại thẻ JavaScript cùng với
%%EXTRA_TAG_DATA%%
được điền bằng vùng đệm giao thức Mạng quảng cáo đã mã hoá có chứa giá trị nhận dạng đó. - Ứng dụng chạy thẻ này, thực hiện lệnh gọi đến Mạng quảng cáo để giành chiến thắng quảng cáo.
- Để sử dụng (kiếm tiền) thông tin này, Mạng quảng cáo phải xử lý
vùng đệm giao thức:
- Giải mã chuỗi websafe trở lại thành một bytestring bằng WebSafeBase64.
- Hãy giải mã mã bằng giao thức nêu dưới đây.
- Giải tuần tự proto và lấy mã nhận dạng nhà quảng cáo từ ExtraTagData.advertising_id hoặc ExtraTagData.hashed_idfa.
Phần phụ thuộc
- Công cụ WebSafeBase64 bộ mã hoá.
- Một thư viện mật mã hỗ trợ HMAC SHA-1, chẳng hạn như Openssl.
- Giao thức Google trình biên dịch vùng đệm.
Giải mã chuỗi websafe
Do thông tin được gửi qua macro %%EXTRA_TAG_DATA%%
phải được gửi thông qua URL, còn máy chủ của Google mã hoá URL bằng base64 an toàn cho web (RFC 3548).
Trước khi thử do đó, bạn phải giải mã các ký tự ASCII trở lại thành chuỗi byte. Mã C++ mẫu bên dưới dựa trên giao diện OpenSSL BIO_f_base64() của dự án và là một phần trong mẫu của Google mã giải mã.
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); }
Cấu trúc của chuỗi byte đã mã hoá
Sau khi giải mã xong các ký tự ASCII trở lại thành chuỗi byte, bạn đã sẵn sàng để giải mã email đó. Chuỗi byte đã mã hoá chứa 3 phần:
initialization_vector
: 16 byte.ciphertext
: chuỗi gồm các phần có kích thước 20 byte.integrity_signature
: 4 byte.
{initialization_vector (16 bytes)}{ciphertext (20-byte sections)}{integrity_signature (4 bytes)}
Mảng ciphertext
được chia thành nhiều 20 byte
ngoại trừ phần cuối cùng có thể có giữa
1 và 20 byte. Đối với mỗi phần của nội dung gốc
byte_array
, ciphertext
20 byte tương ứng
được tạo là:
<byte_array <xor> HMAC(encryption_key, initialization_vector || counter_bytes)>
trong đó ||
là phép nối.
Định nghĩa
Biến | Thông tin chi tiết |
---|---|
initialization_vector |
16 byte – duy nhất cho hiển thị. |
encryption_key |
32 byte – được cung cấp khi thiết lập tài khoản. |
integrity_key |
32 byte – được cung cấp khi thiết lập tài khoản. |
byte_array |
Đối tượng ExtraTagData được chuyển đổi tuần tự trong các phần có kích thước 20 byte. |
counter_bytes |
Giá trị byte cho biết số thứ tự của phần này, hãy xem bên dưới. |
final_message |
Mảng byte được gửi qua macro %%EXTRA_TAG_DATA%% (trừ đi phương thức mã hoá WebSafeBase64). |
Toán tử | Thông tin chi tiết |
---|---|
hmac(key, data) |
HMAC SHA-1, sử dụng key để mã hoá data . |
a || b |
chuỗi a nối với chuỗi b . |
Tính byte bộ đếm
counter_bytes
đánh dấu thứ tự của từng phần 20 byte của
ciphertext
Lưu ý rằng phần cuối cùng có thể chứa từ 1 đến
20 byte. Để điền giá trị chính xác vào counter_bytes
khi chạy hàm hmac()
, hãy đếm các phần có kích thước 20 byte
(bao gồm phần còn lại) và sử dụng bảng tham chiếu sau:
Số mục | Giá trị counter_bytes |
---|---|
0 | Không có |
1 ... 256 | 1 byte. Giá trị tăng dần từ 0 đến 255. |
257 ... 512 | 2 byte. Giá trị của byte đầu tiên là 0, giá trị của byte thứ hai tăng theo tuần tự từ 0 đến 255. |
513 ... 768 | 3 byte. Giá trị của hai byte đầu tiên là 0, giá trị của byte cuối cùng tăng theo tuần tự từ 0 đến 255. |
Giao thức mã hoá
Lược đồ mã hóa này dựa trên chính lược đồ dùng để giải mã tín hiệu nhắm mục tiêu siêu địa phương.
Chuyển đổi tuần tự: Một thực thể của đối tượng ExtraTagData dưới dạng được xác định trong vùng đệm giao thức được chuyển đổi tuần tự lần đầu tiên qua
SerializeAsString()
thành một mảng byte.Mã hoá: Sau đó, mảng byte được mã hoá bằng được thiết kế để giảm thiểu hao tổn kích thước trong khi vẫn đảm bảo có mức bảo mật vừa đủ. Giao thức mã hoá sử dụng thuật toán HMAC có khoá để tạo một khoá bí mật dựa trên
initialization_vector
(chỉ dành cho sự kiện hiển thị.
Mã giả mã hoá
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
Giao thức giải mã
Mã giải mã của bạn phải 1) giải mã vùng đệm giao thức bằng cách sử dụng mã và 2) xác minh bit tính toàn vẹn bằng khoá toàn vẹn. Các khoá sẽ là được cung cấp cho bạn trong quá trình thiết lập tài khoản. Không có bất kỳ hạn chế nào về cách bạn cấu trúc quá trình triển khai của bạn. Trong hầu hết trường hợp, bạn sẽ có thể tận dụng mã mẫu và điều chỉnh mã đó theo nhu cầu của bạn.
- Tạo bàn phím di chuyển:
HMAC(encryption_key, initialization_vector || counter_bytes)
- XOR: Lấy kết quả này và
<xor>
bằng để đảo ngược mã hoá. - Xác minh: Chữ ký tính toàn vẹn chuyển 4 byte
HMAC(integrity_key, byte_array || initialization_vector)
Giải mã mã giả
// 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)
Mã C++ mẫu
Dưới đây là một chức năng chính trong giải mã mã ví dụ.
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'); } }
Lấy dữ liệu từ vùng đệm giao thức Mạng quảng cáo
Sau khi bạn đã giải mã và giải mã dữ liệu được truyền vào
%%EXTRA_TAG_DATA%%
thân mến, bạn đã sẵn sàng giải tuần tự vùng đệm giao thức
và lấy mã nhận dạng nhà quảng cáo để nhắm mục tiêu.
Nếu bạn chưa hiểu rõ về vùng đệm giao thức, hãy bắt đầu với tài liệu của chúng tôi.
Định nghĩa
Vùng đệm giao thức Mạng quảng cáo của chúng tôi được xác định như sau:
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; }
Bạn sẽ cần giải tuần tự bằng cách sử dụng ParseFromString()
như mô tả trong
Tài liệu về vùng đệm giao thức C++.
Để biết chi tiết về advertising_id
trên Android và iOS
Trường hashed_idfa
, xem phần Giải mã
Mã nhận dạng cho quảng cáo và Nhắm mục tiêu đến ứng dụng di động
khoảng không quảng cáo có IDFA.
Thư viện Java
Thay vì triển khai thuật toán mật mã để mã hoá và giải mã Giá trị nhận dạng nhà quảng cáo cho mạng quảng cáo, bạn có thể dùng DoubleClickCrypto.java. Để biết thêm thông tin, hãy xem Mật mã học.