# PDF 加密

把文档锁上，而不是为了锁它先把它交给一个网站。

> 在浏览器里给 PDF 加上密码，或者限制打印和复制。默认 AES-256，什么都不上传，做好的文件会先在这里重新打开一次、证明密码管用，然后才交给你。

This is an interactive browser tool at https://httcup.github.io/tools/protect-pdf/. Files are processed on the device running that browser. Any deliberate sharing or optional network feature is described on the page. What follows is its written explanation; open the address to use it.

## Your 文档 are **processed in your browser**. No processing upload.

你选的那份文档，打开、加密、写回，全都在这台机器的内存里完成，用的是从这个地址发来的代码。这里根本没有能做上传的东西，这一页的另一头也没有服务器可以接收。文件不会离开这个标签页，你打进去的密码也不会。

- ✗ 不上传
- ✗ 不注册
- ✓ 断网可用
- ✓ 开源
- ✓ 文件留在你的设备上

## 怎么给 PDF 加密码，或者加限制

1. **选那份 PDF。** 一次一份文档。浏览器直接从你的硬盘上把它读进来，在这里打开。已经要密码才能打开的文档会被退回，附一个去解锁那一页的链接；只带着限制的文档会被收下，你在下面设的会替换掉它原来的。
2. **设一个打开密码，再打一遍。** 这是真的锁。有这个密码的人能读这份文档，别人都不能，而且要是忘了，这里和别处任何诚实的地方都找不回来。两个框必须一致，按钮才会亮起来。要是你只想给一份仍然谁都打得开的文档加限制，两个框都留空就行。
3. **想要限制的话，勾上。** 打印、把文字和图片复制出去、改动文档。这些是行为端正的阅读器会遵守的请求，不是加密，页面在复选框旁边就是这么写的。权限密码能解除它们；那个框留空，打开密码就兼两份工；要是你一个密码都没设，就会用一个随机的、然后扔掉，这样限制不会被「什么都不输」解除。
4. **加密，然后读那句写着「已核对」的话。** 文档会用一把新鲜的密钥加密后写回去。接着做好的文件会在这里被重新打开两次，一次不给密码，这一次它必须被拒绝；一次给你的密码，这一次它必须打开，而且页数跟原来一样。两关里任何一关过不了，你不会拿到下载，只会拿到一句说明。

## The longer version

