Python・Rust・GoでPDFを暗号化・復号する
バインディングの対応状況。 復号(パスワードを使ったファイルのオープン)はすべてのバインディングでサポートされています。暗号化済みPDFの新規保存は Python、Rust、Go(
DocumentEditor.SaveEncrypted)、WASM(saveEncryptedToBytes)で利用できます。C# の公開 API はPdfDocument.OpenWithPasswordによるパスワード付きオープンに対応していますが、公開用のSaveEncryptedラッパーはまだ提供されていません。C# パイプラインで暗号化出力を生成したい場合は、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 is a 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)
}
}
C++
#include <pdf_oxide/pdf_oxide.hpp>
auto editor = pdf_oxide::DocumentEditor::open("report.pdf");
editor.save_encrypted("protected.pdf", "userpass", "ownerpass");
Swift
import PdfOxide
let editor = try DocumentEditor.open("report.pdf")
try editor.saveEncrypted("protected.pdf", userPassword: "userpass", ownerPassword: "ownerpass")
Dart
import 'package:pdf_oxide/pdf_oxide.dart';
final editor = DocumentEditor.open('report.pdf');
editor.saveEncrypted('protected.pdf', 'userpass', 'ownerpass');
editor.close();
R
library(pdfoxide)
editor <- pdf_editor_open("report.pdf")
pdf_editor_save_encrypted(editor, "protected.pdf", "userpass", "ownerpass")
pdf_editor_close(editor)
Julia
using PdfOxide
editor = open_editor("report.pdf")
save_encrypted(editor, "protected.pdf", "userpass", "ownerpass")
Zig
const pdf_oxide = @import("pdf_oxide");
var editor = try pdf_oxide.DocumentEditor.open("report.pdf");
defer editor.deinit();
try editor.saveEncrypted("protected.pdf", "userpass", "ownerpass");
Objective-C
#import "POXPdfOxide.h"
NSError *err = nil;
POXDocumentEditor *editor = [POXDocumentEditor openEditor:@"report.pdf" error:&err];
[editor saveEncryptedToPath:@"protected.pdf"
userPassword:@"userpass"
ownerPassword:@"ownerpass"
error:&err];
Elixir
{:ok, editor} = PdfOxide.open_editor("report.pdf")
:ok = PdfOxide.editor_save_encrypted(editor, "protected.pdf", "userpass", "ownerpass")
暗号化済み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));
C++
auto doc = pdf_oxide::Document::open_with_password("protected.pdf", "userpass");
auto text = doc.extract_text(0);
std::cout << text << "\n";
Swift
let doc = try Document.openWithPassword("protected.pdf", password: "userpass")
let text = try doc.extractText(0)
print(text)
Dart
final doc = PdfDocument.openWithPassword('protected.pdf', 'userpass');
final text = doc.extractText(0);
print(text);
R
doc <- pdf_open_with_password("protected.pdf", "userpass")
text <- pdf_extract_text(doc, 0)
cat(text)
Julia
doc = open_with_password("protected.pdf", "userpass")
text = extract_text(doc, 0)
println(text)
Zig
var doc = try pdf_oxide.Document.openWithPassword("protected.pdf", "userpass");
defer doc.deinit();
const text = try doc.extractText(a, 0);
defer a.free(text);
Objective-C
POXDocument *doc = [POXDocument openWithPassword:@"protected.pdf" password:@"userpass" error:&err];
NSString *text = [doc extractText:0 error:&err];
NSLog(@"%@", text);
Elixir
{:ok, doc} = PdfOxide.open_with_password("protected.pdf", "userpass")
{:ok, text} = PdfOxide.extract_text(doc, 0)
IO.puts(text)
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")?;
C++
auto editor = pdf_oxide::DocumentEditor::open("input.pdf");
editor.save_encrypted("output.pdf", "user123", "owner456");
Swift
let editor = try DocumentEditor.open("input.pdf")
try editor.saveEncrypted("output.pdf", userPassword: "user123", ownerPassword: "owner456")
Dart
final editor = DocumentEditor.open('input.pdf');
editor.saveEncrypted('output.pdf', 'user123', 'owner456');
editor.close();
R
editor <- pdf_editor_open("input.pdf")
pdf_editor_save_encrypted(editor, "output.pdf", "user123", "owner456")
pdf_editor_close(editor)
Julia
editor = open_editor("input.pdf")
save_encrypted(editor, "output.pdf", "user123", "owner456")
Zig
var editor = try pdf_oxide.DocumentEditor.open("input.pdf");
defer editor.deinit();
try editor.saveEncrypted("output.pdf", "user123", "owner456");
Objective-C
POXDocumentEditor *editor = [POXDocumentEditor openEditor:@"input.pdf" error:&err];
[editor saveEncryptedToPath:@"output.pdf"
userPassword:@"user123"
ownerPassword:@"owner456"
error:&err];
Elixir
{:ok, editor} = PdfOxide.open_editor("input.pdf")
:ok = PdfOxide.editor_save_encrypted(editor, "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",
"", # No password to open
"adminpass", # Owner password for full access
allow_print=False,
allow_copy=False,
allow_modify=False,
allow_annotate=False,
)
WASM
const doc = new WasmPdfDocument(bytes);
const restricted = doc.saveEncryptedToBytes(
"", // No password to open
"adminpass", // Owner password for full access
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(
"", // No password to open
"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()?);
C++
auto doc = pdf_oxide::Document::open_with_password("encrypted.pdf", "secret");
auto text = doc.extract_text(0);
std::cout << "Pages: " << doc.page_count() << "\n";
Swift
let doc = try Document.openWithPassword("encrypted.pdf", password: "secret")
let text = try doc.extractText(0)
print("Pages: \(try doc.pageCount())")
Dart
final doc = PdfDocument.openWithPassword('encrypted.pdf', 'secret');
final text = doc.extractText(0);
print('Pages: ${doc.pageCount}');
R
doc <- pdf_open_with_password("encrypted.pdf", "secret")
text <- pdf_extract_text(doc, 0)
cat("Pages:", pdf_page_count(doc), "\n")
Julia
doc = open_with_password("encrypted.pdf", "secret")
text = extract_text(doc, 0)
println("Pages: ", page_count(doc))
Zig
var doc = try pdf_oxide.Document.openWithPassword("encrypted.pdf", "secret");
defer doc.deinit();
const text = try doc.extractText(a, 0);
defer a.free(text);
std.debug.print("Pages: {d}\n", .{try doc.pageCount()});
Objective-C
POXDocument *doc = [POXDocument openWithPassword:@"encrypted.pdf" password:@"secret" error:&err];
NSString *text = [doc extractText:0 error:&err];
NSLog(@"Pages: %ld", (long)[doc pageCountError:&err]);
Elixir
{:ok, doc} = PdfOxide.open_with_password("encrypted.pdf", "secret")
{:ok, text} = PdfOxide.extract_text(doc, 0)
{:ok, pages} = PdfOxide.page_count(doc)
IO.puts("Pages: #{pages}")
暗号化なしで保存
暗号化済み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 is an unencrypted 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 入門 — インストールと基本