@pdfsmaller/pdf-decrypt-lite
v1.0.0
Published
Ultra-lightweight PDF decryption (~8KB) with RC4 40/128-bit support. Built for edge environments like Cloudflare Workers. Powers PDFSmaller.com's unlock tool.
Downloads
56
Maintainers
Readme
pdf-decrypt-lite 🔓
Ultra-lightweight PDF decryption library (~8KB!) with RC4 40/128-bit support
Built by PDFSmaller.com - Try our free online PDF tools with this decryption built-in!
🚀 Why pdf-decrypt-lite?
When building PDFSmaller.com, we needed lightweight PDF decryption that worked within edge constraints. Every existing solution pulled in all of pdf.js (2MB+) just to remove a password. There was literally no standalone PDF decryption package on npm.
So we built one.
This is the companion to our @pdfsmaller/pdf-encrypt-lite package — same crypto engine, reverse direction.
The Problem We Solved:
- ❌ pdf.js: 2MB+ just for decryption
- ❌ qpdf/poppler: Native binaries, not browser-compatible
- ❌ No npm package:
pdf-decrypt,pdf-unlock— nothing existed! - ✅ pdf-decrypt-lite: Only ~8KB! 🎉
✨ Features
- 🔓 Real PDF decryption - RC4 40/128-bit that actually works
- 📦 Tiny size - Only ~8KB total (MD5 + RC4 implementations)
- ⚡ Edge-ready - Works in Cloudflare Workers, Vercel Edge, Deno Deploy
- 🌐 Browser compatible - No Node.js dependencies
- 🔑 Dual password support - Works with both user and owner passwords
- 🔍 Encryption detection - Check if a PDF is encrypted before decrypting
- 📱 PDF Standard compliant - Implements Algorithms 2, 4-7 from PDF spec
- 🚀 Zero dependencies - Just needs pdf-lib as peer dependency
- 🤝 Companion package - Pairs perfectly with
@pdfsmaller/pdf-encrypt-lite
📥 Installation
npm install @pdfsmaller/pdf-decrypt-lite pdf-lib💻 Usage
import { decryptPDF, isEncrypted } from '@pdfsmaller/pdf-decrypt-lite';
// Decrypt a PDF
const decryptedPdfBytes = await decryptPDF(encryptedPdfBytes, 'password123');
// Check if encrypted first
const info = await isEncrypted(pdfBytes);
if (info.encrypted) {
console.log(`Encrypted: V=${info.version}, R=${info.revision}, ${info.keyLength}-bit`);
const decrypted = await decryptPDF(pdfBytes, password);
}
// Full example
async function unlockPDF() {
// Load your encrypted PDF
const encryptedBytes = await fetch('protected.pdf').then(res => res.arrayBuffer());
// Decrypt it
const decryptedBytes = await decryptPDF(
new Uint8Array(encryptedBytes),
'secret123'
);
// Save the unlocked PDF
const blob = new Blob([decryptedBytes], { type: 'application/pdf' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'unlocked.pdf';
a.click();
}🔐 Encrypt + Decrypt Pair
Use with our companion encryption package for a complete solution:
import { encryptPDF } from '@pdfsmaller/pdf-encrypt-lite';
import { decryptPDF } from '@pdfsmaller/pdf-decrypt-lite';
// Encrypt
const encrypted = await encryptPDF(pdfBytes, 'password');
// Later... Decrypt
const decrypted = await decryptPDF(encrypted, 'password');🔥 Use Cases
Perfect for:
- Edge Functions (Cloudflare Workers, Vercel Edge, Netlify Edge)
- Browser applications (Like PDFSmaller.com)
- Serverless functions with size limits
- Client-side PDF unlocking without server uploads
- Automated document pipelines that need to process protected PDFs
- Lightweight Node.js applications
🎯 Real-World Example
See it in action at PDFSmaller.com/unlock-pdf - our free online tool uses this exact library to decrypt PDFs directly in your browser. No uploads, no server processing, just pure client-side decryption!
🏗️ How It Works
- Parse encryption dict - Reads /Encrypt, /ID from PDF trailer via pdf-lib
- Validate password - Tries as user password, then owner password
- Derive encryption key - MD5-based key derivation per PDF spec
- Decrypt all objects - RC4 decrypts every stream and string with per-object keys
- Strip encryption - Removes /Encrypt entry, outputs clean PDF
Total crypto code: ~8KB 🤯
📊 Comparison
| Library | Size | Real Decryption | Edge Compatible | Browser | |---------|------|-----------------|-----------------|---------| | pdf-decrypt-lite | ~8KB ✅ | ✅ | ✅ | ✅ | | pdf.js | 2,000KB+ | ✅ | ❌ | ✅ | | qpdf | Native | ✅ | ❌ | ❌ | | pdf-lib alone | 0KB | ❌ | ✅ | ✅ |
⚠️ Supported Encryption
| Type | Version | Status | |------|---------|--------| | RC4 40-bit | V=1, R=2 | ✅ Supported | | RC4 128-bit | V=2, R=3 | ✅ Supported | | AES 128-bit | V=4, R=4 | 🔜 Planned (v2) | | AES 256-bit | V=5, R=6 | 🔜 Planned (v2) |
RC4 encryption covers the majority of password-protected PDFs in the wild. AES support is planned for v2 using the Web Crypto API.
🤝 Contributing
We welcome contributions! This library powers PDFSmaller.com, so we maintain high standards for security and compatibility.
📜 License
MIT License - Use it freely in your projects!
🙏 Credits
Built with ❤️ by PDFSmaller.com - Your free PDF toolkit
If this library helps you, check out our other free PDF tools:
- Unlock PDF - Uses this library!
- Protect PDF - Uses pdf-encrypt-lite!
- Compress PDF - Reduce PDF size by up to 90%
- Merge PDF - Combine multiple PDFs
- 20+ more tools - All free, all private
🚀 Quick Start for Cloudflare Workers
import { decryptPDF } from '@pdfsmaller/pdf-decrypt-lite';
export default {
async fetch(request, env) {
const formData = await request.formData();
const file = formData.get('pdf');
const password = formData.get('password');
const pdfBytes = new Uint8Array(await file.arrayBuffer());
const decrypted = await decryptPDF(pdfBytes, password);
return new Response(decrypted, {
headers: { 'Content-Type': 'application/pdf' }
});
}
}📧 Support
⭐ Star this repo if it helps you!
Built because nothing existed. Shared because you need it too.
PDFSmaller.com - Free PDF Tools That Actually Work™
