Overview

ממשק API של Oblivious HTTP Gateway API

הערה: המסמכים האלה עדיין בשלבי פיתוח. צפויים שיפורים בעתיד הקרוב.

ממשק API של Oblivious HTTP Gateway API הוא ממשק API לשמירה על פרטיות המבוסס על פרוטוקול IETF RFC בשם Oblivious HTTP, RFC 9458.

סקירה כללית

גלישה בטוחה של Oblivious HTTP Gateway API הוא שירות של Google שמאפשר לאפליקציות לקוח לבדוק כתובות URL מול רשימות של Google שכוללות משאבי אינטרנט לא בטוחים שמתעדכנים באופן שוטף, כולל אמצעי הגנה נוספים על פרטיות.

אפשר לעשות זאת באמצעות פרוטוקול פשוט שנקרא Oblivious HTTP, או OHTTP. זהו פרוטוקול ללא שמירת מצב, שיכול לשמש את לקוחות הגלישה הבטוחה כדי לגשת אל ממשקי ה-API של גלישה בטוחה בגרסה 5, ולקבל אמצעי הגנה חזקים וכיסוי מוגבר בלי לפגוע במשתמשים פרטיות.

הערה: לא ניתן לגשת לממשקי API של גרסה 4 של הגלישה הבטוחה של Google דרך השירות הזה.

פרוטוקול Oblivious HTTP של גלישה בטוחה

פרוטוקול RFC

Oblivious HTTP הוא פרוטוקול קל ופשוט שמוגדר ב-RFC 9458, והוא משמש להצפנה ולשליחה של הודעות HTTP מלקוח לשרת יעד. הפעולה הזו משתמשת בשירות ממסר מהימן באופן שמצמצם את השימוש של שרת היעד במטא-נתונים, כמו כתובת IP ופרטי חיבור לצורך זיהוי הלקוח, תוך שמירה על פרטיות ואבטחה בנוסף לפרוטוקול HTTP/S פשוט. הפרוטוקול משתמש ב-Binary HTTP, שמוגדר ב-RFC 9292, כדי לקודד/לפענח בקשות/תגובות של HTTP.

ברמה הכללית, שרת הממסר נמצא בין משאב הלקוח ל-Gateway, שמעביר את תנועת הלקוחות דרך שרת proxy על ידי הסרת כל מזהי הלקוח, כולל מאפיינים רגישים לפרטיות כמו כתובות IP, ומבצע אנונימיזציה של בקשות HTTP נכנסות לשירות Gateway. היתרון הנוסף של OHTTP הוא שכל הבקשות מוצפנות מקצה לקצה, כלומר שאילתות של גלישה בטוחה (כלומר גיבובים חתוכים של ביטויים של כתובות URL) לא גלויות לשרת הממסר. הטמעה לדוגמה ב-Chrome מופיעה בblogpost.

הארכיטקטורה הכוללת של השירות.
Fig: זרימת OHTTP.

הלקוחות יכולים לבחור כל ספק ממסר (למשל, Fastly) לשילוב עם השירות. כדי לגשת לשירות, הממסר צריך להשתמש באימות Oauth 2.0 עם היקף ההרשאה הבא.


// OAuth Authorization scope: https://www.googleapis.com/auth/3p-relay-safe-browsing
נקודות קצה ל-API
מפתח ציבורי מסוג OHTTP

נקודת הקצה (endpoint) הזו מספקת הגדרה של מפתח ציבורי מסוג OHTTP כפי שמצוין ב-RFC 9458, והלקוח ישתמש בו כדי להצפין בקשת OHTTP.


GET https://safebrowsingohttpgateway.googleapis.com/v1/ohttp/hpkekeyconfig?key=<API key>

מפתח ה-API שלמעלה אינו הכרחי בהחלט. השרת לא משנה את המפתח הציבורי של OHTTP בהתאם למפתח ה-API שסופק. הלקוחות יכולים לבדוק את העובדות האלה על ידי שימוש במפתחות API תקפים שונים כדי לגשת לנקודת הקצה הזאת, בלי להשתמש בכלל במפתחות API, ולבדוק שהתשובה אכן מכילה את אותו מפתח ציבורי של OHTTP. עם זאת, כדי להקל על ניפוי באגים, מומלץ להשתמש במפתח API. כך לקוחות יכולים לצפות בנתונים סטטיסטיים כמו מספר הבקשות במסוף Google Cloud. אם הלקוח מתכוון לספק מפתח API, אפשר לקרוא את מאמרי העזרה בנושא הגדרת מפתחות API.

