文档站新增八个小工具,全部在读者自己的浏览器里执行¶
我们是一群关心匿名网络与网络自由的志工,从台湾出发,维运文档站,把个人隐私与匿名的做法依日常、敏感工作与高风险三种情境整理成可以照着操作的指引。
站上的文章说明怎么保护自己,小工具区放的是可以直接按的东西。八个工具都在读者的浏览器里完成运算,不送出任何数据,存进设备之后没有网络也能用。

起点是照片的 metadata¶
Metadata 是什么那篇提到,照片里带着拍摄时间、相机型号与 GPS 坐标,而上传照片前先去 EXIF 是任何人现在就能做的低成本防护。
在线的清除工具几乎都需要先把文件传上去,而需要清除 metadata 的人,正是最不该把原始文件交出去的人。密码生成器、QR code 读取器与网址清理器都有同样的矛盾,要用的东西本身就是不该外流的东西。
把运算放回读者自己的浏览器可以解决矛盾,代价是功能受限于浏览器能做到的范围。需要连到外部服务才能运作的功能不会放进来,网络测量请用 OONI Probe,那是专门为测量设计的工具,数据的处理方式也公开。
八个工具看起来各做各的,收进来的判准只有一条:处理的东西本身就不该外流。照片里的坐标、刚生成的主密码、还没确认过的 QR code、可能被标记过的文件、答完就显示你在防谁的清单,交给任何一台服务器都说不过去。威胁模型清单与隐形字符检测离清除 metadata 这个起点比较远,收进来的理由相同。
八个工具共同的四条规则¶
- 在你的设备上运算:所有工具都在浏览器中完成计算,不送出任何数据
- 断网可用:存进设备之后没有网络也能用,域名被封锁、连接被切断或身处没有信号的地方都可以打开
- 源代码公开:程序放在 anoni-net/docs 仓库,具备能力的人可以自行验证
- 需要 JavaScript:运算在读者的设备上进行,浏览器关掉 JavaScript 时整页不会有反应
想自己确认第一条,最直接的做法是打开浏览器开发者工具的网络面板,用任何一个工具处理一次数据,看有没有请求送出去。整个过程不到一分钟,比读完源代码快得多。
用 Tor Browser 的话有一个冲突¶
Tor Browser 的安全等级调到 Safest 会关掉 JavaScript,八个工具都无法使用。冲突在于,安全等级页的指引写的是在遇到来路不明的钓鱼链接与不熟悉的域名时把等级调高,而收到可疑链接正是最需要用隐形字符检测或 QR code 读取器检查一次的时候。
可疑的网站用高安全等级打开,把要检查的文字或图片复制出来之后切回 Standard,检查完再调回去。工具不连外,在 Standard 等级下打开不会增加你在可疑网站上的暴露。
开始之前,先答三题¶
威胁模型清单把「要保护什么、要防谁、愿意付出多少」三题答成一份可复制的纯文本摘要,并列出建议先读的页面。分级与威胁模型如何建立一文完全一样,资产四类、对手六级、成本三级。
三题各自看都合理,凑在一起未必,清单会把凑不起来的组合标出来。对手选到执法或国家级而成本填最低、要防亲密关系的人却没把设备列进要保护的东西、只防随意路人却打算大改工作流程,都在标记的范围里。

答案只留在该标签页里,不写进 localStorage、不写进 IndexedDB、不写进 cookie,刷新就回到空白。「我要防的是亲密关系的人」写在设备上正好是最不该留的记录,而设备很可能就在对方的接触范围内。要保存一份就按复制摘要,贴到自己选的地方。tools/test_threatmodel.mjs 有一项测试守着不落地这件事,避免日后有人为了体验方便顺手加上存储。

刚加入一个团体、被交代注意安全却不知道从哪开始的时候,最适合打开清单。换工作、换城市、开始参与新议题,或经历一次安全事件之后,回头再答一次。
要交给别人的东西¶
密语与密码生成器¶
密语与密码生成器从 asian-diceware 的 7776 字词表抽密语,或从勾选的字符集抽随机密码。两个模式的随机数都来自 crypto.getRandomValues,取样时将无法整除的部分舍弃重抽,让每个字被抽中的概率完全相同。抽六个字的熵约为 77.5 位,画面会直接显示熵值。

