实战:从 AES-256-GCM 构建时加密到影子内容索引的动态解密全流程)
Quartz 加密页面EncryptedPages实战从 AES-256-GCM 构建时加密到影子内容索引的动态解密全流程【免费下载链接】quartz a fast, batteries-included static-site generator that transforms Markdown content into fully functional websites项目地址: https://gitcode.com/GitHub_Trending/qua/quartz加密页面Encrypted Pages是 Quartz v5 提供的一项社区插件能力它让站点可以在构建时用 AES-256-GCM 加密指定页面的正文访问者必须输入正确密码才能在浏览器端借助 Web Crypto API解密查看从而在静态站点上实现密码保护内容。本文以仓库中的 EncryptedPages Demo 演示页为核心线索结合 EncryptedPages 插件文档、UnlistedPages、BasesPage 与 CrawlLinks 等相关文档完整还原构建时加密 → 运行时解密 → 影子内容索引动态补丁的技术链路并给出可直接复制到quartz.config.yaml的配置方案与安全边界分析。演示页实际展示了什么仓库中的docs/plugins/EncryptedPages Demo.md是一张活体演示页其 frontmatter 本身就是加密功能的完整样例--- title: Encrypted Pages Demo password: quartz unlisted: true tags: - plugin/transformer image: ---页面正文只有一句Congratulations! Youve successfully decrypted this page. ——当你看到这句话时说明解密已经成功。这个演示页揭示了插件的两个核心事实正文在构建时被加密password: quartz告诉插件标题以下的所有 Markdown 内容都要在构建阶段用 AES-256-GCM 加密页面在任何发现面上被隐藏unlisted: true使得该页从侧边栏 graph、explorer、搜索、RSS、sitemap、backlinks、标签页和 bases 视图中完全缺席直到访问者输入密码。页面正文里列出了它自己经历的完整生命周期即What just happened?五步构建时插件读取 frontmatter 的password字段加密标题以下全部内容元数据旁路由于unlisted: true插件把该页的元数据slug、标题、链接、标签加密后写入独立的static/encryptedContentIndex.json即影子内容索引且使用该页自身的密码加密首次访问访问者看到的是密码输入提示而非正文页面同时从 graph、explorer、搜索、RSS、sitemap、backlinks、标签页和 bases 视图消失输入密码插件用 PBKDF2 派生加密密钥在浏览器端解密内容索引补丁插件利用缓存的密码解锁影子内容索引中该页的条目并原地修补内存中的内容索引派发content-index-updated事件graph、explorer、搜索随即用新解锁的条目重新初始化——此时再导航到其他页面就能在侧边栏、graph 和搜索结果中看到该页了。第五步有一个重要的结构性限制正文中明确强调服务端渲染的列表不会在本会话内更新。backlinks、recent notes、标签页、文件夹列表以及 BasesPage|bases 视图 都是在构建时烘焙进 HTML 的解密后的页面要等站点重新构建后才会出现在这些列表中。密码缓存与会话行为演示页还示范了一次输入、整站可用的体验密码被缓存在session storage中。如果站点上还有其他使用相同密码的加密页插件会在你访问它们时自动尝试该密码——同时解锁其内容和影子内容索引条目——整个会话只需输入一次。如果你在浏览器中打开 EncryptedPages Demo 对应的渲染页面并输入quartz即可亲自验证上述五步流程与缓存行为。快速上手安装与启用在 Plugins 总览 中EncryptedPages 被标记为transformer、emitter、component 三合一的多类别插件transformer 负责加密正文并设置 unlisted 标记emitter 负责写出影子内容索引component 负责渲染密码输入框与解密后的内容。它们共享同一份配置条目Quartz 会自动实例化全部三者。安装方式与任何社区插件一致参见 configuration 的 Community Plugins 一节 与 CLI 参考npx quartz plugin add github:quartz-community/encrypted-pages该命令会把插件写入quartz.config.yaml并安装到.quartz/plugins/。批量同步、清理与预览可用npx quartz plugin install --from-config # 按配置安装缺失插件并清理孤儿插件 npx quartz plugin prune # 仅清理不再被引用的插件两个命令均支持--dry-run预览变更。在 TS override 场景中对应的函数为ExternalPlugin.EncryptedPages()与ExternalPlugin.EncryptedContentIndex()。给页面加密最简配置在任意页面的 frontmatter 中添加password字段即可加密--- title: My Secret Page password: mysecretpassword ---构建时页面正文会被加密访问者必须输入正确密码才能查看内容。输入成功的密码会缓存于 session storage并在其他加密页面上自动尝试。隐藏加密页面unlisted: true默认情况下加密页面仍然会出现在graph、explorer、搜索、RSS、sitemap 和 backlinks 中——访问者能看到页面存在及其标题只是没有密码读不到正文。若想彻底隐藏直到访问者成功解密才暴露可在 frontmatter 中设置unlisted: true--- title: My Secret Page password: mysecretpassword unlisted: true ---unlisted页面具有以下行为与演示页完全一致缺席于contentIndex.json、sitemap.xml、RSS 源、backlinks、recent notes、文件夹列表、标签列表、bases 视图、graph、explorer 和搜索仍然输出 HTML可通过直接 URL 访问其元数据slug、标题、链接、标签被写入独立的static/encryptedContentIndex.json并以该页自身密码加密访问者成功解密后该页会被动态重新加入内存中的内容索引graph、explorer、搜索在本次浏览器会话剩余时间内都会反映它而 backlinks、recent notes、标签页、文件夹列表和 BasesPage|bases 视图 属于构建时烘焙的服务端渲染 HTML即使解密后也保持隐藏直到站点重新构建。如果需要让所有加密页默认 unlisted可以在插件选项中设置unlistWhenEncrypted: true个别页面再通过unlisted: false重新选择可见。[!note] 与 UnlistedPages 的组合unlisted: true仅在安装本插件时对加密页生效。若想让unlisted: true对站点的非加密页同样生效需要同时安装 UnlistedPages。两者可以干净地组合同时启用后unlisted: true会隐藏任何页面无论是否加密因为两个插件都遵循file.data.unlisted约定。永久隐藏stealth: true——密门内容unlisted页面在解密后会被重新揭示到 graph、explorer、搜索中这通常正是想要的行为——用户刚证明了自己知道密码会话剩余时间里在侧边栏看到该页很合理。但如果你想要的是即使成功解密了本站其他页面该页也永久不可见、只能通过直接 URL 访问的页面请设置stealth: true--- title: Deep Secret password: mysecretpassword stealth: true ---stealth页面的行为与任何unlisted页面一样缺席于所有发现面在影子内容索引encryptedContentIndex.json中没有条目——插件构建影子索引时会刻意跳过 stealth 页即使访问者输入了正确密码也保持隐藏由于没有影子索引条目可供解密也就没有任何内容可补丁进内存内容索引graph、explorer、搜索永远不会知道该页存在用户只能看到页面上解密后的 HTML 本身密码仍会缓存在 session storage 中因此再次访问同一 stealth 页可自动解锁。注意优先级规则stealth: true隐含unlisted: true两者无需同时写如果写了stealth: true, unlisted: falsestealth 标志胜出。对非加密页stealth: true没有效果因为不存在影子索引可供跳过。stealth页适合密门类内容——只应触达已经知道确切 URL 的用户外部 wiki 链接过来的私人笔记、只发送给特定对象的个人页面或任何即使对已认证读者也不希望出现在站内搜索中的内容。配置项详解所有配置都写在一个 config 条目上由 transformer 与 emitter 共享选项默认值说明iterations600000PBKDF2 密钥派生的迭代次数。越高越安全但解锁越慢passwordFieldpassword保存页面密码的 frontmatter 字段名。transformer 与 emitter 共用unlistWhenEncryptedfalse为true时所有加密页默认标记为 unlisted除非 frontmatter 显式覆盖outputPathstatic/encryptedContentIndex.json影子内容索引的输出路径相对于 Quartz 输出目录组件还有一项独立选项className即组件包裹层的 CSS 类名默认为encrypted-page-wrapper。完整的默认配置可直接粘贴到quartz.config.yaml- source: github:quartz-community/encrypted-pages enabled: true options: iterations: 600000 passwordField: password unlistWhenEncrypted: false outputPath: static/encryptedContentIndex.jsonTransformer 顺序约束CrawlLinks 必须先行[!warning]EncryptedPagestransformer 会把加密页的整个 HAST 树替换为一个不透明的密文容器。任何需要读取真实 HTML 的 transformer——特别是 CrawlLinks它负责填充 backlinks 和影子内容索引所需的链接关系——都必须运行在EncryptedPages之前。Quartz 插件按order字段控制同类插件内的执行顺序参见 configuration 的 Plugins 一节。实践中应确保CrawlLinks的order小于EncryptedPages的order否则链接爬取将因看不到真实 HTML 而失效导致 backlinks 与影子内容索引中的链接关系缺失。安全模型与边界插件文档明确给出了安全特性与边界这些都应作为部署决策的依据加密算法AES-256-GCM 加密内容PBKDF2 SHA-256 派生密钥明文剥离无论可见性设置如何明文都会被从搜索索引、RSS 源和影子内容索引中剥离影子索引的不可读性影子内容索引是一个扁平的不透明加密 blob 数组。攻击者下载它只能获知 unlisted 加密页的数量和 PBKDF2 迭代次数无法得知任何 slug、标题或链接关系密钥管理密码按页写在 frontmatter 中避免将密码提交到公开仓库能力边界这是静态站点的客户端加密能防御随意浏览但无法防御能拿到页面源码并全力分析的攻击者——加密密钥派生自用户输入的密码而 HTML/JS 全部在客户端可见。与相关插件的组合关系速查场景安装组合效果仅加密页面只装 EncryptedPagesunlisted: true只对加密页生效全站 unlisted只装 UnlistedPages任何页面的unlisted: true都生效加密功能独立加密 全站 unlisted推荐两者都装unlisted: true对所有页面生效两个插件通过file.data.unlisted约定干净组合bases 视图安装 BasesPage尊重file.data.unlistedstealth: true或unlisted: true的页面被排除在所有 base 视图之外且无法通过.asFile()被可见页公式解引用另外BasesPage 与加密页面共享同一结构性限制base 视图是构建时服务端渲染的 HTML访问者解密一个可揭示的加密页后它会出现于 graph、explorer、搜索它们从被补丁的内存内容索引重新水合但不会出现在任何 base 视图中——直到站点用已列出的页面重新构建。这个限制同样适用于 backlinks、recent notes、文件夹列表和标签列表。总结一条完整的加密发布链路至此可以串起整条链路构建时transformer 用页面的 frontmatter 密码以 AES-256-GCM 加密正文并在 unlisted/stealth 场景下把元数据写入用该页密码加密的影子内容索引运行时component 弹出密码输入框PBKDF2 派生密钥、Web Crypto API 客户端解密随后用缓存的密码解锁影子索引条目、补丁内存内容索引并派发content-index-updated事件让 graph、explorer、搜索即时响应——而服务端烘焙的列表则保持静态直到下一次构建。配合 UnlistedPages 的全站 unlisted 能力、stealth模式的密门页面以及 EncryptedPages Demo 提供的可交互样例你可以在一个纯静态站点上构建出密码即钥匙、内容零泄露的私密发布体系。【免费下载链接】quartz a fast, batteries-included static-site generator that transforms Markdown content into fully functional websites项目地址: https://gitcode.com/GitHub_Trending/qua/quartz创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考