Khi mẫu quảng cáo của bạn giành chiến thắng trong một phiên đấu giá, Google có thể thông báo cho bạn về giá giành chiến thắng nếu mẫu quảng cáo đó có macro ${AUCTION_PRICE}
.
Khi mở rộng, macro sẽ trả về giá trúng thưởng ở dạng mã hoá. Bạn có thể đưa mã này vào mẫu quảng cáo, chẳng hạn như với yêu cầu pixel không hiển thị được hiển thị như một phần của quảng cáo:
<div> <script language='JavaScript1.1' src='https://example.com?creativeID=5837243'/> <img src='https://example.com/t.gif?price=${AUCTION_PRICE}' width='1' height='1'/> </div>
Bạn cũng có thể đưa macro ${AUCTION_PRICE}
vào URL VAST của mẫu quảng cáo dạng video, nhưng không được đưa vào URL hiển thị trong VAST:
https://example.com/vast/v?price=${AUCTION_PRICE}
Trường hợp
- Ứng dụng đặt giá thầu OpenRTB của bạn bao gồm macro
${AUCTION_PRICE}
trong đoạn mã HTML hoặc URL VAST mà ứng dụng trả về cho Google. - Google sẽ thay thế giá trúng thưởng cho macro trong quá trình mã hoá base64 an toàn cho web chưa được đệm (RFC 3548).
- Đoạn mã này sẽ chuyển thông báo xác nhận ở định dạng bạn đã chọn. Ví dụ: thông báo xác nhận có thể được truyền trong URL của yêu cầu pixel ẩn được hiển thị trong quảng cáo.
- Trên máy chủ, base64 an toàn cho web của ứng dụng sẽ giải mã thông tin về giá trúng thưởng và giải mã kết quả.
Phần phụ thuộc
Bạn sẽ cần một thư viện mật mã hỗ trợ SHA-1 HMAC, chẳng hạn như Openssl.
Mã mẫu
Mã mẫu được cung cấp trong Java và C++ và có thể được tải xuống từ dự án privatedatacommunicationprotocol.
Mã mẫu Java sử dụng bộ giải mã base64 từ dự án Apache commons. Bạn sẽ không cần tải mã Apache commons xuống, vì quá trình triển khai tham chiếu bao gồm phần cần thiết và do đó là độc lập.
Mã mẫu C++ sử dụng phương thức BIO base64 của OpenSSL. Phương thức này lấy một chuỗi được mã hoá base64 an toàn cho web (RFC 3548) và giải mã chuỗi đó. Thông thường, các chuỗi base64 an toàn cho web sẽ thay thế khoảng đệm "=" bằng "." (lưu ý rằng dấu ngoặc kép được thêm vào để đọc rõ ràng và không có trong giao thức) nhưng việc thay thế macro không đệm giá đã mã hoá. Việc triển khai tham chiếu sẽ thêm khoảng đệm vì OpenSSL gặp sự cố với các chuỗi không được đệm.
Mã hoá
Quá trình mã hoá và giải mã giá thắng thầu yêu cầu hai khoá bí mật nhưng dùng chung. Khoá tính toàn vẹn và khoá mã hoá, được gọi là i_key
và e_key
tương ứng. Cả hai khoá đều được cung cấp khi thiết lập tài khoản dưới dạng chuỗi base64 an toàn cho web và có thể tìm thấy trên trang Authorized Buyers trong mục Cài đặt người đặt giá thầu > Cài đặt RTB > Khoá mã hoá.
Ví dụ về khoá mã hoá và khoá toàn vẹn:
skU7Ax_NL5pPAFyKdkfZjZz2-VhIN8bjj1rVFOaJ_5o= // Encryption key (e_key) arO23ykdNqUQ5LEoQ0FVmPkBd7xB5CO89PDZlSjpFxo= // Integrity key (i_key)
Khoá phải được giải mã an toàn cho web, sau đó ứng dụng của bạn giải mã base64:
e_key = WebSafeBase64Decode('skU7Ax_NL5pPAFyKdkfZjZz2-VhIN8bjj1rVFOaJ_5o=') i_key = WebSafeBase64Decode('arO23ykdNqUQ5LEoQ0FVmPkBd7xB5CO89PDZlSjpFxo=')
Lược đồ mã hoá
Giá được mã hoá bằng một lược đồ mã hoá tuỳ chỉnh được thiết kế để giảm thiểu hao tổn kích thước trong khi vẫn đảm bảo tính bảo mật đầy đủ. Lược đồ mã hoá sử dụng thuật toán HMAC khoá để tạo một vùng đệm bí mật dựa trên mã sự kiện hiển thị duy nhất.
Giá đã mã hoá có độ dài cố định là 28 byte. Gói này bao gồm một vectơ khởi động 16 byte, 8 byte văn bản đã mã hoá và chữ ký tính toàn vẹn 4 byte. Giá đã mã hoá được mã hoá base64 an toàn cho web, theo RFC 3548, bỏ qua các ký tự đệm. Do đó, giá được mã hoá gồm 28 byte được mã hoá dưới dạng chuỗi base-64 an toàn trên web gồm 38 ký tự, bất kể giá trúng thưởng đã trả.
Ví dụ về giá được mã hoá:
YWJjMTIzZGVmNDU2Z2hpN7fhCuPemCce_6msaw // 100 CPI micros YWJjMTIzZGVmNDU2Z2hpN7fhCuPemCAWJRxOgA // 1900 CPI micros YWJjMTIzZGVmNDU2Z2hpN7fhCuPemC32prpWWw // 2700 CPI micros
Định dạng đã mã hoá là:
{initialization_vector (16 bytes)}{encrypted_price (8 bytes)} {integrity (4 bytes)}
Giá được mã hoá dưới dạng <price xor HMAC(encryption_key,
initialization_vector)>
, do đó, quá trình giải mã sẽ tính toán HMAC(encryption_key,initialization_vector)
và xor với giá đã mã hoá để đảo ngược quá trình mã hoá. Giai đoạn tính toàn vẹn mất 4 byte <HMAC(integrity_key, price||initialization_vector)>
, trong đó ||
là chuỗi nối.
Thông tin đầu vào | |
---|---|
iv |
vectơ khởi tạo (16 byte – dành riêng cho lượt hiển thị) |
e_key |
khoá mã hoá (32 byte – được cung cấp khi thiết lập tài khoản) |
i_key |
khoá tính toàn vẹn (32 byte – được cung cấp khi thiết lập tài khoản) |
price |
(8 byte – tính bằng micro của đơn vị tiền tệ của tài khoản) |
Ký hiệu | |
hmac(k, d) |
SHA-1 HMAC của dữ liệu d , sử dụng khoá k |
a || b |
chuỗi a được nối với chuỗi b |
Mã giả | |
pad = hmac(e_key, iv) // first 8 bytes enc_price = pad <xor> price signature = hmac(i_key, price || iv) // first 4 bytes final_message = WebSafeBase64Encode( iv || enc_price || signature ) |
Lược đồ giải mã
Mã giải mã của bạn phải giải mã giá bằng khoá mã hoá và xác minh các bit toàn vẹn bằng khoá toàn vẹn. Khoá sẽ được cung cấp cho bạn trong quá trình thiết lập. Không có quy định hạn chế nào về chi tiết cách bạn cấu trúc quá trình triển khai. Trong hầu hết trường hợp, bạn có thể lấy mã mẫu và điều chỉnh mã đó theo nhu cầu của mình.
Thông tin đầu vào | |
---|---|
e_key |
khoá mã hoá, 32 byte – được cung cấp khi thiết lập tài khoản |
i_key |
khoá tính toàn vẹn, 32 byte – được cung cấp khi thiết lập tài khoản |
final_message |
38 ký tự được mã hoá base64 an toàn cho web |
Mã giả | |
// Base64 padding characters are omitted. // Add any required base64 padding (= or ==). final_message_valid_base64 = AddBase64Padding(final_message) // Web-safe decode, then base64 decode. enc_price = WebSafeBase64Decode(final_message_valid_base64) // Message is decoded but remains encrypted. (iv, p, sig) = enc_price // Split up according to fixed lengths. price_pad = hmac(e_key, iv) price = p <xor> price_pad conf_sig = hmac(i_key, price || iv) success = (conf_sig == sig) |
Phát hiện các cuộc tấn công phản hồi cũ
Để phát hiện các cuộc tấn công phản hồi cũ hoặc phát lại, bạn nên lọc các phản hồi có dấu thời gian khác biệt đáng kể với thời gian hệ thống, sau khi tính đến sự khác biệt về múi giờ.
Vectơ khởi chạy chứa dấu thời gian trong 8 byte đầu tiên. Hàm C++ sau đây có thể đọc tệp này:
void GetTime(const char* iv, struct timeval* tv) { uint32 val; memcpy(&val, iv, sizeof(val)); tv->tv_sec = htonl(val); memcpy(&val, iv+sizeof(val), sizeof(val)); tv->tv_usec = htonl(val) }
Bạn có thể chuyển đổi dấu thời gian thành một dạng mà con người có thể đọc được bằng cách sử dụng mã C++ sau:
struct tm tm; localtime_r(&tv->tv_sec, &tm); printf("%04d-%02d-%02d|%02d:%02d:%02d.%06ld", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, tv_.tv_usec);
Thư viện Java
Thay vì triển khai các thuật toán mật mã để mã hoá và giải mã giá trúng thưởng, bạn có thể sử dụng DoubleClickCrypto.java. Để biết thêm thông tin, hãy xem phần Mã hoá.