加密往往是安全性的一大主題,但也十分重視隱私權。加密的目標是防止他人讀取加密資訊,但要防止他人讀取您的資訊,這是防止資訊外洩的方法之一。使用者通常能夠做到的程度通常有限,但您可以提供協助做為他們所用服務的供應商,以保護他們的資料。
目前有三種方法採用加密機制來保護使用者隱私:傳輸中的資料加密、靜態資料加密,以及端對端加密:
- 傳輸中資料加密會將使用者和網站之間的資料加密,也就是 HTTPS。您可能已為網站設定了 HTTPS,但您是否確定傳輸至網站中的「所有」資料都會經過加密?這就是重新導向和 HSTS 的適用情況,下文將說明這些方法,應包含在 HTTPS 設定中。
- 靜態資料加密:對儲存在伺服器上的資料進行加密。這有助於防止資料侵害事件,是安全性方面相當重要的一環。
- 端對端加密是指在用戶端將資料加密後,才會傳輸至您的伺服器。這不僅能保護使用者資料,還能儲存使用者資料,但無法讀取。這種實作方式難以實作,也不適用於所有類型的應用程式,但由於任何人都能查看使用者資料,因此有助於保護使用者隱私。
HTTPS
第一項做法是透過 HTTPS 提供網路服務。您很可能已經完成這項操作,但如果不會是重要步驟,HTTPS 是 HTTP,瀏覽器用來從伺服器要求網頁,但使用 SSL 加密的通訊協定。 也就是說,外部攻擊者無法讀取或乾擾傳送者 (使用者) 和收件者 (您) 之間的 HTTPS 要求,因為這類要求都經過加密,因此無法讀取或變更內容。這種做法在傳輸過程中會加密處理,也就是資料從使用者轉移給您,或在您提供給使用者時。傳輸過程中的 HTTPS 加密也會防止使用者的網際網路服務供應商 (ISP) 或所用 Wi-Fi 的供應商,在與服務的關係期間讀取他們傳送給你的資料。也可能會影響您服務的功能;許多使用方式的現有 JavaScript API 都需要透過 HTTPS 提供網站。MDN 提供更詳盡的清單,但受安全環境保護的 API 包括服務工作站、推播通知、網路共用和網路加密,以及部分裝置 API。
如要透過 HTTPS 提供網站,您必須具備 SSL 憑證。這些映像檔可透過 Let's Encrypt 免費建立,或可能由代管服務提供 (如果您使用的話)。此外,您也可以使用第三方服務「代理」您的網路服務,並可提供 HTTPS、快取和 CDN 服務。這類服務有許多範例,例如 Cloudflare 和 Fastly,具體取決於您目前的基礎架構。以往,HTTPS 可能十分繁瑣或花費昂貴,因此通常只用於付款頁面或特別是安全來源。不過,開放自由使用的憑證、標準改善和日益普及的瀏覽器已經消除了這些障礙。
正確做法
- 無論您選擇哪種方式,都請在伺服器上啟用 HTTPS。
- 建議您在伺服器前方使用 Proxy,例如 Cloudflare (httpsiseasy.com/ 說明瞭相關流程)。
- Let's Encrypt 會逐步引導您建立自己的 Let's Encrypt SSL 憑證。
- 或者,直接使用 OpenSSL 建立您自己的憑證,並由您選擇的憑證授權單位 (CA) 簽署 (如需詳細說明,請參閱「啟用 HTTPS」一節)。
該選擇哪種方法,取決於業務優缺點。設定方式是讓第三方管理 SSL 連線,這是設定方法最簡單的方法,且會同時提供負載平衡、快取和分析等其他好處。但我們也向第三方提供明顯的控管功能,並可避免依賴於其服務 (以及可能的付款,視您使用的服務和流量層級而定)。
產生憑證並由 CA 簽署是安全資料傳輸層 (SSL) 程序的執行方式。不過,如果您的供應商支援 Let's Encrypt,或者您的伺服器團隊技術面夠高且免費,即可使用 Let's Encrypt。此外,如果您使用比雲端託管更高的層級,供應商也會提供安全資料傳輸層 (SSL) 式服務,因此請另行檢查。
為什麼要
安全性是隱私權故事的一部分:能證明您能避免使用者資料受到干擾,有助於建立信任感。如果您未使用 HTTPS,瀏覽器也會將您的網站標記為「不安全」,且已經存在一段時間。 現有的 JavaScript API 通常僅適用於 HTTPS 網頁 (「安全來源」)。 還可以防止使用者看到網際網路服務供應商 (ISP) 查看網路用量。 這是最佳做法,因此幾乎沒有必要立即為網站使用 HTTPS。
瀏覽器顯示 HTTP (不安全) 網頁的方式
重新導向至 HTTPS
如果您的網站同時存取 http: 和 https: 網址,您必須將所有 HTTP 網址存取重新導向至 https。基於上述原因,這種做法也能確保你的網站不會在 whynohttps.com 熱門網站顯示。 要怎麼做,有很大取決於基礎架構。如果您是託管於 AWS,可以使用傳統版或應用程式負載平衡器。Google Cloud 也是類似的服務,在 Azure 中,您可以建立 Front Door;在 Node 中,使用 Express check for request.secure;在 Nginx 中,找出所有通訊埠 80 並傳回 301;在 Apache 中則使用 RewriteRule。如果您使用代管服務,這些代管服務可能會自動為您處理重新導向至 HTTPS 網址:Netlify、Firebase 和 GitHub 頁面等等。
HTTPS 嚴格傳輸安全性
HSTS 是「HTTP Strict-Transport-Security」的縮寫,讓瀏覽器永久啟用 HTTPS,不再用於您的服務。 一旦您對遷移至 HTTPS 感到滿意,或執行上述操作後,即可在傳出回應中加入 Strict-Transport-Security HTTP 回應標頭。之前存取過網站的瀏覽器會記錄有這個標頭,之後就算您要求 HTTP,瀏覽器也能自動將這個網站以 HTTPS 形式存取。這可避免重新導向進行上述的重新導向:就像瀏覽器會在無訊息中「升級」服務使用 HTTPS 的所有要求。
同樣地,您可以在網頁同時提供 upgrade-Insecure-Requests 標頭。這會有別於 Strict-Transport-Security
,但與 Strict-Transport-Security
有關的內容。如果新增 Upgrade-Insecure-Requests: 1
,則即使連結為 http,系統仍會要求從這個網頁指向其他資源 (圖片、指令碼) 的要求。但是瀏覽器不會重新要求網頁本身為 https,瀏覽器也不會記住密碼。實際上,如果您要將含有許多連結的現有網站轉換為 HTTPS,並將連結網址轉換為內容中的連結網址並不容易,但建議您盡可能變更內容,升級不安全要求就十分實用。
HSTS 主要是一項安全性功能,能夠將網站「鎖定」至 HTTPS,供曾經造訪的使用者使用。不過如上所述,HTTPS 可保護隱私權,HSTS 則適合用於 HTTPS。同樣地,如果您要更新所有內容,則不一定要使用「升級不安全要求」,但這是一種實用的「帶頭式」方法,可進一步強化防護機制,確保您的網站一律採用 HTTPS。
正確做法
在傳出回應中加入 HSTS 標頭:
Strict-Transport-Security: max-age=300; includeSubDomains
max-age 參數指定瀏覽器應記住並強制執行 HTTPS 升級的時間 (以秒為單位)。 (我們在這裡設定為 300 秒,例如 5 分鐘)。最後會希望這個值是 6,3072,000 (也就是兩年),這是 hstspreload.org 建議的數值,但如果發生問題,會很難復原。因此,建議您先將此值設為較小的數字 (300),然後進行測試以確認沒有任何毀損,然後再分階段增加數量。
將 Upgrade-Insecure-Requests
標頭新增至傳出回應:
Upgrade-Insecure-Requests: 1
Content-Security-Policy: upgrade-insecure-requests
端對端加密
保護使用者資料的一個隱密方法,就是不要對使用者 (包括您) 以外的人顯示。這有助於增進您的信任感:如果您沒有可用的使用者資料,就會確定 Google 無法存取他們想要的方案。要達到這個目標,其中一個方法是儲存用戶端的所有內容,防止使用者資料外洩。這個方法雖然可行,但只有用戶端的應用程式有限制:瀏覽器資料儲存空間可能會受到限制,且部分瀏覽器可能會在沒有警告的情況下遭到清除。此外,在筆電和手機等兩部裝置上存取資料也很困難或根本無法。因此,我們建議照常將資料傳送至伺服器,但以使用者只會知道的金鑰來加密,這樣伺服器就無法存取該金鑰 (因為無法解密),但可以儲存資料。
運作方式
這個方法經常用於訊息應用程式,也就是「端對端加密」(e2e)。如此一來,知道彼此金鑰的兩位使用者可以對自己的訊息進行加密和解密,並透過訊息傳遞供應商傳送這些訊息,但訊息提供者 (沒有金鑰) 就無法讀取訊息。大部分的應用程式都不是訊息應用程式,但您可以結合兩種做法:僅用戶端資料儲存庫、資料加密與用戶端已知的金鑰,以便在本機儲存資料,同時將資料加密傳送至伺服器。請務必瞭解這種方法有其限制:並非所有服務都適用,特別是如果服務供應商需要存取使用者儲存的內容,則無法使用這項功能。如本系列文章第 2 部分所述,最好遵循資料最小化原則,請盡可能避免收集資料。如果使用者需要資料儲存空間,但您不需要存取該資料來提供服務,建議採用端對端加密。如果您提供服務,必須要能查看使用者所儲存的內容來提供服務,則不適合使用端對端加密。但是,如果不是的話,則可以讓網路服務的用戶端 JavaScript 將傳送至伺服器的任何資料加密,並解密收到的任何資料。
範例:Excalidraw
Excalidraw 會執行這項操作,並在網誌文章中說明操作方式。這個向量繪圖應用程式會在伺服器上儲存繪圖,並以隨機選擇的金鑰加密。Excalidraw 可運用相對少量程式碼實作此端對端加密的原因之一,就是現在使用 window.crypto 在瀏覽器中建構加密程式庫,這是所有新式瀏覽器支援的一組 JavaScript API。密碼編譯很困難,實作演算法也經常遇到許多極端情況。透過瀏覽器進行繁雜的工作,可讓網頁開發人員更容易存取加密資料,因此也能更輕鬆地透過加密資料實施隱私保護。如同 Excalidraw 在寫入中所描述的,加密金鑰是保存在用戶端上,因為它是網址片段的一部分:當瀏覽器造訪網址 https://example.com/path?param=1#fraghere
時,網址的路徑 (/path
) 和參數 (param=1
) 會傳遞至伺服器 (example.com
),但片段 (fraghere
) 不會被記錄,因此伺服器也永遠不會顯示。這表示即使加密資料通過伺服器,加密金鑰不會發揮作用,並能保護隱私,因為資料會經過端對端加密處理。
限制
這種加密使用者資料的方法並非百分之百準確。這將成為您使用者的信任立場,但無法完全取代。使用者仍必須相信您的服務,因為您隨時都能將用戶端 JavaScript 替換成某些不太容易加密的 JavaScript。雖然使用者有可能能夠偵測您使用的網站是否完成該動作,但這非常困難,因此使用者仍然必須相信他們不會輕易相信資料。
另請注意,端對端加密的目標之一是禁止網站擁有者 (也就是網站擁有者) 讀取資料。雖然這有助於保護隱私權,但也代表發生問題時無法提供協助。基本上,使用端對端加密的服務會讓使用者自行管理加密金鑰。(這可能不是很明顯或隱含著的,但必須有人知道金鑰;若資料不是由您公開,那就不是您。)如果這些金鑰遺失,您就能夠不必採取任何因應措施,使用這些金鑰加密的任何資料可能也會遺失。在隱私權和可用性之間取得良好平衡:使用加密機制保障資料不外洩,並避免要求使用者以安全的方式管理自己的金鑰。
靜態資料加密
除了加密傳輸中使用者資料之外,您也必須考慮加密儲存在伺服器上的資料。這有助於防範資料侵害事件,因為任何人都能在未經授權的情況下,存取您儲存的資料,而或許不會有金鑰解密。有兩種方法可以加密靜態資料,方法有兩種:您新增的加密機制,以及由雲端儲存空間供應商新增的加密機制 (如果您使用的是雲端儲存空間供應商服務)。儲存空間供應商加密功能對於透過軟體發生資料侵害事件提供多餘的保護措施 (因為儲存空間供應商加密機制通常能夠讓您瞭解自己服務的使用者),但這有助於防止供應商基礎架構發生的侵害事件。這項功能通常啟用簡單,值得考量。這個欄位瞬息萬變,而您的安全性團隊 (或您團隊中的 Security-savy 工程師) 最適合為您提供建議,但所有雲端儲存空間供應商都會透過設定、Azure Storage 和 Google Cloud Storage,為區塊儲存空間 Amazon S3 提供靜態資料加密功能,如為資料庫資料儲存空間,AWS RDS、Azure SQL 等Google Cloud SQL 都提供。如果您有使用授權 請向雲端儲存空間供應商確認這一點要自行處理靜態資料加密作業,防止使用者資料遭到侵害,要加以處理並不容易,因為安全管理加密金鑰並將其提供給程式碼的物流程序並不容易,卻不開放攻擊者使用,是相當困難的事。這並非針對該層級提出的安全性問題建議首選;您可以和資安專家或專責團隊 (或外部安全性機構) 討論相關事宜。