Overview

安全瀏覽介面的 HTTP Gateway API

注意:這份文件目前仍在開發階段,希望不久後也能有所改善。

Safe Browsing Oblivious HTTP Gateway API 是以 IETF RFC 通訊協定為基礎,建構在名為 Oblivious HTTPRFC 9458 上的隱私權保護 API。

總覽

安全瀏覽 Oblivious HTTP Gateway API 是一項 Google 服務,可讓用戶端應用程式根據 Google 持續更新的不安全網頁資源清單來檢查網址,並增添額外的隱私保護機制。

這會透過稱為 Oblivious HTTP (或簡稱 OHTTP) 的輕量通訊協定來達成。安全瀏覽用戶端可透過這項無狀態通訊協定存取 Google 安全瀏覽第 5 版 API,取得完善的保護措施,在不影響使用者的情況下隱私權。

注意: Google 安全瀏覽第 4 版 API 無法透過這項服務存取。

安全瀏覽顯而易見的 HTTP 通訊協定

RFC 通訊協定

顯而易見的 HTTP 是 RFC 9458 中定義的輕量通訊協定,可用於加密用戶端的 HTTP 訊息並傳送至目標伺服器。此方法使用信任的轉發服務,以減輕目標伺服器使用中繼資料 (例如 IP 位址和連線資訊) 來進行用戶端識別的使用,在一般 HTTP/S 通訊協定之上提供隱私及安全性。此通訊協定使用 RFC 9292 中定義的二進位 HTTP 對 HTTP 要求/回應進行編碼/解碼。

大致上來說,Relay 位於用戶端和閘道資源之間,會移除所有用戶端 ID (包括 IP 位址等隱私權敏感屬性) 來透過 Proxy 處理用戶端流量,進而有效將傳入的 HTTP 要求去識別化。OHTTP 的附加好處是所有要求都會經過端對端加密處理Relay 不會顯示安全瀏覽查詢 (例如網址運算式遭截斷的雜湊)。如需 Chrome 的實作範例,請參閱blogpost

服務的整體架構。
:OHTTP 流程。

客戶可以選擇任何 Relay 提供者 (例如,Fastly) 以整合服務。Relay 必須搭配以下授權範圍使用 Oauth 2.0 驗證,才能存取服務。


// OAuth Authorization scope: https://www.googleapis.com/auth/3p-relay-safe-browsing
API 端點
OHTTP 公開金鑰

這個端點會提供 RFC 9458 中指定的 OHTTP 公開金鑰設定,用戶端將使用這組設定加密 OHTTP 要求。


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

上述 API 金鑰並非強制性必要。伺服器「不會」依據提供的 API 金鑰變更 OHTTP 公開金鑰。用戶端可藉由使用不同的有效 API 金鑰來存取這個端點,或是完全不使用 API 金鑰,並檢查回應的確實包含相同的 OHTTP 公開金鑰,藉此證明用戶端是如此。不過,為了方便偵錯,建議您使用 API 金鑰。這可讓用戶端在 Google Cloud 控制台上查看要求數量等統計資料。如果用戶端打算提供 API 金鑰,請參閱這份說明文件,瞭解如何設定 API 金鑰。

如「隱私權建議」一節所述,為了達成金鑰一致性目標,客戶供應商建議設定集中化金鑰分配基礎架構,以便從這個端點擷取金鑰,然後發布到用戶端應用程式。

根據金鑰管理指南,金鑰會定期在伺服器上輪替。用戶端應頻繁重新整理金鑰 (即多次擷取及更新金鑰本機副本),以免解密失敗。

用戶端每天應重新整理 (擷取及更新) 公開金鑰。如果您採用集中發布機制,請務必每天擷取並分配金鑰一次。

OHTTP 封裝要求

這個端點會透過執行要求解密,在 HTTP 回應中加密要轉回 Relay 的 OHTTP 回應,藉此提供該要求包含在 POST 要求 HTTP 主體中的 OHTTP 要求。用戶端必須在 HTTP POST 要求中納入 Content-Type 要求標頭做為 message/ohttp-req


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

注意:按照 RFC 指南規定,使用 RFC 9292 通訊協定,將內部要求編碼 (請參閱 V5 說明文件,瞭解如何建構安全瀏覽要求)。

用戶端程式庫

Google Quiche 提供適用於 OHTTPBHTTP 通訊協定的用戶端實作方式。建議用戶端使用這些程式庫。請參閱下方的虛擬程式碼,瞭解如何建立 OHTTP 要求,以存取 API。

用戶端導入範例

用戶端會從公開金鑰端點擷取過時的 HTTP 公開金鑰。接著像這樣初始化 quiche OHTTP 金鑰設定,並初始化 quiche 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();

收到 Relay 的回應後,用戶端會將回應解密。回應中會包含 ohttp-resContent-Type 回應標頭。


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

成功解密 OHTTP 回應之後,請類似使用二進位 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(); }