إذا مرَّر الناشرون بيانات الموقع الجغرافي المتوافق مع الأجهزة الجوّالة إلى "الشراة المعتمَدون" الأكثر تحديدًا من الرمز البريدي، سيرسل "الشراة المعتمَدون" الجغرافي إلى المشترين عبر حقل مشفّر جديد: BidRequest.encrypted_hyperlocal_set
.
المخطط الزمني
- يثبّت المستخدم تطبيقًا متوافقًا مع الإعلانات متوافقًا مع الأجهزة الجوّالة ويوافق على وصول التطبيق إلى الموقع الجغرافي للجهاز ومشاركته مع أطراف ثالثة. وهذا التطبيق مُدمج أيضًا مع حزمة تطوير البرامج (SDK) في "إعلانات Google"، ويرسل هذا الموقع الجغرافي إلى Google.
- تُنشئ خوادم Google إشارة استهداف محلية خاصة تمثّل جدارًا جغرافيًا تحيط بموقع الجهاز الجغرافي، كحماية خصوصية المستخدم.
- تعمل خوادم Google على إنشاء تسلسل وإشارة إشارة استهداف محلية باستخدام مفتاح الأمان الخاص بكل مشترٍ. تذكّر أنّ نظام عروض الأسعار يعتمد على المفتاح نفسه لفك تشفير وحدة ماكرو WinNING_PRICE.
- يك ويمكن عندئذٍ لنظام عروض الأسعار الخاص بك تحليل الإشارة وعرض الأسعار وفقًا لذلك.
المهام التابعة
ستحتاج إلى مكتبة مشفّرة تتوافق مع خوارزمية SHA-1 HMAC، مثل Openssl.
التعريف
يتم تحديد إشارة استهداف محلية عالية في Proto على النحو التالي:
// A hyperlocal targeting location when available. // message Hyperlocal { // A location on the Earth's surface. // message Point { optional float latitude = 1; optional float longitude = 2; } // The mobile device can be at any point inside the geofence polygon defined // by a list of corners. Currently, the polygon is always a parallelogram // with 4 corners. repeated Point corners = 1; } message HyperlocalSet { // This field currently contains at most one hyperlocal polygon. repeated Hyperlocal hyperlocal = 1; // The approximate geometric center of the geofence area. It is calculated // exclusively based on the geometric shape of the geofence area and in no // way indicates the mobile device's actual location within the geofence // area. If multiple hyperlocal polygons are specified above then // center_point is the geometric center of all hyperlocal polygons. optional Hyperlocal.Point center_point = 2; } // Hyperlocal targeting signal when available, encrypted as described at // https://developers.google.com/authorized-buyers/rtb/response-guide/decrypt-hyperlocal optional bytes encrypted_hyperlocal_set = 40;
تحتوي كل إشارة استهداف لغويًا محليًا على مضلع واحد أو أكثر ونقطة توسيط. بالنسبة إلى كل مضلّع، تحتوي إشارة الاستهداف المحلي على:
- خط الطول وخط العرض لكل زاوية من المضلع بالتسلسل،
ويتم تمريره كحقل
corners
متكرر. - المركز الهندسي التقريبي لمساحة الحدود الجغرافية، تم تمريره في الحقل الاختياري
center_point
.
بنية إشارة الاستهداف
تحتوي إشارة الاستهداف المحلي المشفّر المضمّنة في
BidRequest.encrypted_hyperlocal_set
على 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
، يتم إنشاء ciphertext
بحجم 20 بايت على النحو التالي:
<byte_array <xor> HMAC(encryption_key, initialization_vector || counter_bytes)>
حيث يكون ||
عبارة عن تسلسل.
التعريفات
متغير | التفاصيل |
---|---|
initialization_vector |
16 بايت - فريد لمرة الظهور. |
encryption_key |
32 بايت - يتم تقديمها عند إعداد الحساب. |
integrity_key |
32 بايت - يتم تقديمها عند إعداد الحساب. |
byte_array |
عنصر HyperlocalSet متسلسل، في أقسام 20 بايت. |
counter_bytes |
قيمة بايت تعرض الرقم الترتيبي للقسم، انظر أدناه. |
final_message |
تم إرسال مصفوفة وحدات البايت من خلال الحقل BidRequest.encrypted_hyperlocal_set . |
عوامل التشغيل | التفاصيل |
---|---|
hmac(key, data) |
بروتوكول SHA-1 MAC، باستخدام key لتشفير data |
a || b |
السلسلة a مرتبطة بسلسلة b . |
حساب Count_bytes
تحدّد السمة counter_bytes
ترتيب كل قسم بحجم 20 بايت من
ciphertext
. تجدُر الإشارة إلى أنّ القسم الأخير قد يتضمّن بين 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 بشكل تسلسلي. |
لا نتوقع أن يتجاوز طول
BidRequest.encrypted_hyperlocal_set
كيلوبايت واحدًا،
مع أخذ المزيد من النمو في الاعتبار. ومع ذلك، طالما أنّ السمة counter_bytes
تتيح هذه الإشارات، يمكن استخدام إشارة عشوائية ذات مدة عشوائية.
نظام التشفير
يستند نظام التشفير لإشارة الاستهداف المحلي للغاية إلى المخطّط نفسه المستخدَم في فك ترميز الأسعار.
التسلسل: إنّ إشارة الاستهداف المحلي، وهي نسخة من كائن HyperlocalSet كما هو محدّد في Proto، يتم تسلسلها أولاً من خلال
SerializeAsString()
إلى مصفوفة بايت.التشفير: يتم بعد ذلك تشفير مصفوفة وحدات البايت باستخدام نظام تشفير مخصّص مصمّم لتقليل الحجم الزائد مع ضمان الأمان الكافي. يستخدم نظام التشفير خوارزمية HMAC رئيسية لإنشاء لوحة سرّية استنادًا إلى
initialization_vector
، وهو حدث فريد لحدث الظهور.
رمز مستعار للتشفير
byte_array = SerializeAsString(HyperlocalSet 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)
.
الرمز البريدي للتشفير
(initialization_vector, ciphertext, integrity_signature) = final_message // split up according to length rules pad = hmac(encryption_key, initialization_vector || counter_bytes) // for each 20-byte section of ciphertext byte_array = ciphertext <xor> pad // for each 20-byte section of ciphertext 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'); } } }
نموذج إشارة ومفاتيح محلية للغاية
لاختبار الرمز وإثبات ملكيته:
- حوِّل سلسلة تحتوي على 308 حرف ست عشري إلى مصفوفة من 154 بايت. على سبيل المثال، في ما يلي السلسلة التالية:
E2014EA201246E6F6E636520736F7572636501414243C0ADF6B9B6AC17DA218FB50331EDB376701309CAAA01246E6F6E636520736F7572636501414243C09ED4ECF2DB7143A9341FDEFD125D96844E25C3C202466E6F6E636520736F7572636502414243517C16BAFADCFAB841DE3A8C617B2F20A1FB7F9EA3A3600256D68151C093C793B0116DB3D0B8BE9709304134EC9235A026844F276797
تحويله إلى مصفوفة من 154 بايت على النحو التالي:const char serialized_result[154] = { 0xE2, 0x01, 0x4E, ... };
- يجب استدعاء الطريقة
BidRequest.ParsePartialFromString()
لإلغاء تسلسل 154 بايت في المخزن المؤقت لبروتوكولBidRequest
.BidRequest bid_req; bid_req.ParsePartialFromString(serialzed_result);
- تأكّد من أن
BidRequest
يحتوي على 3 حقول فقط:encrypted_hyperlocal_set
المُعلَنة في رسالةBidReqeust
.encrypted_advertising_id
المُعلَنة في رسالةBidReqeust.Mobile
.encrypted_hashed_idfa
المُعلَنة في رسالةBidReqeust.Mobile
.
مثلاً:
encrypted_hyperlocal_set:( { 100, 100 }, { 200, -300 }, { -400, 500 }, { -600, -700 },) encrypted_advertising_id: { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11 } encrypted_hashed_idfa : { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0xF1 }
- استخدِم السمتَين
encryption_key
وintegrity_key
لفك تشفير 3 حقول وتحقّق من فك تشفيرها بشكل صحيح.encryption_key = {0x02, 0xEE, 0xa8, 0x3c, 0x6c, 0x12, 0x11, 0xe1, 0x0b, 0x9f, 0x88, 0x96, 0x6c, 0xee, 0xc3, 0x49, 0x08, 0xeb, 0x94, 0x6f, 0x7e, 0xd6, 0xe4, 0x41, 0xaf, 0x42, 0xb3, 0xc0, 0xf3, 0x21, 0x81, 0x40}; integrity_key = {0xbf, 0xFF, 0xec, 0x55, 0xc3, 0x01, 0x30, 0xc1, 0xd8, 0xcd, 0x18, 0x62, 0xed, 0x2a, 0x4c, 0xd2, 0xc7, 0x6a, 0xc3, 0x3b, 0xc0, 0xc4, 0xce, 0x8a, 0x3d, 0x3b, 0xbd, 0x3a, 0xd5, 0x68, 0x77, 0x92};
رصد هجمات الاستجابة القديمة
لاكتشاف هجمات الاستجابة القديمة، ننصح بفلترة الردود بطابع زمني يختلف كثيرًا عن وقت النظام، بعد مراعاة الاختلافات في المناطق الزمنية. تم ضبط خوادمنا على توقيت PST/توقيت المحيط الهادئ الصيفي.
للحصول على تفاصيل التنفيذ، يُرجى الاطّلاع على مقالة "اكتشاف هجمات الاستجابة القديمة" في مقالة فك تشفير الأسعار.
مكتبة Java
بدلاً من تنفيذ خوارزميات التشفير لتشفير وفك ترميز إشارات الاستهداف المحلي، يمكنك استخدام DoubleClickCrypto.java. لمزيد من المعلومات، راجِع التشفير.