ถอดรหัสการยืนยันราคา

เมื่อครีเอทีฟโฆษณาชนะการประมูล Google สามารถแจ้งให้คุณทราบว่าราคาที่ชนะคือเท่าใด หากข้อมูลโค้ด HTML หรือ VAST URL ที่กำหนดครีเอทีฟโฆษณามีมาโคร WINNING_PRICE รวมอยู่ด้วย Google จะแสดงราคาที่ชนะในรูปแบบที่เข้ารหัส หัวข้อต่อไปนี้อธิบายวิธีที่แอปพลิเคชันของคุณสามารถถอดรหัสข้อมูลราคาที่ชนะ

คุณใส่มาโคร WINNING_PRICE ไว้ในครีเอทีฟโฆษณาได้ เช่น โดยจะแสดงคำขอพิกเซลที่มองไม่เห็นเป็นส่วนหนึ่งของโฆษณา ดังนี้

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

คุณรวมมาโคร WINNING_PRICE ไว้ใน VAST URL ของครีเอทีฟโฆษณาวิดีโอได้ด้วย (แต่ไม่ใช่ใน URL การแสดงผลใน VAST)

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

สถานการณ์

  1. แอปพลิเคชันของคุณมีมาโคร WINNING_PRICE ในข้อมูลโค้ด HTML หรือ VAST URL ที่ส่งกลับไปยัง Google
  2. Google จะแทนที่ราคาที่ชนะสำหรับมาโครด้วยการเข้ารหัส Base64 แบบ Web-safe แบบไม่มีอักขระแทรก (RFC 3548)
  3. ข้อมูลโค้ดจะส่งการยืนยันในรูปแบบที่คุณเลือก ตัวอย่างเช่น อาจมีการส่งการยืนยันใน URL ของคำขอพิกเซลที่มองไม่เห็นซึ่งแสดงผลเป็นส่วนหนึ่งของโฆษณา
  4. บนเซิร์ฟเวอร์ แอปพลิเคชัน Web-safe base64 ของคุณจะถอดรหัสข้อมูลราคาที่ชนะและถอดรหัสผลลัพธ์

การอ้างอิง

คุณจะต้องมีไลบรารีคริปโตที่รองรับ SHA-1 HMAC เช่น Openssl

รหัสตัวอย่าง

โดยโค้ดตัวอย่างจะมีให้ใน Java และ C++ และดาวน์โหลดได้จากโปรเจ็กต์privatedatacommunicationprotocol

  • โค้ดตัวอย่างของ Java จะใช้ตัวถอดรหัส base64 จากโปรเจ็กต์ Apache Commons คุณไม่จำเป็นต้องดาวน์โหลดโค้ด Apache Commons เนื่องจากการใช้งานข้อมูลอ้างอิงรวมส่วนที่จำเป็นและมีอยู่ในตัวแล้ว

  • โค้ดตัวอย่าง C++ ใช้เมธอด BIO ของ OpenSSL ใช้สตริงที่เข้ารหัสแบบ Web-safe base64 (RFC 3548) และถอดรหัส โดยทั่วไป Web-safe base64 สตริงจะแทนที่ "=" ระยะห่างจากขอบด้วย "." (โปรดทราบว่าระบบจะเพิ่มเครื่องหมายคำพูดเพื่อความชัดเจนในการอ่าน และไม่รวมอยู่ในโปรโตคอล) แต่การแทนที่มาโครจะไม่ใช้ราคาที่เข้ารหัส การใช้งานข้อมูลอ้างอิงจะเพิ่มระยะห่างจากขอบเนื่องจาก OpenSSL มีปัญหากับสตริงที่ไม่มีอักขระบุคลิก

การเข้ารหัส

การเข้ารหัสและการถอดรหัสราคาที่ชนะต้องใช้ข้อมูลลับ 2 อย่าง แต่ใช้คีย์ร่วมกัน คีย์ความสมบูรณ์และคีย์การเข้ารหัสเรียกว่า i_key และ e_key ตามลำดับ คีย์ทั้ง 2 คีย์มีให้ในการตั้งค่าบัญชีในฐานะสตริง base64 สำหรับ Web-safe และอยู่ในหน้า Authorized Buyers ในส่วนการตั้งค่าผู้เสนอราคา > การตั้งค่า RTB > คีย์การเข้ารหัส

ตัวอย่างคีย์ความสมบูรณ์และคีย์การเข้ารหัส

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

คีย์ควรถอดรหัส Web-safe แล้วถอดรหัส base64 โดยแอปพลิเคชันของคุณ

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

รูปแบบการเข้ารหัส

ราคาได้รับการเข้ารหัสโดยใช้รูปแบบการเข้ารหัสที่กำหนดเองซึ่งออกแบบมาเพื่อลดส่วนเกินของขนาดในขณะที่มั่นใจได้ถึงความปลอดภัยที่เพียงพอ รูปแบบการเข้ารหัสนี้ใช้อัลกอริทึม HMAC ที่มีคีย์ในการสร้างแพดลับตามรหัสเหตุการณ์การแสดงผลที่ไม่ซ้ำกัน