怀疑手边的电脑被人动过的话,切到实体骰子模式。词表的顺序本身就是编码,第一个字是 11111,最后一个是 66666。掷五颗骰子按下画面上的数字即可查出一个字,随机性来自你自己的手,程序只剩查表的工作。按下载完整对照表会得到一份 7776 行的纯文本文件,印出来之后不必再打开工具。

申请密码管理器要设主密码、加密磁盘等长期不换的密码,都适合在此生成。复制之后记得用一段无关的文字覆盖剪贴板,手机上的剪贴板常常跨 App 共用。
QR code 生成器¶
QR code 生成器将很长又容易打错的字符串转成 QR code,让眼前的人用相机读取。活动报名链接、讲义的下载网址、临时的联系方式都适用,56 个字符的 onion 网址与一行含 IP 与指纹的 Tor bridge 也在其中,中间不经过任何服务器,也不留下消息记录。

QR code 里面是明文,任何拍到图的人都能读出内容,包括墙上的摄像头与你身后的人。真正需要保密的内容应该用端对端加密的通信工具传送。要印在纸上时将容错度调到 Q 或 H,纸会折也会脏。
现场要把一个链接交给眼前的人,而网络不方便使用的时候最适合。带工作坊把一行 bridge 交给参加者是典型的例子,念出来两边都不确定刚才是大写 O 还是数字 0,改用 QR code 让对方扫描,一次就对。
收到来路不明的东西时¶
QR code 读取器¶
QR code 读取器在浏览器中解出图片里的内容,图片不离开设备。解出来是网址时会将主机名独立标出,并且刻意不提供打开按钮,确认主机之后再自行贴进浏览器。

Wi-Fi 设置、两步验证绑定、预先写好的邮件与短信、地理坐标、电子名片都能识别,字段会拆开来标记,密码默认遮蔽。扫到 nopass 的 Wi-Fi、含 secret 的 otpauth:、javascript: 开头的内容都会另外提醒,那几种按下去的后果与扫到一个普通网址差很多。
停车缴费机上贴着一张看起来没有异状的 QR code,或刚认识的人递来印着 QR code 的名片,都适合先确认内容再决定要不要照做。
隐形字符检测¶
隐形字符检测找出文字里的零宽字符、方向控制、标签字符与混在拉丁字母里的同形字,标出位置并说明每一类是什么。

机构发文件给二十个人、每一份在不同位置插入不同组合的零宽字符,内容看起来完全一样,外流之后比对即可知道是哪一份。记者取得文件向机构求证时出示原件或复制粘贴其中一段,等于把消息来源交给正在找他的人。完整的场景见记者保护消息来源。
不可见字符的另一个用途是把整段指令藏进看起来正常的文件里。人读不到,模型读得到,把一段来路不明的文字贴给 AI 助手之前扫描一次,成本十秒。
检测结果能证明「有」,不能证明「没有」,零宽字符是最粗糙的一种标记方式,同义词替换、段落空白行数、标点微调、PDF 里的字符间距都不会被检测到,彩色激光打印机还会在每张纸上留下编码序号与时间的黄点阵列。处理真正敏感的文件时,正确的做法是重新打字或转述内容,不要传递原始文件。
社区的立场是教检测、不教植入,同一组零宽字符,机构用来保护内部文件是合理需求,用来找出举报人就是压迫工具,所以工具不提供生成带标记副本的功能,示范文字也固定,无法换成自己的文字。
送出去之前先清一次¶
文件 metadata 清除器¶
文件 metadata 清除器移除 EXIF、XMP、IPTC、制作软件与注释字段,文件不离开设备,清完的是新的一份,原始文件不会被改动。处理范围是 JPEG、PNG、WebP、GIF、MP4、MOV 与 PDF,遇到认不出来的文件,画面上会直接标示,不会安静地交回一份没有处理过的东西。

