利用保護隱私的加密技術實現匿名存取 Web
可以說自從 Web 出現,區分人類和傀儡程式的挑戰就隨之而來。從線上票務廠商到約會應用程式,再到電子商務和金融,您有很多合理的理由想知道造訪網站的是人還是機器。
遺憾的是,Web 的工具歷來都很笨拙,有時還會帶來糟糕的使用者體驗。CAPTCHA 就是一個令人討厭的解決方案,人類為此浪費了大量時間。一種更隱蔽但更具侵擾性的方法是 IP 追蹤,它使用 IP 位址來識別可疑流量並採取相應措施,但這也會帶來不可預知的後果。
然而,區分合法的人類請求和自動化傀儡程式的問題仍然一如既往地重要。這就是為什麼 Cloudflare 多年來一直投資於 Privacy Pass 通訊協定,這是一種依靠密碼學而不是簡單拼圖來建立使用者身分的新穎方法,同時為終端使用者提供簡化、保護隱私且通常無摩擦的體驗。
隨著 Chrome 和 Firefox 瀏覽器擴充功能的發佈,Cloudflare 於 2017 年開始支援 Privacy Pass。在 Cloudflare 上擁有網站的 Web 管理員將在 Cloudflare Dash 中啟用 Privacy Pass;在瀏覽器中安裝該擴充功能的使用者在存取啟用了 Privacy Pass 的網站上會看到更少的 CAPTCHA。
此後,Cloudflare 停止了 CAPTCHA 的發放,而 Privacy Pass 也取得了長足的進步。Apple 公司在其 Private Access Token 系統中使用了一個版本的 Privacy Pass, 該系統與裝置的安全飛地協同工作,以證明使用者為人類。Cloudflare 將 Privacy Pass 用作 Web 應用程式防火牆和傀儡程式管理產品中的一個重要訊號,這意味著數百萬個網站都原生提供 Privacy Pass。
在這篇文章中,我們將探討 Privacy Pass 通訊協定的最新變化。我們還很高興地推出 Privacy Pass 通訊協定最新 IETF 草案的公開實施,其中包括一組可用於實施 Privacy Pass 源站、發行者和證明者的開放原始碼範本。這些基於 Cloudflare Workers,是開始部署新 Privacy Pass 的最簡單方法。
為了補充更新的實施,我們發佈了新版本的 Privacy Pass 瀏覽器擴充功能(Firefox、Chrome),其名稱為:Silk - Privacy Pass Client。這些擴充功能的使用者將會在 Web 上看到更少的傀儡程式檢查,並將透過一組可信的證明者為隱私保護訊號的研究做出貢獻,這些證明者可以在擴充功能的設定面板中進行配置。
最後,我們將討論除了區分傀儡程式和人類流量外,Privacy Pass 還能如何用於其他一系列場景。
使用者須知
如果您使用在 Cloudflare 上控制 Privacy Pass 設定的 Privacy Pass API,則可以移除這些呼叫。由於我們的驗證平台現在已預設包含 Privacy Pass,因此不再需要此 API。出於對客戶的謹慎考慮,我們發佈了四個月後停用的通知。
如果您安裝了 Privacy Pass 擴充功能,它應該會在接下來的幾天內自動更新為 Silk - Privacy Pass Client(Firefox、Chrome)。我們對其進行了重新命名,以明確區分通訊協定本身和通訊協定的用戶端。
簡要歷史
在過去的十年中,我們看到了以隱私為核心的通訊協定的興起,包括 Oblivious HTTP (OHTTP)、分散式聚合通訊協定 (DAP) 和 MASQUE。這些通訊協定提高了線上瀏覽服務和與服務互動時的隱私性。透過保護使用者的隱私,這些通訊協定還要求源站和網站擁有者修改他們期望從使用者流量中收集的資料。這可能會導致他們重新考慮關於可疑流量的現有假設和緩解措施(例如 IP 篩選),這通常會產生意想不到的後果。
2017 年,Cloudflare 宣佈支援 Privacy Pass。在推出之初,這意味著提高 Web 使用者的內容可存取性,因為他們在瀏覽受 Cloudflare 保護的網站時會看到大量插頁(例如 CAPTCHA)。Privacy Pass 權杖向網站擁有者提供有關使用者能力的訊號,同時透過確保每個權杖兌換無法連結至其發行上下文,來保護他們的隱私。自那之後,在學術界和產業的努力下,該技術已成為數百萬人使用的成熟通訊協定。現有的瀏覽器擴充功能已獲得數十萬次下載。與此同時,Cloudflare 極大地改進了允許客戶驗證訪客的方式,在接收訊號方面更加靈活,並不再使用 CAPTCHA 作為二進位合法性訊號。
這項研究的部署擴大了用例,為不同類型的證明打開了大門。證明是支援事實的加密簽名資料點。這可以包括表明使用者已成功通過 CAPTCHA 的簽名權杖、讓使用者的硬體證明其未被篡改,或者證明者可以根據另一個資料來源驗證的一段資料。
例如,2022 年,Apple 硬體裝置開始向希望減少 CAPTCHA 顯示頻率的網站提供 Privacy Pass 權杖,使用硬體本身作為證明因素。CAPTCHA 提供者可以在向使用者顯示巴士和消防栓的影像之前請求 Private Access Token (PAT)。這種原生支援不需要安裝擴充功能,也不需要使用者採取任何動作,就能獲得更流暢、更私密的 Web 瀏覽體驗。
以下是我們所參與的通訊協定變更的簡要概述:
該時間表展示了密碼學的變化、社群的投入和產業的合作。這些變化有助於制定更好的 Web 標準,例如 VOPRF (RFC 9497) 或 RSA 盲簽名 (RFC 9474)。在接下來的內容中,我們將深入研究 Privacy Pass 通訊協定,以瞭解其來龍去脈。
現實生活中的匿名憑證
在更深入地解釋該通訊協定之前,讓我們打個比方。您正在參加一個音樂節,並以學生折扣線上購買了門票。當您到達檢票口時,工作人員會掃描您的門票,檢查您的學生身分,並給您一個黃色腕帶和兩張飲品券。
節日期間,進出都要出示腕帶。當朋友喊您去喝一杯時,您用飲品券付錢。一張為您自己付款,一張為您的朋友付款。您把飲品券交給調酒師,他們檢查飲品券,然後給您一杯飲料。使這種互動具有私密性的特點是,飲品券無法追溯到您本人或您的付款方式,但可以驗證它們是否未使用且可用於購買飲料。
在 Web 用例中,網際網路就是節日。當您到達網站門口時,代理程式會掃描您的請求,並為您提供一個工作階段 cookie 以及兩個 Privacy Pass 權杖。它們可能只給您一個權杖,也可能給您兩個以上,但在我們的範例中,「兩個權杖」是給定網站的政策。您可以使用這些權杖來證明您是人類、在某些網站上進行驗證,甚至確認您的硬體的合法性。
現在,您可能會問,既然這是我們已經使用多年的技術,為什麼還需要花哨的密碼學和標準化工作呢? 怎麼說呢,在現實世界的音樂節上,大多數人不會隨身攜帶影印機,但在網際網路上,複製權杖卻非常容易。例如,我們如何阻止人們兩次使用權杖?我們可以在每個權杖上標注一個唯一的號碼,並檢查它是否被使用了兩次,但如果這樣,檢票處的服務人員就有可能告訴調酒師,哪個號碼與哪個人有關。所以,我們需要密碼學。
當另一個網站向您發出驗證要求時,您可以提供您的 Privacy Pass 權杖,然後就可以檢視擁有美麗貓咪圖片的圖庫。與節日的不同之處在於,這個驗證要求可能是互動的,這類似于調酒師給您一張有編號的票,在獲得飲料之前必須由代理人簽名。網站擁有者可以驗證權杖是否有效,但無法追蹤使用者或將使用者連接回為他們提供 Privacy Pass 權杖的動作。在 Privacy Pass 術語中,您是用戶端,網站是源站,代理是證明者,酒吧是發行者。下一節將更詳細地介紹這些內容。
Privacy Pass 通訊協定
Privacy Pass 指定了用於建立和兌換匿名和可轉讓權杖的可擴展通訊協定。事實上,Apple 有自己的 Private Access Token (PAT) 實施,稍後我們將描述另一個使用 Silk 瀏覽器擴充功能的實施。鑒於 PAT 是第一個實施 IETF 定義的通訊協定,文獻中有時將 Privacy Pass 稱為 PAT。
該通訊協定是通用的,定義了四個組成部分:
用戶端:具有啟用 Privacy Pass 的瀏覽器的 Web 使用者代理程式。這可能是帶有 PAT 的 Apple 裝置,或者是安裝了 Silk 擴充功能的 Web 瀏覽器。通常,這是請求內容並被要求分享自身某些屬性的參與者。
源站:提供用戶端請求的內容。源站信任一個或多個發行者,並向用戶端提出 Privacy Pass 驗證要求。例如,Cloudflare 受管驗證是一個 Privacy Pass 源站,服務兩個 Privacy Pass 驗證:一個針對 Apple PAT 發行者,一個針對 Cloudflare Research 發行者。
發行者:根據受信任方(證明者或用戶端,具體取決於部署模型)的請求簽署 Privacy Pass 權杖。不同的發行者有自己的一組信任方,具體取決於他們所尋求的安全層級以及它們的隱私考慮。驗證裝置完整性的發行者應使用不同的方法來保證該屬性,以確認用戶端設定的多樣性。
證明者:驗證用戶端的屬性,並在滿足時請求發行者將簽名的 Privacy Pass 傳回用戶端。在為用戶端提供保證之前,證明者可能會要求用戶端完成特定任務。該任務可能是 CAPTCHA、位置檢查、年齡驗證或其他一些將產生單個二進位結果的檢查。然後,Privacy Pass 權杖將以不可連結的方式分享這個一位元資訊。
它們之間的互動如下圖所示。
讓我們透過一個範例來深入瞭解到底發生了什麼。使用者想要存取一個源站,例如 store.example.com。該網站過去曾遭受過攻擊或濫用,且正在使用 Privacy Pass 來幫助避免此類事件再次發生。為此,源站向用戶端傳回一個驗證請求:WWW-Authenticate: PrivateToken challenge="A==",token-key="B=="
。透過這種方式,源站發出訊號,表明它接受具有公開金鑰「B==」的發行者的權杖,以滿足驗證。該發行者反過來又相信信譽良好的證明者會透過 cookie、CAPTCHA、Turnstile 或 CAP 驗證等方式來保證用戶端不是攻擊者。出於我們範例的可存取性原因,我們假設用戶端可能更喜歡 Turnstile 方法。使用者的瀏覽器提示他們解決 Turnstile 驗證。成功後,它會使用該解決方案聯絡發行者「B==」,然後重放對 store.example.com 的初始請求,這次會傳送權杖標頭 Authorization: PrivateToken token="C=="
,即源站接受並向用戶端傳回所需的內容。就是這樣。
我們已經介紹了 Privacy Pass 驗證通訊協定。基本驗證 (RFC 7671) 要求您提供使用者名稱和密碼,而 PrivateToken 驗證方案允許瀏覽器更靈活地選擇檢查類型,同時保留隱私。源站 store.example.com 不知道您的證明方法,它們只是根據權杖發行者得知您是信譽良好的使用者。本著同樣的精神,發行者 "B==" 看不到您的 IP,也看不到您正在造訪的網站。發行和兌換之間的這種分離(也稱為不可連結性)使 Privacy Pass 具有私密性。
示範時間
為了將上述內容付諸實踐,讓我們看看該通訊協定如何與 Silk(一個提供 Privacy Pass 支援的瀏覽器擴充功能)配合使用。首先,下載相關的 Chrome 或 Firefox 擴充功能。
然後,前往 https://demo-pat.research.cloudflare.com/login。該頁面傳回一個不存在的 401 Privacy Pass 權杖。事實上,源站希望您執行 PrivateToken 驗證。如果您沒有安裝擴充功能,流程將在此處停止。如果您安裝了擴充功能,則擴充功能將協調為您獲取源站要求的權杖所需的流程。
安裝擴充功能後,您將被導向到一個新索引標簽 https://pp-attester-turnstile.research.cloudflare.com/challenge。這是由證明者提供的頁面,能夠向您提供源站要求的發行者簽署的權杖。在這種情況下,證明者會檢查您是否能夠解決 Turnstile 驗證。
點擊一下,就可以了。Turnstile 驗證解決方案會傳送給證明者,證明者在驗證後會傳回一個來自所要求發行者的權杖。該頁面出現的時間很短,因為一旦擴充功能獲得了權杖,就不再需要驗證頁面了。
現在,擴充功能獲得了源站要求的權杖,它會第二次傳送您的初始請求,並附上一個包含有效的發行者 PrivateToken 的授權標頭。通過驗證後,源站會允許您使用有效的 200 Privacy Pass 權杖進入!
如果您想查看幕後情況,可以滑鼠右鍵按一下擴充功能標誌,然後轉到偏好設定/選項頁面。它包含擴充功能信任的證明者清單,每行一個。您可以新增自己的證明方法(下文介紹的 API)。這允許用戶端決定其偏好的證明方法。
Privacy Pass 通訊協定——延伸
Privacy Pass 通訊協定是新通訊協定,尚未成為標準,這意味著並非所有平台都支援該通訊協定。為了在現有標準提案的基礎上提高靈活性,我們引入了兩種機制:用於證明者的 API 和用於 Web 用戶端的重放 API (replay API)。證明者 API 允許開發人員構建新的證明方法,只需提供其 URL 即可與 Silk 瀏覽器擴充功能進行互動。Web 用戶端的重放 API 是一種機制,使網站能夠與擴充功能配合,使 PrivateToken 驗證在具有 Chrome 使用者代理程式的瀏覽器上工作。
由於您的電腦上可能支援多個證明者,因此您的用戶端需要根據所要求的發行者瞭解應使用哪個證明者。如前所述,作為用戶端,您不會直接與發行者通訊,因為您不一定知道他們與證明者的關係,所以您無法獲取其公開金鑰。為此,證明者 API 公開了所述證明者可透過端點存取的所有發行者:/v1/private-token-issuer-directory。這樣,您的用戶端在觸發驗證之前會選擇合適的證明者——與源站信任的發行者相關的證明者。
此外,我們還提出了重放 API。其目標是,如果第一次回應提出 Privacy Pass 驗證要求,則允許用戶端第二次獲取資源。有些平台會自動執行此操作,例如 Firefox 上的 Silk,但有些平台不會。以 Silk Chrome 擴充功能為例,該擴充功能在支援 manifest v3 時無法封鎖請求,只能在 onAuthRequired 擴充功能事件中支援基本驗證。Privacy Pass 驗證方案建議傳送一次請求以獲得驗證要求,然後傳送第二次以獲取實際資源。在對源站發出這兩個請求之間的時間裡,平台會協調權杖的發行。為了讓用戶端瞭解此過程的狀態,我們在 private-token-client-replay: UUID header
。透過使用平台定義的端點,該 UUID 會通知 Web 用戶端當前的驗證狀態:待處理、已完成、未找到。
要進一步瞭解當今如何使用這些方法以及如何部署自己的證明方法,請繼續閱讀。
當今的人們是如何使用 Privacy Pass 的?
如上一節所示,Privacy Pass 圍繞四個部分構建:源站、用戶端、證明者、發行者。這就是我們建立四個存放庫的原因: cloudflare/pp-origin、cloudflare/pp-browser-extension、cloudflare/pp-attester、cloudflare/pp-issuer。此外,還提供底層加密庫:cloudflare/privacypass-ts、cloudflare/blindrsa-ts 和 cloudflare/voprf-ts。在本節中,我們將根據您的用例深入探討如何使用其中的每一項。
注意:以下所有範例均使用 JavaScript 設計,且針對 Cloudflare Workers。Privacy Pass 也可以用其他語言實施,並可根據您的需要部署設定。
作為源站——網站擁有者、服務提供者
您是人們非常依賴的線上服務提供者(例如健康或資訊服務)。您希望為使用者提供私人支付選項,以維護使用者隱私。您只有一個訂閱層級,每月 10 美元。您聽說有人在製作保護隱私的應用程式,因此希望使用最新版本的 Privacy Pass。
要使用您的服務,使用者必須證明他們已透過自己選擇的支付提供者(您認為可以接受的)支付了服務費用。該付款提供者確認付款,並為使用者申請一個權杖以存取服務。序列圖如下:
要在 Workers 中實施該功能,我們需要使用 @cloudflare/privacypass-ts
庫,可透過執行以下程式碼來安裝:
本節將著重介紹源站的工作。我們假定您已經安裝並執行了發行者,這將在後面的章節中介紹。
npm i @cloudflare/privacypass-ts
源站定義了兩個流程:
使用者兌換權杖
使用者請求發放權杖
import { Client } from '@cloudflare/privacypass-ts'
const issuer = 'static issuer key'
const handleRedemption => (req) => { const token = TokenResponse.parse(req.headers.get('authorization')) const isValid = token.verify(issuer.publicKey) }
const handleIssuance = () => { return new Response('Please pay to access the service', { status: 401, headers: { 'www-authenticate': 'PrivateToken challenge=, token-key=, max-age=300' } }) }
const handleAuth = (req) => { const authorization = req.headers.get('authorization') if (authorization.startsWith(
PrivateToken token=
)) { return handleRedemption(req) } return handleIssuance(req) }export default { fetch(req: Request) { return handleAuth(req) } }
從使用者的角度來看,開銷微乎其微。他們的用戶端(可能是 Silk 瀏覽器擴充功能)會收到一個 WWW-Authenticate 標頭,其中包含簽發權杖所需的資訊。然後,根據他們的用戶端設定,他們會被帶到所選擇的支付提供者處,以驗證對服務的存取權。
import { Client } from '@cloudflare/privacypass-ts'
const issuer = 'static issuer key'
const handleRedemption => (req) => {
const token = TokenResponse.parse(req.headers.get('authorization'))
const isValid = token.verify(issuer.publicKey)
}
const handleIssuance = () => {
return new Response('Please pay to access the service', {
status: 401,
headers: { 'www-authenticate': 'PrivateToken challenge=, token-key=, max-age=300' }
})
}
const handleAuth = (req) => {
const authorization = req.headers.get('authorization')
if (authorization.startsWith(`PrivateToken token=`)) {
return handleRedemption(req)
}
return handleIssuance(req)
}
export default {
fetch(req: Request) {
return handleAuth(req)
}
}
在成功回應 PrivateToken 驗證後,工作階段就建立起來了,傳統的 Web 服務流程繼續進行。
作為證明者——CAPTCHA 提供者、驗證提供者
您是新證明方法的作者,例如 CAP、新的 CAPTCHA 機制或驗證 cookie 同意的新方法。您知道網站擁有者已經使用 Privacy Pass 在用戶端觸發此類驗證,並且發行者願意信任您的方法,因為它保證了高安全層級。此外,由於 Privacy Pass 通訊協定,您永遠不會看到您的證明正在用於哪個網站。
因此,您決定將您的證明方法作為 Privacy Pass 證明者公開。擁有公開金鑰 B== 的發行者信任您,這就是您要向其請求權杖的發行者。您可以使用下面的「是/否證明者」進行檢查,其程式碼位於 Cloudflare Workers 領域上
上面的驗證方法只是檢查使用者是否選擇了「是」。您的方法可能更複雜,但包裝是不變的。
const ISSUER_URL = 'https://pp-issuer-public.research.cloudflare.com/token-request'
const b64ToU8 = (b) => Uint8Array.from(atob(b), c => c.charCodeAt(0))
const handleGetChallenge = (req) => {
return new Response(`
<html>
<head>
<title>Challenge Response</title>
</head>
<body>
<button onclick="sendResponse('Yes')">Yes</button>
<button onclick="sendResponse('No')">No</button>
</body>
<script>
function sendResponse(choice) {
fetch(location.href, { method: 'POST', headers: { 'private-token-attester-data': choice } })
}
</script>
</html>
`, { status: 401, headers: { 'content-type': 'text/html' } })
}
const handlePostChallenge = (req) => {
const choice = req.headers.get('private-token-attester-data')
if (choice !== 'Yes') {
return new Response('Unauthorised', { status: 401 })
}
// hardcoded token request
// debug here https://pepe-debug.research.cloudflare.com/?challenge=PrivateToken%20challenge=%22AAIAHnR1dG9yaWFsLmNsb3VkZmxhcmV3b3JrZXJzLmNvbSBE-oWKIYqMcyfiMXOZpcopzGBiYRvnFRP3uKknYPv1RQAicGVwZS1kZWJ1Zy5yZXNlYXJjaC5jbG91ZGZsYXJlLmNvbQ==%22,token-key=%22MIIBUjA9BgkqhkiG9w0BAQowMKANMAsGCWCGSAFlAwQCAqEaMBgGCSqGSIb3DQEBCDALBglghkgBZQMEAgKiAwIBMAOCAQ8AMIIBCgKCAQEApqzusqnywE_3PZieStkf6_jwWF-nG6Es1nn5MRGoFSb3aXJFDTTIX8ljBSBZ0qujbhRDPx3ikWwziYiWtvEHSLqjeSWq-M892f9Dfkgpb3kpIfP8eBHPnhRKWo4BX_zk9IGT4H2Kd1vucIW1OmVY0Z_1tybKqYzHS299mvaQspkEcCo1UpFlMlT20JcxB2g2MRI9IZ87sgfdSu632J2OEr8XSfsppNcClU1D32iL_ETMJ8p9KlMoXI1MwTsI-8Kyblft66c7cnBKz3_z8ACdGtZ-HI4AghgW-m-yLpAiCrkCMnmIrVpldJ341yR6lq5uyPej7S8cvpvkScpXBSuyKwIDAQAB%22
const body = b64ToU8('AALoAYM+fDO53GVxBRuLbJhjFbwr0uZkl/m3NCNbiT6wal87GEuXuRw3iZUSZ3rSEqyHDhMlIqfyhAXHH8t8RP14ws3nQt1IBGE43Q9UinwglzrMY8e+k3Z9hQCEw7pBm/hVT/JNEPUKigBYSTN2IS59AUGHEB49fgZ0kA6ccu9BCdJBvIQcDyCcW5LCWCsNo57vYppIVzbV2r1R4v+zTk7IUDURTa4Mo7VYtg1krAWiFCoDxUOr+eTsc51bWqMtw2vKOyoM/20Wx2WJ0ox6JWdPvoBEsUVbENgBj11kB6/L9u2OW2APYyUR7dU9tGvExYkydXOfhRFJdKUypwKN70CiGw==')
// You can perform some check here to confirm the body is a valid token request
console.log('requesting token for tutorial.cloudflareworkers.com')
return fetch(ISSUER_URL, {
method: 'POST',
headers: { 'content-type': 'application/private-token-request' },
body: body,
})
}
const handleIssuerDirectory = async () => {
// These are fake issuers
// Issuer data can be fetch at https://pp-issuer-public.research.cloudflare.com/.well-known/private-token-issuer-directory
const TRUSTED_ISSUERS = {
"issuer1": { "token-keys": [{ "token-type": 2, "token-key": "A==" }] },
"issuer2": { "token-keys": [{ "token-type": 2, "token-key": "B==" }] },
}
return new Response(JSON.stringify(TRUSTED_ISSUERS), { headers: { "content-type": "application/json" } })
}
const handleRequest = (req) => {
const pathname = new URL(req.url).pathname
console.log(pathname, req.url)
if (pathname === '/v1/challenge') {
if (req.method === 'POST') {
return handlePostChallenge(req)
}
return handleGetChallenge(req)
}
if (pathname === '/v1/private-token-issuer-directory') {
return handleIssuerDirectory()
}
return new Response('Not found', { status: 404 })
}
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request))
})
「是/否證明者」範例螢幕擷取畫面
由於使用者可能為給定發行者設定了多個證明者,因此我們建議您的證明者實施一個額外的端點,以公開您所聯絡的發行者的金鑰。您可以在 Cloudflare Workers 領域上嘗試此程式碼。
您有一個可直接與 Silk 瀏覽器擴充功能(Firefox、Chrome)一起使用的證明者。當您進行部署時,它也可以直接整合到您的應用程式中。
const handleIssuerDirectory = () => {
const TRUSTED_ISSUERS = {
"issuer1": { "token-keys": [{ "token-type": 2, "token-key": "A==" }] },
"issuer2": { "token-keys": [{ "token-type": 2, "token-key": "B==" }] },
}
return new Response(JSON.stringify(TRUSTED_ISSUERS), { headers: { "content-type": "application/json" } })
}
export default {
fetch(req: Request) {
const pathname = new URL(req.url).pathname
if (pathname === '/v1/private-token-issuer-directory') {
return handleIssuerDirectory()
}
}
}
如果您想擁有更進階的證明者和部署管道,請查看 cloudflare/pp-attester 範本。
作為發行者——基金會、財團
我們已經多次提到發行者。發行者的作用是選擇一組它希望與之合作的證明者,並將自己的公開金鑰傳遞給源站。發行者的整個加密行為由 IETF 草案指定。與具有自由裁量行為的用戶端和證明者相比,發行者是完全標準化的。它們的機會是選擇一個對於源站來說足夠強的訊號,同時保護用戶端的隱私。
Cloudflare Research 營運著一個用於實驗目的公用發行者,在 https://pp-issuer-public.research.cloudflare.com 上使用。這是立即開始試用 Privacy Pass 的最簡單解決方案。一旦成熟,您可以考慮加入生產發行者,或部署自己的發行者。
要部署自己的發行者,您應該:
使用您的 Cloudflare Workers 帳戶 ID 和區域 ID 更新 wrangler.toml。開放原始碼發行者 API 的工作原理如下:
git clone github.com/cloudflare/pp-issuer
/.well-known/private-token-issuer-directory 傳回發行者設定。請注意,它不會公開非標準 token-key-legacy
/token-request 傳回一個權杖。應對該端點進行門控(例如透過 Cloudflare Access)以僅允許受信任的證明者呼叫它
/admin/rotate 產生新的公開金鑰。這只能由您的團隊存取,並在發行者可用之前呼叫。
然後,wrangler
發佈 ,您就可以上線證明者了。
Silk 擴充功能的發展
就像通訊協定一樣,證明 Privacy Pass 可行的瀏覽器技術也發生了變化。五年來,該通訊協定與 Chrome 和 Firefox 的瀏覽器擴充功能一起部署。2021 年,Chrome 發佈了新版本的擴充功能設定,通常稱為 Manifest v3 (MV3)。Chrome 還開始對所有新發佈的擴充功能強制執行此新設定。
Privacy Pass _擴充功能_基於商定的 Privacy Pass 驗證通訊協定。根據 Chrome 的 API 文件,我們應該能夠使用 onAuthRequired 事件。但是,由於 PrivateToken 驗證尚未成為標準,因此瀏覽器沒有為擴充功能提供掛鉤來向該事件新增邏輯。
影像根據 Google For Developers 提供的 CC-BY-SA 4.0 提供
我們決定使用的方法是定義用戶端重放 API。當回應帶有 401 WWW-Authenticate PrivateToken 時,瀏覽器會允許其通過,但會觸發私人權杖兌換流程。當擷取到權杖時,原始頁面會收到通知,並重放請求。對於第二次請求,瀏覽器能夠附加授權權杖,然後請求成功。這是用戶端執行的主動重放,而不是平台完成的透明重放。GitHub 上提供了規範。
我們期待著該標準取得進展,並簡化專案的這一部分。這應該會提高證明方法的多樣性。正如我們將在下一節中看到的,這是識別可被源站利用的新訊號的關鍵。
匿名憑證標準
IP 仍然是反濫用系統中的一個關鍵識別碼。與此同時,IP 指紋識別技術已成為一個更大的問題,平台已開始取消其中一些追蹤使用者的方式。為了使反濫用系統不依賴 IP,同時確保使用者隱私,Privacy Pass 提供了合理的替代方案來處理潛在的濫用或可疑流量。證明方法各不相同,可以根據特定部署的需要進行選擇。例如,Apple 公司在使用 Privacy Pass 作為 iCloud Private Relay 的授權技術時, 決定用硬體支援他們的證明。另一個範例是 Cloudflare Research,它決定部署 Turnstile 證明者,作為 Cloudflare 驗證平台成功解決驗證問題的訊號。
在所有這些部署中,類似 Privacy Pass 的技術允許分享特定的資訊。您的裝置不會僅僅透過連接到網站來分享您的位置、過去的流量,甚至是您的姓名和電話號碼,而是能夠以保護隱私的方式向第三方證明特定資訊。哪些使用者資訊和證明方法足以防止濫用是一個懸而未決的問題。我們希望透過發佈這款軟體來增強研究人員的能力,幫助他們找到答案。這可以透過新的實驗來實現,例如測試新的證明方法,或透過提供特定資訊共用的框架來促進其他隱私通訊協定。
未來建議
正如我們期待最新版本的 Privacy Pass 能帶來新的應用和想法,我們也期待該標準和使用該標準的用戶端能進一步發展。Privacy Pass 的未來發展有望涵蓋大量權杖發行和限速等主題。在我們構建和部署這一版本的 Privacy Pass 的過程中,我們遇到了一些限制,我們希望將來也能解決這些限制。
證明者和發行者之間的分工,以及源站和發行者之間、發行者和證明者之間的信任關係的明確方向,使得對失信影響的推理變得清晰。發行者可以信任多個證明者,但由於許多當前的 Privacy Pass 部署無法識別導致發行的證明者,因此對一個證明者失去信任,將使所有信任該證明者的發行者發行的所有權杖都變得不受信任。這是因為無法判斷哪個證明者參與了發行過程。這是否會促進證明者和發行者之間的一對一通訊,讓我們等待時間來揭曉答案。
開發一個同時受 Firefox 和 Chrome 瀏覽器支援的瀏覽器擴充功能,有時可能需要相當複雜(且脆弱)的程式碼路徑。Privacy Pass 通訊協定似乎非常適合 webRequest.onAuthRequired 瀏覽器事件的擴充功能。正如 Privacy Pass 在 WWW-Authenticate HTTP 標頭中顯示為備用驗證訊息一樣,瀏覽器也可以觸發 onAuthRequired 事件以進行私有權杖驗證,並在 onAuthRequired 事件中包含並允許請求封鎖支援。這似乎是該事件使用方式的自然演變,目前僅限於現在已經相當老舊的基本驗證。
結論
Privacy Pass 為 Web 長期面臨的挑戰之一——匿名驗證——提供了解決方案。透過利用加密技術,該通訊協定允許網站從使用者那裡獲取所需的資訊,並且僅獲取這些資訊。它已經被數百萬人使用,能夠無阻礙地幫助區分人類請求和自動化傀儡程式請求,同時保護隱私。我們對該通訊協定廣泛且不斷增長的採用情況感到興奮,也很期待該最新版本可能帶來的新穎用例。
Cloudflare 的 Privacy Pass 實施可在 GitHub 上獲取,並且符合該標準。我們對一組範本進行了開源,這組範本可用於實施 Privacy Pass 源站、發行者和證明者,它們利用 Cloudflare Workers 快速啟動和執行。
如果想要立即嘗試 Privacy Pass 的人,請立即下載 Silk - Privacy Pass Client 瀏覽器擴充功能(Firefox、Chrome、GitHub),並在瀏覽 Web 的過程中體驗更少的傀儡程式檢查吧。