PDF 암호화·복호화 — 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는 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 시작하기 — 설치와 기초