כפי שצוין בקטע המלצות בנושא פרטיות, כדי לעמוד ביעדים של עקביות במפתחות, מומלץ לספקי לקוח להגדיר תשתית של הפצת מפתחות מרוכזת כדי לאחזר את המפתח מנקודת הקצה הזו ולהפיץ אותו לאפליקציות הלקוח שלהם.

בהתאם להנחיות לניהול מפתחות, המפתחות עוברים רוטציה באופן קבוע בשרת. על הלקוחות לרענן את המפתח, כלומר, לאחזר ולעדכן את העותק המקומי של המפתח מדי פעם, כדי למנוע כשלים בפענוח.

הלקוחות צריכים לרענן (לאחזר ולעדכן) את המפתח הציבורי פעם ביום. אם משתמשים במנגנון הפצה ריכוזי, המנגנון הזה מבטיח אחזור והפצה של המפתחות פעם ביום.

בקשה מכוסה של OHTTP

נקודת הקצה (endpoint) הזו תציג את בקשת ה-OHTTP שכלולה בגוף ה-HTTP של בקשת ה-POST, על ידי ביצוע פענוח של הבקשה, ולאחר מכן תצפין את תגובת ה-OHTTP שתועבר חזרה לממסר בתגובת ה-HTTP. הלקוח חייב לכלול את כותרת הבקשה Content-Type כ-message/ohttp-req בבקשת ה-HTTP POST.


POST https://safebrowsingohttpgateway.googleapis.com/v1/ohttp:handleOhttpEncapsulatedRequest?key=<API key>

הערה: בהתאם להנחיות ב-RFC, צריך לקודד את הבקשה הפנימית (אפשר לעיין במסמכי התיעוד של V5 שמסבירים איך לפתח בקשה של גלישה בטוחה) באמצעות פרוטוקול Binary HTTP, RFC 9292.

ספריות לקוח

ל-Google Quiche יש הטמעות בצד הלקוח עבור הפרוטוקולים OHTTP ו-BHTTP. אנחנו ממליצים ללקוחות להשתמש בספריות האלה. בהמשך מופיע קוד מדומה להסבר על בניית בקשות OHTTP כדי לגשת ל-API.

הטמעה לדוגמה בצד הלקוח

לקוחות מאחזרים את המפתח הציבורי של Oblivious HTTP מנקודת הקצה של מפתח ציבורי. לאחר מכן מאתחלים את תצורת מפתח ה-OHTTP של קיש כמו זה, ומאתחלים את לקוח ה-OHTTP של קיש.


auto ohttp_key_cfgs = quiche::ObliviousHttpKeyConfigs::ParseConcatenatedKeys(std::string public_key); auto key_config = ohttp_key_cfgs->PreferredConfig(); auto public_key = ohttp_key_cfgs->GetPublicKeyForId(key_config.GetKeyId()) auto ohttp_client = quiche::ObliviousHttpClient::Create(public_key, key_config);

הלקוח ישתמש בקידוד HTTP בינארי כדי ליצור בקשת BHTTP כשלב ראשון לפני ההצפנה.


quiche::BinaryHttpRequest::ControlData bhttp_ctrl_data{ .method = "POST", .scheme = "https", .authority = "safebrowsing.googleapis.com", .path = "/v5/hashes:search?key=<API key>&hashPrefixes=<HASH prefix 1>&hashPrefixes=<HASH prefix 2>", }; quiche::BinaryHttpRequest bhttp_request(bhttp_ctrl_data);

לאחר מכן הלקוח יצפין את בקשת ה-HTTP הבינארית שנוצרה בשלב הקודם.


auto bhttp_serialized = bhttp_request.Serialize(); auto ohttp_request = ohttp_client.CreateObliviousHttpRequest(*bhttp_serialized); // Client must include this in POST body, and add `Content-Type` header as "message/ohttp-req". auto payload_include_in_post_body = ohttp_request.EncapsulateAndSerialize();

אחרי שהתשובה תתקבל משרת הממסר, הלקוח יפענח את התגובה. התגובה תכלול את כותרת התגובה Content-Type בפורמט ohttp-res.


auto ctx = std::move(ohttp_request).ReleaseContext(); auto ohttp_response = ohttp_client.DecryptObliviousHttpResponse("data included in body of http_response", ctx);

אחרי הפענוח של תגובת ה-OHTTP, צריך לפענח את הפלט באמצעות Binary HTTP באופן הזה.


auto bhttp_response = BinaryHttpResponse::Create(ohttp_response.GetPlaintextData()); if (bhttp_response.status_code() == 200) { auto http_response = bhttp_response.body(); auto response_headers = bhttp_response.GetHeaderFields(); }