pdf-stego
Structure-based PDF watermarking — implementation of the scheme from Jiang et al. [1].
Embeds watermarks or arbitrary payloads as dictionary entries in Font Dictionary Objects and XObjects within the PDF structure. The embedding is invisible, produces zero visual distortion (SSIM = 1.0), and survives content editing, page extraction, and textbox-level attacks.
Note: Most of the code was generated by Claude Opus 4.6 and Gemini 3.1 Pro running in Antigravity.
Installation
pip install pdf-stego
From source
git clone https://github.com/samijuvaste/pdf-stego.git
cd pdf-stego
uv sync
Usage
CLI
Tip: Run
pdf-stego --helporpdf-stego <command> --help(e.g.pdf-stego embed --help) to see all available flags for each subcommand.
# Embed a payload (split across objects, default mode)
pdf-stego embed -i document.pdf -o payload.pdf -f payload.txt
# Embed a watermark (redundant copy to every object)
pdf-stego embed -i document.pdf -o watermarked.pdf -m "my watermark" --mode watermark
# Embed with AES encryption and explicit ordering
pdf-stego embed -i document.pdf -o encrypted-payload.pdf -m "secret" --encryption aes --key "passphrase" --order forwards
# Extract (flags must match what was used during embed)
pdf-stego extract -i payload.pdf
pdf-stego extract -i watermarked.pdf --mode watermark
pdf-stego extract -i encrypted-payload.pdf --encryption aes --key "passphrase" --order forwards
# Show object counts and watermark status
pdf-stego info -i document.pdf
Important: Extraction requires the same
--mode,--order,--seed,--channel, and--encryption/--keyflags that were used during embedding.
Python API
from pathlib import Path
from pdf_stego import embed, extract, info
# Embed
embed("input.pdf", "output.pdf", "my watermark", mode="watermark")
# Embed with encryption
embed("input.pdf", "output.pdf", "secret", encryption="aes", encryption_key="passphrase")
# Embed payload from a file
embed("input.pdf", "output.pdf", Path("payload.txt"))
# Extract (parameters must match embed)
data = extract("watermarked.pdf")
data = extract("watermarked.pdf", encryption="aes", encryption_key="passphrase")
data = extract("watermarked.pdf", mode="watermark", output="extracted.bin")
# Inspect
info("document.pdf")
Modes
payload(default) — Base64-encodes the input and splits it across available objects to maximize capacity. Each chunk is independently decodable. Can be ordered via--order(forwards,backwards, orrandom). A--seedcan be supplied forrandomordering (default:0).watermark— Embeds the full data into every available object for maximum redundancy and survivability.
Channels
font— Embed in Font Dictionary Objects onlyxobject— Embed in Image/Form XObjects onlyboth(default) — Embed in both channels
Encryption
none(default) — No encryptionaes— AES-256-GCM with PBKDF2 key derivation
Reference
[1] Jiang, Z., Wang, H. & Han, S. A robust PDF watermarking scheme with versatility and compatibility. Multimed Tools Appl 83, 64341-64367 (2024). https://doi.org/10.1007/s11042-024-18151-w
Metadata
Release files for pdf-stego 0.1.9
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| pdf_stego-0.1.9.tar.gz | 79.5 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pdf_stego-0.1.9-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 95.1 kB
Release files / pdf_stego-0.1.9.tar.gz
| Download URL | pdf_stego-0.1.9.tar.gz |
|---|---|
| Size | 79.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
660c4273fa7ec3b7abe926ce519ce57677cc4219104d87cc4d0df2dc667e3148
|
|
BLAKE2b-256 checksum How to use checksums |
0588351df81e1ed3f1dac022ec0b15baefe6591664815b46b713489a7de9a2d4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.13.5 {"installer":{"name":"uv","version":"0.13.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / pdf_stego-0.1.9-py3-none-any.whl
| Download URL | pdf_stego-0.1.9-py3-none-any.whl |
|---|---|
| Size | 15.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d1d216f565d9b1a05debf293232c4446a1a106396a5924c28ddd300932f06706
|
|
BLAKE2b-256 checksum How to use checksums |
3f35842033f9acab181aec252cf57082b669fec4dd09ac7278ff6639440b80b3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.13.5 {"installer":{"name":"uv","version":"0.13.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Security for pdf-stego 0.1.9
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.