照片与视频的压缩数据从文件里的固定位置一路照抄到文件尾,一个比特都没有变动,清完的文件解出来与原文件完全相同。重新编码的工具做不到无损,每一次重新压缩都会损失画质,而且会在输出里留下自己的处理痕迹,用 mat2 清过的文件可以辨识出是 mat2 清的。
EXIF 里还有一张没有被裁切过的缩略图。照片裁掉一半再传出去,缩略图可能仍是原本的完整画面。画面上会逐项列出移除与保留的内容,含各自占几个字节,以及文件格式里对应的段落代号。
iPhone 默认拍出来的 HEIC 还无法处理,可以在「设置 → 相机 → 格式」选「最兼容」,之后拍的就是 JPEG。TIFF、RAW、MKV、WebM、AVI 与 Office 文档目前也不在范围内。工具不做人脸模糊,画面里的门牌、路标、制服与窗外景色都在图像本身,分享之前自行检视一次。
网址清理器¶
网址清理器挑出网址里的跟踪参数并移除,每一个都说明是谁在跟踪,同时拆掉 Google 与 Facebook 的跳转包装。

移除的逻辑是白名单,只处理清单里能识别的参数,其余一律保留。反过来做的话,YouTube 的视频 ID 与分页参数会一起被删除,读者会得到一个打不开或指向错误内容的网址,而且不会联想到是清理工具改坏的,只会觉得对方给错了链接。
从 Facebook 点开文章再复制出来的网址带着 fbclid,贴进群组之后,每个点进去的人都会带着同一个 ID 回到 Meta,同一个 ID 将整串点击记录串了起来。邮件通讯的 utm_source 转发出去等于告诉收件人你订了哪份通讯,mc_eid 更直接,属于 Mailchimp 的收件人识别码,对得回电子邮件地址。
短网址刻意不展开,因为展开的动作会把想清理的网址送到第三方服务器上,正好是工具要避免的事。
想知道自己的浏览器透露什么¶
你的浏览器透露了什么列出任何网站在打开页面的那一刻就能取得的信息,没有问过使用者,也不需要同意。每一项下面标出 Tor Browser 会显示什么,例如时区直接写「Tor Browser 会显示:UTC」,换一个浏览器打开同一页就可以对照。

最上面的八位短码是将稳定的值揉在一起算出来的,换设备或换浏览器再打开一次,只要比对短码就知道有没有变。十五项值加起来足以认出一个人,短码把整组值浓缩成一个可以直接比对的识别码。原理见浏览器指纹是什么。
列出的十五项里,在自己设备上真正能够关闭的只有三项,位置权限、语言偏好与 Do Not Track 信号。其余没有开关可以关,因为它们本来就是网页平台提供给网站的能力。单一动作能处理最多项目的是改用有内建防护的浏览器。
工具刻意没有导出按钮,导出的文件本身就是一份完整的指纹,留在设备上比不留更糟。也没有独特性百分比,计算独特性需要一个母体数据库,社区不打算为此开始收集访客数据。想看那种统计可以用 EFF 的 Cover Your Tracks。
视频与 PDF 各有一个限制¶
编码器会把自己的版本写进压缩数据本身,与画面内容混在一起,不属于描述字段,要移除只能重新编码,而重新编码会损失画质,也只是把旧编码器的痕迹换成新的。工具不做重新编码,改成把扫到的字符串列出来,避免使用者误以为已经清干净。
照片与视频可以把描述那一段直接剪掉,PDF 不行。PDF 的每个对象在交叉引用表里记着自己的位置,剪掉一段之后后面全部位移,整张表要重算,而 1.5 版之后常见的做法还会把好几个对象压进同一段压缩数据,从外面连内容都看不到。所以工具是把整份文件重写,无损的保证在 PDF 上不成立。实测页面内容不会重新排版,渲染出来与原文件逐像素相同,但表单、数字签名或特殊交互元素重写之后不一定完全保留,重要的文件先留一份原始文件。
XMP 另有一个陷阱,把文档目录里指向 XMP 的引用删掉、重新保存之后,内容仍然完整留在文件里,只是没有人指向它,用文本搜索工具打开还是找得到作者与地点,所以工具是把对象本身移除,tools/test_stripmeta.mjs 有一项测试专门守着。
整份文档站可以存进设备¶
用一般浏览器打开过文档站之后,目前语言的核心章节(概念、工具、进阶、在地)会在后台保存到设备的缓存里,不需要另外安装任何东西。切换语言时才会下载该语言的章节,所以设备上只会有实际读过的语言。

