PDF 加密与解密 — Python / Rust / Go
绑定支持情况。 打开带密码的 PDF(解密)在五个绑定中都可用。写出新的加密 PDF 在 Python、Rust、Go (
DocumentEditor.SaveEncrypted)、WASM (saveEncryptedToBytes) 中支持。C# 公共 API 通过PdfDocument.OpenWithPassword支持以密码打开文件,但尚未暴露公共的SaveEncrypted包装——如果你需要在 C# 流水线里生成加密 PDF,请使用 Rust CLI 或 Go / Python 绑定。
用密码加密一个 PDF:
Python
from pdf_oxide import PdfDocument
doc = PdfDocument("report.pdf")
doc.save_encrypted("protected.pdf", "userpass", "ownerpass")
WASM
import { WasmPdfDocument } from "pdf-oxide-wasm";
const doc = new WasmPdfDocument(bytes);
const encrypted = doc.saveEncryptedToBytes("userpass", "ownerpass", true, true, true, true);
// encrypted 是一个 Uint8Array
doc.free();
Rust
use pdf_oxide::api::Pdf;
let mut doc = Pdf::open("report.pdf")?;
doc.save_encrypted("protected.pdf", "userpass", "ownerpass")?;
Go
package main
import (
"log"
pdfoxide "github.com/yfedoseev/pdf_oxide/go"
)
func main() {
editor, err := pdfoxide.OpenEditor("report.pdf")
if err != nil { log.Fatal(err) }
defer editor.Close()
if err := editor.SaveEncrypted("protected.pdf", "userpass", "ownerpass"); err != nil {
log.Fatal(err)
}
}
打开一个加密的 PDF:
Python
from pdf_oxide import PdfDocument
doc = PdfDocument("protected.pdf", password="userpass")
text = doc.extract_text(0)
print(text)
WASM
const doc = new WasmPdfDocument(encryptedBytes);
doc.authenticate("userpass");
const text = doc.extractText(0);
console.log(text);
doc.free();
Rust
let mut doc = Pdf::open_with_password("protected.pdf", "userpass")?;
let text = doc.extract_text(0)?;
println!("{}", text);
Go
doc, _ := pdfoxide.Open("protected.pdf")
defer doc.Close()
if _, err := doc.Authenticate("userpass"); err != nil { log.Fatal(err) }
text, _ := doc.ExtractText(0)
fmt.Println(text)
C#
using PdfOxide;
using var doc = PdfDocument.OpenWithPassword("protected.pdf", "userpass");
Console.WriteLine(doc.ExtractText(0));
PDF Oxide 默认使用 AES-256 加密。采用 MIT 协议,没有 AGPL 之类的限制。
安装
pip install pdf_oxide
加密 PDF
基本加密
Python
from pdf_oxide import PdfDocument
doc = PdfDocument("input.pdf")
doc.save_encrypted("output.pdf", "user123", "owner456")
WASM
const doc = new WasmPdfDocument(bytes);
const encrypted = doc.saveEncryptedToBytes("user123", "owner456", true, true, true, true);
doc.free();
Rust
let mut doc = Pdf::open("input.pdf")?;
doc.save_encrypted("output.pdf", "user123", "owner456")?;
- 用户密码 — 打开并查看文档所必需
- 所有者密码 — 拥有完全权限(打印、复制、修改)所必需
仅设置打开密码
只设置用户密码,不限制任何操作:
doc = PdfDocument("input.pdf")
doc.save_encrypted("locked.pdf", "viewpass", "adminpass")
不设置打开密码,但限制操作
允许任何人查看,但禁止打印和复制:
Python
doc = PdfDocument("input.pdf")
doc.save_encrypted(
"restricted.pdf",
"", # 无打开密码
"adminpass", # 拥有完全权限的所有者密码
allow_print=False,
allow_copy=False,
allow_modify=False,
allow_annotate=False,
)
WASM
const doc = new WasmPdfDocument(bytes);
const restricted = doc.saveEncryptedToBytes(
"", // 无打开密码
"adminpass", // 拥有完全权限的所有者密码
false, // allowPrint
false, // allowCopy
false, // allowModify
false // allowAnnotate
);
doc.free();
Rust
let config = EncryptionConfig::new("", "adminpass")
.with_permissions(Permissions::none());
doc.save_with_encryption("restricted.pdf", config)?;
只允许打印
允许查看和打印,但禁止复制和修改:
Python
doc = PdfDocument("input.pdf")
doc.save_encrypted(
"print-only.pdf",
"",
"adminpass",
allow_print=True,
allow_copy=False,
allow_modify=False,
)
WASM
const doc = new WasmPdfDocument(bytes);
const printOnly = doc.saveEncryptedToBytes(
"", // 无打开密码
"adminpass",
true, // allowPrint
false, // allowCopy
false, // allowModify
true // allowAnnotate
);
doc.free();
Rust
let config = EncryptionConfig::new("", "adminpass")
.with_permissions(Permissions::print_only());
doc.save_with_encryption("print-only.pdf", config)?;
权限选项
| 参数 | 默认值 | 说明 |
|---|---|---|
allow_print |
True |
允许打印文档 |
allow_copy |
True |
允许复制文本和图形 |
allow_modify |
True |
允许修改内容 |
allow_annotate |
True |
允许添加注释 |
解密 PDF
用密码打开
Python
from pdf_oxide import PdfDocument
doc = PdfDocument("encrypted.pdf", password="secret")
text = doc.extract_text(0)
print(f"Pages: {doc.page_count()}")
WASM
const doc = new WasmPdfDocument(encryptedBytes);
doc.authenticate("secret");
const text = doc.extractText(0);
console.log(`Pages: ${doc.pageCount()}`);
doc.free();
Rust
let mut doc = Pdf::open_with_password("encrypted.pdf", "secret")?;
let text = doc.extract_text(0)?;
println!("Pages: {}", doc.page_count()?);
保存为未加密副本
打开加密的 PDF 并保存未加密副本:
Python
from pdf_oxide import PdfDocument
doc = PdfDocument("encrypted.pdf", password="secret")
doc.save("decrypted.pdf")
WASM
const doc = new WasmPdfDocument(encryptedBytes);
doc.authenticate("secret");
const decrypted = doc.save();
// decrypted 是未加密的 Uint8Array
doc.free();
Rust
let mut doc = Pdf::open_with_password("encrypted.pdf", "secret")?;
doc.save("decrypted.pdf")?;
用新密码重新加密
Python
from pdf_oxide import PdfDocument
doc = PdfDocument("old-protected.pdf", password="oldpass")
doc.save_encrypted("new-protected.pdf", "newuser", "newowner")
WASM
const doc = new WasmPdfDocument(encryptedBytes);
doc.authenticate("oldpass");
const reEncrypted = doc.saveEncryptedToBytes("newuser", "newowner", true, true, true, true);
doc.free();
Rust
let mut doc = Pdf::open_with_password("old-protected.pdf", "oldpass")?;
doc.save_encrypted("new-protected.pdf", "newuser", "newowner")?;
批量加密
加密目录下的全部 PDF:
from pdf_oxide import PdfDocument, PdfError
from pathlib import Path
input_dir = Path("reports/")
output_dir = Path("protected/")
output_dir.mkdir(exist_ok=True)
for pdf_path in input_dir.glob("*.pdf"):
try:
doc = PdfDocument(str(pdf_path))
out_path = output_dir / pdf_path.name
doc.save_encrypted(
str(out_path),
"company2025",
"admin2025",
allow_print=True,
allow_copy=False,
)
print(f"Encrypted: {pdf_path.name}")
except PdfError as e:
print(f"Failed: {pdf_path.name}: {e}")
批量解密
使用已知密码解密目录下的全部 PDF:
from pdf_oxide import PdfDocument, PdfError
from pathlib import Path
input_dir = Path("protected/")
output_dir = Path("decrypted/")
output_dir.mkdir(exist_ok=True)
for pdf_path in input_dir.glob("*.pdf"):
try:
doc = PdfDocument(str(pdf_path), password="company2025")
out_path = output_dir / pdf_path.name
doc.save(str(out_path))
print(f"Decrypted: {pdf_path.name}")
except PdfError as e:
print(f"Failed: {pdf_path.name}: {e}")
支持的算法
PDF Oxide 支持所有标准的 PDF 加密算法:
| 算法 | 密钥长度 | 安全强度 |
|---|---|---|
| AES-256 | 256 位 | 最强(默认) |
| AES-128 | 128 位 | 强 |
| RC4-128 | 128 位 | 遗留 |
| RC4-40 | 40 位 | 弱(仅用于兼容) |
save_encrypted() 默认使用 AES-256。如果想显式指定算法,请使用 Rust API 的 EncryptionConfig。
为什么不用 pdfplumber 或 pdfminer?
pdfplumber 和 pdfminer 都不能处理加密 PDF:
- pdfplumber — 遇到带密码的 PDF 会直接报错,不支持解密。
- pdfminer — 加密支持有限,对 AES-256 加密的文件会失败。
- pypdf — 支持解密,但解密后提取文本比 PDF Oxide 慢 15 倍。
如果需要大规模处理加密 PDF,PDF Oxide 可以原生完成解密与加密,覆盖 AES-128 与 AES-256。
相关页面
- 加密与安全 API — 完整的加密 API 参考
- 批量处理 — 并行处理模式
- Python 快速上手 — 安装与基础