Xác nhận giá giải mã

Khi mẫu quảng cáo của bạn thắng một phiên đấu giá, Google có thể thông báo cho bạn giá chiến thắng là gì, nếu đoạn mã HTML hoặc URL VAST xác định mẫu quảng cáo có chứa macro WINNING_PRICE. Google trả về giá chiến thắng dưới dạng mã hoá. Các chủ đề sau đây giải thích cách ứng dụng của bạn có thể giải mã thông tin giá chiến thắng.

Macro WINNING_PRICE có thể được đưa vào một mẫu quảng cáo, chẳng hạn như với một yêu cầu pixel vô hình đượ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=%%WINNING_PRICE%%' width='1' height='1'/>
</div>

Macro WINNING_PRICE cũng có thể được đưa vào URL VAST của mẫu quảng cáo video (nhưng không có trong URL hiển thị trong VAST):

https://example.com/vast/v?price=%%WINNING_PRICE%%

Trường hợp

  1. Ứng dụng của bạn có chứa macro WINNING_PRICE trong đoạn mã HTML hoặc URL VAST mà ứng dụng trả về cho Google.
  2. Google thay thế giá chiến thắng cho macro bằng phương thức mã hoá base64 không được đệm an toàn trên web (RFC 3548).
  3. Đoạn mã sẽ chuyển thông báo xác nhận theo định dạng mà bạn đã chọn. Ví dụ: thông báo xác nhận có thể được chuyển vào URL của một yêu cầu pixel ẩn được hiển thị trong quảng cáo.
  4. Trên máy chủ, base64 an toàn trên web của ứng dụng sẽ giải mã thông tin giá chiến thắng và giải mã kết quả.

Phần phụ thuộc

Bạn sẽ cần có một thư viện mật mã hỗ trợ HMAC SHA-1, chẳng hạn như OpenGL.

Mã mẫu

Mã mẫu được cung cấp bằng Java và C++, đồng thời 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 commons của Apache. Bạn sẽ không cần tải mã Apache commons xuống vì quá trình triển khai tài liệu tham khảo bao gồm phần cần thiết và do đó độc lập.

  • Mã mẫu C++ sử dụng phương thức BIO SSL base64. Phương thức này sẽ lấy một chuỗi mã hoá base64 an toàn cho web (RFC 3548) và giải mã chuỗi đó. Thông thường, chuỗi base64 an toàn trên web sẽ thay thế khoảng đệm "=" bằng dấu "." (lưu ý rằng dấu ngoặc kép được thêm vào để đọc rõ ràng và không được đưa vào giao thức) nhưng việc thay thế macro không đệm giá được mã hoá. Việc triển khai tệp đối 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á

Để giành chiến thắng trong quá trình mã hoá và giải mã giá, bạn cần có hai khoá bí mật nhưng dùng chung. Khoá tính toàn vẹn và khoá mã hoá lần lượt được gọi là i_keye_key. Cả hai khoá này đều được cung cấp khi thiết lập tài khoản dưới dạng chuỗi base64 an toàn trên web, và bạn có thể tìm thấy trên trang Authorized Buyers trong phần Cài đặt bên đặt giá thầu > Cài đặt RTB > Khoá mã hoá.

Ví dụ về khoá mã hoá và tính toàn vẹn:

skU7Ax_NL5pPAFyKdkfZjZz2-VhIN8bjj1rVFOaJ_5o=  // Encryption key (e_key)
arO23ykdNqUQ5LEoQ0FVmPkBd7xB5CO89PDZlSjpFxo=  // Integrity key (i_key)

Các khoá phải được giải mã an toàn cho web, sau đó được giải mã base64 bằng ứng dụng của bạn:

e_key = WebSafeBase64Decode('skU7Ax_NL5pPAFyKdkfZjZz2-VhIN8bjj1rVFOaJ_5o=')
i_key = WebSafeBase64Decode('arO23ykdNqUQ5LEoQ0FVmPkBd7xB5CO89PDZlSjpFxo=')

Giao thức mã hoá

Giá được mã hoá bằng một giao thức mã hoá tuỳ chỉnh được thiết kế để giảm thiểu mức hao tổn kích thước trong khi vẫn đảm bảo khả năng bảo mật cao. Lược đồ mã hoá sử dụng thuật toán HMAC có khoá để tạo một bảng bí mật dựa trên mã sự kiện hiển thị riêng biệt.

Giá được mã hoá có độ dài cố định là 28 byte. Nó bao gồm một vectơ khởi tạo 16 byte, 8 byte văn bản mật mã và một chữ ký tính toàn vẹn 4 byte. Giá đã mã hoá được mã hoá base64 an toàn trên web (theo RFC 3548), không có các ký tự khoảng đệm. Do đó, giá được mã hoá 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á chiến thắng phải trả là bao nhiêu.

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)> nên quy 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 toàn vẹn sẽ lấy 4 byte của <HMAC(integrity_key, price||initialization_vector)> trong đó || là nối.

Thông tin đầu vào
iv vectơ khởi tạo (16 byte – duy nhất 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 một phần triệu đơ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 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 về tính toàn vẹn bằng khoá tính toàn vẹn. Các khoá sẽ được cung cấp cho bạn trong quá trình thiết lập. Không có bất kỳ hạn chế nào đối với chi tiết về cách bạn xây dựng cấu trúc triển khai. Trong hầu hết trường hợp, bạn sẽ có thể lấy mã mẫu và điều chỉnh mã đó cho phù hợp với 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 Được mã hoá base64 an toàn cho web gồm 38 ký tự
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 lỗi thời

Để phát hiện phản hồi lỗi thời hoặc các cuộc tấn công 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ể so với thời gian hệ thống, sau khi tính đến sự chênh lệch về múi giờ.

Vectơ khởi tạo chứa dấu thời gian trong 8 byte đầu tiên. Hàm C++ có thể đọc chuỗi 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 sang dạng dễ đọ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ã hoá để mã hoá và giải mã giá chiến thắng, bạn có thể sử dụng DoubleClickCrypto.java. Để biết thêm thông tin, hãy xem phần Mật mã học.