ราคาที่เข้ารหัสมีความยาวคงที่ที่ 28 ไบต์ ซึ่งประกอบด้วยเวกเตอร์การเริ่มต้น 16 ไบต์ ข้อความเข้ารหัส 8 ไบต์ และลายเซ็นความสมบูรณ์แบบ 4 ไบต์ ราคาที่เข้ารหัสคือ Web-safe base64 ที่เข้ารหัสตาม RFC 3548 โดยไม่ใส่อักขระระยะห่างจากขอบ ดังนั้น ราคาที่เข้ารหัสแบบ 28 ไบต์จะเข้ารหัสเป็นสตริง Base-64 ที่ใช้กับเว็บที่ปลอดภัยความยาว 38 อักขระ โดยไม่คำนึงถึงราคาที่ชนะที่ชำระ

ตัวอย่างราคาที่เข้ารหัส

YWJjMTIzZGVmNDU2Z2hpN7fhCuPemCce_6msaw  // 100 CPI micros
YWJjMTIzZGVmNDU2Z2hpN7fhCuPemCAWJRxOgA  // 1900 CPI micros
YWJjMTIzZGVmNDU2Z2hpN7fhCuPemC32prpWWw  // 2700 CPI micros

รูปแบบที่เข้ารหัสมีดังนี้

{initialization_vector (16 bytes)}{encrypted_price (8 bytes)}
{integrity (4 bytes)}

ราคามีการเข้ารหัสเป็น <price xor HMAC(encryption_key, initialization_vector)> ดังนั้นการถอดรหัสจึงคำนวณ HMAC(encryption_key,initialization_vector) และ xor ด้วยราคาที่เข้ารหัสเพื่อกลับการเข้ารหัส ขั้นตอนความสมบูรณ์ใช้ <HMAC(integrity_key, price||initialization_vector)> ขนาด 4 ไบต์ที่ || มีการเชื่อมต่อ

อินพุต
iv เวกเตอร์การเริ่มต้น (16 ไบต์ - ไม่ซ้ำกันในการแสดงผล)
e_key คีย์การเข้ารหัส (32 ไบต์ - มีให้ในการตั้งค่าบัญชี)
i_key Integrity Key (32 ไบต์ - มีให้ในการตั้งค่าบัญชี)
price (8 ไบต์ - ในไมโครของสกุลเงินของบัญชี)
เครื่องหมาย
hmac(k, d) SHA-1 HMAC ของข้อมูล d โดยใช้คีย์ k
a || b สตริง a เชื่อมต่อกับสตริง b
ซูโดโค้ด
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 )

รูปแบบการถอดรหัส

โค้ดถอดรหัสต้องถอดรหัสราคาโดยใช้คีย์การเข้ารหัส และยืนยันบิตสมบูรณ์ด้วยคีย์ความสมบูรณ์ คุณจะได้รับคีย์ในระหว่างการตั้งค่า เราไม่ได้จำกัดรายละเอียดวิธีจัดโครงสร้างการติดตั้งใช้งาน โดยส่วนใหญ่แล้ว คุณควรสามารถนำโค้ดตัวอย่าง มาปรับใช้ได้ตามความต้องการ

อินพุต
e_key คีย์การเข้ารหัส 32 ไบต์ - มีให้ในการตั้งค่าบัญชี
i_key คีย์ความสมบูรณ์ 32 ไบต์ - มีให้ในการตั้งค่าบัญชี
final_message เข้ารหัส Web-safe base64 ความยาว 38 อักขระ
ซูโดโค้ด
// 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)

ตรวจจับการโจมตีการตอบสนองที่ไม่มีอัปเดต

หากต้องการตรวจจับการตอบสนองที่ไม่มีการอัปเดตหรือการเล่นซ้ำสำหรับการโจมตี เราขอแนะนำให้คุณกรองคำตอบด้วยการประทับเวลาที่แตกต่างจากเวลาของระบบอย่างมาก หลังจากพิจารณาความแตกต่างของเขตเวลาแล้ว

เวกเตอร์การเริ่มต้นมีการประทับเวลาใน 8 ไบต์แรก ซึ่งสามารถอ่านได้ด้วยฟังก์ชัน C++ ต่อไปนี้

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

การประทับเวลาสามารถแปลงเป็นรูปแบบที่มนุษย์อ่านได้โดยใช้โค้ด C++ ต่อไปนี้

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

ไลบรารี Java

คุณใช้ DoubleClickCrypto.java แทนการใช้อัลกอริทึมคริปโตเพื่อเข้ารหัสและถอดรหัสราคาที่ชนะได้ ดูข้อมูลเพิ่มเติมได้ที่วิทยาการเข้ารหัสลับ