记者、行动者、LGBTQ、家暴等场景页不在预先下载的范围内,只有自行点开过才会保存。场景页留在设备上本身可能就是敏感信号,所以是否留存交给读者决定。要离线带着走的话,在离线阅读页的清单里自行勾选。
自动保存的章节默认只存文字,离线打开会缺图。页面上有一个选项可以连同核心章节的正文图一起保存,大约多 7 MB。默认关着是因为多数人在移动网络上,而缺图仍然读得懂大部分内容。自行勾选的页面不受该选项影响,一律连正文图一起保存。
文档站也可以安装成离线 App,Android、桌面浏览器与 iOS 的逐步操作写在离线阅读页。Tor Browser 以及 onion、IPFS 版基于隐私考量不注册后台的 Service Worker,需要离线备援时用一般浏览器在 anoni.net 安装,平时的匿名浏览再回到 Tor Browser。
用了谁的程序¶
小工具区大部分的程序是社区自己写的。有四样东西来自别人,原封不动放进来,不做任何修改:
| 组件 | 用在 | 许可证 |
|---|---|---|
| qrcode-generator 1.4.4 | QR code 生成器 | MIT |
| jsQR 1.4.0 | QR code 读取器 | Apache-2.0 |
| pdf-lib 1.17.1 | metadata 清除器的 PDF 部分 | MIT |
| asian-diceware 的 7776 字词表 | 密语与密码生成器 | 词表 CC-BY-4.0,程序 MIT |
不做修改是刻意的,改过就失去「这是上游那一份」的可审性,读者要验的时候只能相信我们的说法。文件都在 utils/vendor/ 底下,可以自己跟上游的版本比对。共通的理由是组件写错不会崩溃,只会产生看起来正常但实际上错的结果,那比坏掉更难发现。
想一起做的话¶
工具是纯前端,没有构建流程,程序在 anoni-net/docs 的 docs/zh-TW/js/ 底下,一个工具一支 JS。改完要在本机看效果,执行 cd docs && uv sync && mkdocs serve 即可。
八个工具各有一支测试,执行方式是 node tools/test_<名称>.mjs,不需要安装任何包,每一支都在 CI 里执行。测试守的是画面看起来正常、结果却是错的那几种情况:取样有没有偏差、生成的 QR code 扫回来内容对不对、指纹示范页有没有偷偷送出数据、网址清理有没有误删必要参数、威胁模型的答案有没有被写进存储。
目前缺的东西列在各工具页的不支持清单里,HEIC、TIFF、RAW、MKV、WebM、AVI 与 Office 文档都还没有人做。着手之前先开一个 issue 或到 Matrix room 说一声,避免两个人做同一件事。流程见 CONTRIBUTING 与如何参与与认领主题。
接下来¶
社区想往的方向是让文档站成为一份存在读者自己设备上的隐私与匿名指引。域名被封锁、连接被切断、身处没有网络的环境,正是最需要打开文档的时候,能否打开取决于之前有没有先保存下来。
几件现在就可以协助的事:
- 希望能离线带着走的页面:预先下载的范围目前依核心章节划分,实际需求可能不同
- 工具在你的情境下缺了什么:某个字段没有被识别、某种文件格式无法打开、说明看不懂都算
- 视频或 PDF 的实际案例:手上有无法清除 metadata 的文件,或清完之后无法打开的文件,都欢迎回报
回报渠道是 Matrix 公开 room(家服务器 im.anoni.net,链接见社区工具页),或 anoni-net/docs 的 issue。不方便具名的部分可寄到 whisper@anoni.net(GPG 公钥)。