加密通常是一个保障安全的主题,但它对于隐私也同样重要。加密的目标是防止他人读取加密信息...但阻止他人读取您的信息是确保信息私密性的一种方式。通常,用户能够执行这些操作的操作数量有限,但在您作为他们正在使用的服务提供商的协助下,加密有助于保留他们的数据。
有三种相关方法可以应用加密来帮助保护用户隐私:传输中加密、静态加密和端到端加密:
- 传输过程中加密是指在用户与您的网站之间保持数据加密(即 HTTPS)。您可能已经为网站设置了 HTTPS,但确定要向网站传输的所有数据都经过加密吗?这正是重定向和 HSTS 的用途,下文对其进行了介绍,并且应该纳入您的 HTTPS 设置。
- 静态加密是指对存储在服务器上的数据进行加密。这样可以防止数据泄露,是安全立场的重要组成部分。
- 端到端加密是指在客户端上的数据到达您的服务器之前对其进行加密。这样可保护用户数据,即使是您也无法访问:您可以存储用户的数据,但无法读取这些数据。这很难实现,并且并非适用于所有类型的应用,但它对于保护用户隐私而言非常有价值,因为除了自己之外,任何人都看不到自己的数据。
HTTPS
第一个举措是通过 HTTPS 提供 Web 服务。您很可能已经执行了此操作,但如果没有,这是重要的一步。HTTPS 是 HTTP,即浏览器用于从服务器请求网页的协议,但使用 SSL 进行加密。 这意味着外部攻击者无法读取或干扰发送者(您的用户)和接收者(您)之间的 HTTPS 请求,因为该请求已加密,所以他们无法读取或更改该请求。这属于传输加密:在数据从用户向您或从您传输到用户的过程中。在传输过程中对 HTTPS 加密还会阻止用户的 ISP 或所用 Wi-Fi 提供商读取作为他们与您的服务的关系的一部分发送给您的数据。这还可能会影响您的服务功能:在许多情况下,使用现有 JavaScript API 时,网站都需要通过 HTTPS 提供。 MDN 包含更全面的列表,而安全上下文背后的 API 包括 Service Worker、推送通知、网络共享和网络加密,以及一些设备 API。
如需通过 HTTPS 传送您的网站,您需要拥有 SSL 证书。您可以通过 Let's Encrypt 免费创建这些内容,或者通常由您的托管服务商(如果您使用)提供此类文件。您也可以使用第三方服务来“代理”您的网络服务,并且可以提供 HTTPS 以及缓存和 CDN 服务。此类服务有很多示例,例如 Cloudflare 和 Fastly,具体使用哪个取决于您当前的基础架构。过去,HTTPS 的实现可能负担过重或费用高昂,因此往往只能在付款页面或特别安全的来源上使用 HTTPS;然而,免费提供的证书、标准的改进以及日益普及的浏览器都消除了所有这些障碍。
正确做法
- 在您的服务器上为所有内容启用 HTTPS(无论您选择哪种方法)。
- 考虑在服务器前使用代理,例如 Cloudflare(有关过程的说明,请参阅 httpsiseasy.com/)。
- Let's Encrypt 将引导您完成创建您自己的 Let's Encrypt SSL 证书的过程。
- 或者,直接使用 OpenSSL 创建自己的证书,并让您选择的证书授权机构 (CA) 为其签名(如需详细了解如何执行此操作,请参阅启用 HTTPS)。
您选择哪种方法取决于业务需要权衡。让第三方为您管理 SSL 连接是最简单的设置,并且确实可以带来其他好处,例如负载均衡、缓存和分析。但与此同时,他们也明显将部分控制权移交给了第三方,并且不可避免地依赖于他们的服务(以及可能需要支付的费用,具体取决于您使用的服务和流量水平)。
过去,SSL 流程是通过生成证书并由 CA 进行签名的方式,但如果提供商支持 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 中,您可以创建前门;在具有 Express 的 Node 中,检查 request.secure;在 Nginx 中,捕获所有端口 80 并返回 301;在 Apache 中,使用 RewriteRule。如果您使用了托管服务,它们很可能会自动为您处理重定向到 HTTPS 网址的操作,例如 Netlify、Firebase 和 GitHub Pages 等。
HSTS
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
,则系统会以 https 形式请求从该网页向其他资源(图片、脚本)发出的请求,即使链接是 http 也是如此。但是,浏览器不会以 https 的形式重新请求页面本身,且浏览器不会记住下一次请求。实际上,如果您要将包含大量链接的现有网站转换为 HTTPS 网站,并且在内容中转换链接网址很困难,那么 Upgrade-Insecure-Requests 会非常有用,但我们建议您尽可能更改内容。
HSTS 主要是一项安全功能:对于之前访问过您网站的用户,它会将您的网站“锁定”到 HTTPS。但如上文所述,HTTPS 适用于保护隐私,而 HSTS 适用于 HTTPS。同样,如果您要更新所有内容,其实也不需要 Upgrade-Insecure-Requests,但这是一种很有用的“安全带”方法,可以加强防御,确保您的网站始终为 HTTPS。
正确做法
将 HSTS 标头添加到传出响应中:
Strict-Transport-Security: max-age=300; includeSubDomains
max-age 参数用于指示浏览器应记住并强制执行 HTTPS 升级的时长(以秒为单位)。 (在这里,我们将其设置为 300 秒,即 5 分钟。)最终,您希望此值为 6,3072,000(即 2 年),也是 hstspreload.org 建议采用的值,但如果出现问题,将很难恢复。因此,建议您在最初设置一个较小的数字 (300),进行测试以确认一切正常,然后逐步增加数量。
将 Upgrade-Insecure-Requests
标头添加到传出响应:
Upgrade-Insecure-Requests: 1
Content-Security-Policy: upgrade-insecure-requests
端到端加密
要保持用户数据的私密性,最好不要向除用户以外的任何人(包括您)显示数据。这对建立您的信任立场有很大帮助:如果您没有用户数据,很明显,您不能对这些数据做他们不想做的事。为了做到这一点,其中一种方法是将所有内容存储在客户端,完全不让用户将数据离开其设备。这种方法行之有效,但对于纯客户端应用,存在一些限制:浏览器数据存储可能大小有限,在某些浏览器中,系统可能会在极少数情况下甚至完全没有警告的情况下清除浏览器数据。此外,您很难或无法在两种设备(例如笔记本电脑和手机)上访问您的数据。因此,向服务器发送数据可能很有用,但可以使用只有用户知道的密钥对其进行加密,这样服务器就无法访问数据(因为无法解密),但可以存储数据。
运作方式
这种方法经常被即时通讯应用使用,称为“端到端加密”或“e2e”。通过这种方式,知道彼此密钥的两个用户可以来回加密和解密他们的消息,并通过消息传递提供程序发送这些消息,但消息传递提供程序(没有这些密钥)无法读取消息。大多数应用不是即时通讯应用,但可以结合使用以下两种方法(一种单独的客户端数据存储,以及使用客户端已知的密钥进行数据加密)在本地存储数据,同时将数据以加密形式发送到服务器。请务必认识到这种方法存在一定的局限性:这并不适用于所有服务,特别是如果您作为服务提供商,需要访问用户存储的内容,则无法使用这种方法。如本系列文章的第 2 部分所述,最好遵守数据最少化的原则;如果可以,则尽可能避免收集数据。如果用户需要数据存储,但您不需要访问这些数据即可提供服务,那么端到端加密是一种有用的替代方案。如果您提供的服务需要能够查看用户为了提供服务而存储的内容,那么端到端加密就不适合使用。但如果不这样做,您可让网络服务的客户端 JavaScript 加密它发送到服务器的任何数据,并解密它接收的所有数据。
示例:Excalidraw
Excalidraw 可行,并且会在博文中对此进行说明。它是一款矢量绘图应用,将绘图存储在服务器上,并使用随机选择的密钥加密这些绘图。Excalidraw 可以通过相对较少的代码实现这种端到端加密的部分原因是,现在使用 window.crypto 是加密库内置的加密库,这是所有现代浏览器都支持的一组 JavaScript API。加密很困难,实现这些算法会面临许多极端情况。让浏览器代为完成繁杂的工作,让 Web 开发者更方便地使用加密功能,从而更轻松地通过加密数据实现隐私保护。正如 Excalidraw 中所述,加密密钥仍保留在客户端,因为它是网址片段的一部分:当浏览器访问网址 https://example.com/path?param=1#fraghere
时,网址路径 (/path
) 和参数 (param=1
) 会传递到服务器 (example.com
),但 fragment (fraghere
) 不会传递到服务器,因此服务器永远看不到它。这意味着,即使加密的数据要经过服务器,加密密钥也不会通过服务器,因此可以保留隐私,因为数据已经过端到端加密。
限制
这种加密用户数据的方法并非万无一失。这有助于提升您对用户的信任立场,但无法完全取代它。您的用户仍必须信任您的服务,因为您可以随时将客户端 JavaScript 换成一些无法难以加密的 JavaScript 来替换客户端 JavaScript;尽管用户可能可以检测您正在使用的网站是否已完成上述操作,但这非常困难。实际上,您的用户仍然需要相信您的服务可读取且不值得他们信任,而您不会因此
另外还需要注意的是,端到端加密的目标之一是阻止您(即网站所有者)读取数据。这有益于保护隐私,但也意味着一旦遇到问题,您就无法帮助解决。从本质上讲,使用端到端加密的服务将加密密钥由用户掌控。(这可能并不明显或显而易见,但必须要有人知道密钥,如果数据不对您公开,那就不是您。)如果这些密钥丢失,您将无法采取任何措施,并且使用这些密钥加密的任何数据也可能会丢失。我们可以在隐私保护和易用性之间实现微妙的平衡:使用加密技术确保数据对所有人的私密性,但也避免强制用户成为密码学专家,通过安全的方式管理自己的密钥。
静态加密
除了加密用户传输中的数据之外,您还必须考虑加密存储在服务器上的数据。 这有助于防范数据泄露,因为在未经授权的情况下访问您存储的数据的人将获得已加密的数据,而他们希望没有解密密钥。加密静态数据有两种不同且互补的方法:您自行添加的加密,以及云端存储空间提供商添加的加密(如果您使用云端存储空间服务)。 对于通过您的软件发生的数据泄露,存储提供程序加密无法提供太多保护(因为存储提供程序加密通常对作为服务用户的您而言是透明的),但它确实有助于防止提供程序的基础架构中发生的数据泄露。启用该功能通常很简单,因此值得考虑。这个领域会迅速变化,您的安全团队(或团队中精通安全技术的工程师)是为您提供相关建议的最佳建议,但所有云存储服务提供商都默认为块存储 Amazon S3、Azure Storage 和 Google Cloud Storage 提供静态加密,并为数据库数据存储提供 AWS RDS、Azure SQL 等 Google Cloud SQL{/11。11如果您使用了云存储空间,请与您的云存储空间提供商确认。自行处理静态数据的加密以帮助保护用户数据免受数据泄露的影响,难度会越来越大,因为安全地管理加密密钥并使其可供编码而不向攻击者提供也是一项挑战。这并非针对该级别的安全问题提供建议的最佳场所;请与您精通安全技术的工程师或专门团队讨论此问题,或者与外部安全机构讨论。