[如何给 PDF 加密码，保护到底值多少](https://httcup.github.io/tools/guides/protect-a-pdf/): PDF 密码是真正的锁，打印限制只是请求。了解两者、选择加密、为何无需上传，以及忘记密码会怎样。

## Also in the box

- [PDF 水印](https://httcup.github.io/tools/watermark-pdf/): 一份写着自己去了哪里的扫描件，就没法悄悄再去别的地方。
- [PDF 涂黑](https://httcup.github.io/tools/redact-pdf/): 字从文件里删掉，然后再搜一遍这个文件来证明。
- [PDF 转 CSV](https://httcup.github.io/tools/pdf-to-csv/): 将检测到的 PDF 文本表格转换成电子表格可打开的行。
- [收据与发票识别](https://httcup.github.io/tools/receipt-invoice-extractor/): 读取照片，检查字段和裁剪结果，准备供邮件应用使用的压缩附件和合计。

## Questions

### 加了密码的 PDF 真的安全吗？

用这里的默认方案，是的，安全程度正好等于那个密码：配上 PDF 2.0 密码哈希的 AES-256 是当前的方案，没有绕过它的捷径。值得知道的是，并不是每一份「加了密码」的 PDF 都是这么做的。这个格式经历了五代，从 1994 年那种一台笔记本就能直接搜出来的 40 位密钥，到今天这一个，而阅读器把它们全都写成同样几个字。这一页写的是最强的那个，另一个它也能写的，会按它的本来面目叫出来。

### 密码和限制有什么区别？

一份 PDF 里有两个密码的位置。*打开密码*是阅读器向你要的那个，没有它文件就打不开，这是真的。*权限密码*解除的是那些*限制*，打印、复制、编辑，而那些是一个请求。一份不用密码就能打开的文档必须自己装着推导出自身密钥所需要的一切，所以拦着阅读器不让打印的只是一个它同意遵守的字段，任何一个阅读器都可以不理。本站的 [PDF 解锁](https://httcup.github.io/unlock-pdf/)就是不理它的一个。设限制是说出你的希望；设密码才是把它锁死。

### 要是我把密码忘了呢？

那这份文档就丢了，而在这里听到这句话，比在一个先要你把文件交出去的「密码找回」网站上听到要好。本站不猜密码，你可以自己读 `src/shared/pdf-crypt.js`，里面连一个循环都没有，而对一份用默认方案锁上的文档来说，别处任何诚实的东西也猜不出来。这就是这一页让你把密码打两遍的原因。把你的原件留着：这里做的任何事都不会改动它，密码真的没了的时候，你要的就是那一份。

### 该选 AES-256 还是 AES-128？

AES-256，除非有一个 2010 年之前的阅读器必须能打开这个文件。256 位那个是 PDF 2.0 的方案，Acrobat X 及之后、每一个浏览器、每一部手机、每一个现在还在用的阅读器都支持。128 位那个是 2005 年的方案，那些老阅读器认得它，而它弱不是因为算法，是因为它前面那个 1994 年的密钥推导，那一步让猜密码比算法看上去便宜得多。要是你不知道会用哪个阅读器打开这个文件，选 256。

### 已经加了保护的 PDF 能再加吗？

如果它不用密码就能打开、只带着限制，能：拖进来，你设的会替换掉它原来的。如果它要密码才能打开，这一页会把它退回，指向 [PDF 解锁](https://httcup.github.io/unlock-pdf/)，在同一个浏览器里把旧的保护去掉；把解锁后的副本拿回这里加新的。一份文档上叠两把锁不是这个格式能表达的东西，所以换密码永远是先去掉、再加上。

### 做完之后文档看上去会不一样吗？

不会。什么都不会被重新渲染、重新编码或者重排：每一页的绘制指令、每一个嵌入字体、每一张图片，都原样加密后复制过去。对拿着密码的人来说，文字还能选，扫描件还是原来的分辨率，什么都不会移位。文件可能会小一点，因为一次重写会把早先编辑留在里面、已经被取代的旧对象丢掉；也可能大一点，因为加密会给每一个流多加十六个字节。

### 带签名的文档会怎么样？

它的签名会失效，而且没有办法绕过去。签名覆盖的是它当初签的那个文件的确切字节，所以任何改动，任何程序做的，包括当初签它的那个程序，都会让它失效。这个工具写的是一个新文件，发现原件带签名时会在结果里说明。要是你需要一份既签了名又加了密的文档，先加密，再给加密后的那份签名。

### 我的文档或者密码会被上传到什么地方吗？

不会。文件是你自己的浏览器在你自己的硬件上读取、加密、写出的，密码进的是一段跑在这个标签页里的密钥推导。这个工具没有服务器那一端，页面的 `Content-Security-Policy` 列出了它可以联系的每一个地址，其中没有一个属于本站。最简单的验证办法，是把网线拔掉，照样用这一页。在所有工具里，这一个尤其如此：你正在锁上的文档，正是你最不想先递一圈的那份。

### 我怎么知道保护真的加上了？

因为这个工具会在你的机器上核对，并且把结果给你看。文件写好之后，它会被交给本站其他 PDF 工具用的同一个读取器，打开两次。不给密码的时候它必须被直接拒绝；给你设的密码的时候它必须打开，页数跟原来一样，并且报告出你勾的那些限制。两关里任何一关过不了，这次运行就报告为失败，什么都不会给你下载。你事后也可以自己验：用任何一个阅读器打开它，它会问你要密码，再去文档属性里看那些权限。

### 有大小限制吗？要钱吗？

工具里没有写死任何限制。限制是你自己的机器：文档在处理的时候是放在内存里的，几百兆的量，一台笔记本吃得下，再往上就会吃力。它是免费的，不注册、不登录，也没有试用期。本站带广告，那是养活它的东西；广告拿不到任何关于你文档的内容。

### 断网能用吗？

能。把页面加载一次，然后断开网络，它照样能用。这也是证明什么都没被上传的最简单的办法：一个把你的文档发出去加密的工具，你一拔网线它就停了。

## How the privacy claim is verifiable

- **这是唯一一个「上传」本身就违背目的的工具。** 一份值得加密码的文档，按定义就是一份你不想落到别人手里的文档。每一个提供「保护 PDF」的在线工具都要你先把它交出去，先是没加密的原件，然后是你选的密码，交给一台你看不见它留存了什么的服务器。这一页做不到那件事。文件是你自己的浏览器读的，密钥在这个标签页里推导，加密后的副本在内存里写出，页面的 `Content-Security-Policy` 列出了这一页可以联系的每一个地址，其中没有一个属于本站。把网络断掉它照样能用，这是最简单的证明。
- **密码是真的锁。限制是一个请求。这一页会说清楚哪个是哪个。** *打开密码*是真的把文档锁上了：内容用从它推导出来的密钥加密，密码本身不写在文件里的任何地方，没有它谁也读不了一个字。*限制*，不许打印、不许复制、不许编辑，是另一回事。一份不用密码就能打开的文档，必须自己装着推导出自身密钥所需要的一切，所以拦着阅读器不让打印的只是一个权限字段，阅读器同意去遵守它，而任何一个阅读器都可以不理。Adobe 从一开始就是这么写的，本站的 [PDF 解锁](https://httcup.github.io/unlock-pdf/)就是不理它的程序之一。限制仍然值得设：它是你说出自己希望的方式，大多数阅读器会听。只是它不是一把锁，这一页不会告诉你它是。
- **默认用当前方案 AES-256，除非你自己选那个老的。** PDF 的加密经历了五代，阅读器把它们全都写成「已加密」。这里默认用最新的一代：配上 PDF 2.0 密码哈希的 AES-256，它被故意设计得算起来很贵，也是这一族里唯一一个仍然被认为是强的方案。用它锁上的文档，安全程度等于它上面那个密码的强度。选另一个选项、也就是配上 1994 年密钥推导的 AES-128 的唯一理由，是有一个 2010 年之前的老阅读器必须能打开这个文件，而页面把这句话写在选项旁边，而不是把弱的那个跟强的那个并列着摆出来。
- **密码要打两遍，因为没有回头路。** 本站不猜密码，别处任何诚实的东西也不猜：一份用强方案锁上、密码又没人记得的文档，是一份再也没人读得了的文档。所以打开密码要打两遍，两遍必须一致，页面会用大白话说一次：忘了密码就等于丢了文件。把你的原件留着。这里做的任何事都不会改动它。
- **做好的文件在交给你之前，会在这里重新打开一次。** 在那之前，上面这些话都只是这个工具在给自己判卷。所以那些马上就要变成你下载的字节，会被交给本站每一个 PDF 工具用的同一个读取器，打开两次：一次不给密码，这一次它必须被拒绝；一次给你设的密码，这一次它必须打开，页数跟原来一样，限制也正是你要的那些。两关里任何一关过不了，这次运行就报告为失败，也不会有下载。
- **页面本身不会被重新渲染、重新编码，也不会重排。** 变的是文档外面那层加密，不是文档。每一页的绘制指令、每一个嵌入字体、每一张图片，都按原样加密后写回去，所以对拿着密码的人来说，文字还能选、还能搜，扫描件还是扫描时的分辨率，页面上什么都不会移位。唯一会变的是任何一次重写都会变的东西：早先编辑留下的、已经被取代的旧对象不再带过来。
- **数字签名过不了这一关，有签名的时候页面会说。** 签名覆盖的是它当初签的那个文件的确切字节，所以任何重写都会让它失效，这正是签名的用处。这个工具写的是一个新文件，所以你拿回去的那份是没有签名的；发现文件带着签名时，它会在结果里说明。你的原件仍然是那份签过名的。两样都要的话，先加密，再签名，别反过来。
- **已经锁着的文档会先被送到隔壁。** 一个要密码才能打开的文件，不会在这里被叠上第二层密码。它会被退回，附一个去 [PDF 解锁](https://httcup.github.io/unlock-pdf/)的链接，在同一个浏览器里把旧的保护去掉，再把解锁后的副本拿回这里加新的。一个谁都打得开、只带着限制的文件是收的，并且会被明确告知：你在这里设的会替换掉它原来带的。
- **Google 加载了什么，又没拿到什么。** 广告和统计脚本来自 Google。这两个都没有拿到关于你文档的任何东西：不是文件，不是某一页，不是文件名、大小、页数、密码，也不是这个文件被什么保护着。每一行读取、加密或者写出 PDF 的代码都由这个源站发出，并且列在代码仓库里。
- **打赏按钮加载了什么，又没拿到什么。** 页眉上那个「Buy me a coffee」按钮，是由 cdnjs.buymeacoffee.com 的一段脚本画出来的，字体取自 Google Fonts。它就是一个链接，仅此而已：它不上报访问，也拿不到任何关于你或者你文档的东西。你不点它就什么都不会发生，而点下去要去的是别人的网站。
- **断网也能用。** 把网络断掉，这一页上的所有功能照常。这是最简单的一个证明：一个把你的文档发出去加密的工具，这时候就停了。

**Check it yourself.** None of the above has to be taken on trust. This page is generated from the templates and config in the repository by a build script you can read and run yourself, and the result is committed to the `dist` branch — so you can diff what is served against what a build of the sources produces: https://github.com/httcup/tools

The files worth reading first are `config/site.toml` for the Content-Security-Policy，一个密码是怎么变成文档密钥、/Encrypt 字典又是怎么从它建出来的，看 `src/shared/pdf-crypt.js`；密码算法本身在 `src/shared/aes.js`。这几个都够不着网络，旁边负责读和写的部分也一样。
