html2pdf-secure 0.1.0

A Rust crate for converting HTML to password-protected PDF files
Documentation

html2pdf-secure

A Rust crate for converting HTML to password-protected PDF files using headless Chrome and robust encryption.

Crates.io Documentation License

Features

  • 🌐 HTML to PDF Conversion: Convert HTML content, files, or URLs to PDF using headless Chrome
  • 🔒 Password Protection: Add user and owner passwords to generated PDFs
  • 🛡️ Multiple Encryption Levels: Support for various encryption standards (40-bit, 128-bit, AES-128, AES-256)
  • ⚙️ Customizable PDF Options: Control page format, orientation, margins, and more
  • 🔧 Flexible Permissions: Fine-grained control over PDF permissions (printing, copying, editing, etc.)
  • 🚀 Async Support: Built with async/await for non-blocking operations
  • 🔗 External Tool Integration: Optional integration with qpdf for stronger encryption

Quick Start

Add this to your Cargo.toml:

[dependencies]
html2pdf-secure = "0.1"
tokio = { version = "1.0", features = ["full"] }

Basic Usage

use html2pdf_secure::{Html2PdfConverter, PdfOptions, PasswordOptions};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Create converter
    let converter = Html2PdfConverter::new().await?;
    
    // HTML content
    let html = "<html><body><h1>Hello, Secure World!</h1></body></html>";
    
    // Configure password protection (uses AES-256 by default)
    let password_options = PasswordOptions::new("user123", "owner456");

    // Convert to protected PDF (requires qpdf)
    let pdf_data = converter
        .convert_html_to_protected_pdf(html, PdfOptions::default(), password_options)
        .await?;
    
    // Save to file
    std::fs::write("secure_document.pdf", pdf_data)?;
    
    Ok(())
}

Installation Requirements

Basic Requirements

  • Rust 1.85+: Required for Rust 2024 edition features
  • Chrome/Chromium: Automatically downloaded by headless_chrome crate

Required: qpdf for Password Protection

Important: Password protection requires qpdf to be installed. Without qpdf, PDFs will be generated without encryption.

# Ubuntu/Debian
sudo apt-get install qpdf

# macOS
brew install qpdf

# Windows
# Download from https://qpdf.sourceforge.io/

To verify qpdf installation:

qpdf --version

Examples

Convert URL to Protected PDF

use html2pdf_secure::{Html2PdfConverter, PdfOptions, PasswordOptions, PageFormat};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let converter = Html2PdfConverter::new().await?;
    
    let pdf_options = PdfOptions {
        page_format: PageFormat::A4,
        print_background: true,
        ..Default::default()
    };
    
    let password_options = PasswordOptions::new("secret", "admin");
    
    let pdf_data = converter
        .convert_url_to_protected_pdf(
            "https://www.rust-lang.org/", 
            pdf_options, 
            password_options
        )
        .await?;
    
    std::fs::write("rust_website.pdf", pdf_data)?;
    Ok(())
}

Advanced Configuration

use html2pdf_secure::{
    Html2PdfConverter, PdfOptions, PasswordOptions, 
    EncryptionLevel, PdfPermissions, PageFormat, PageOrientation
};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let converter = Html2PdfConverter::new().await?;
    
    // Advanced PDF options
    let pdf_options = PdfOptions {
        page_format: PageFormat::Letter,
        orientation: PageOrientation::Landscape,
        print_background: true,
        scale: 0.8,
        ..Default::default()
    };
    
    // Strong encryption with restricted permissions
    let password_options = PasswordOptions::new("user_pass", "owner_pass")
        .with_encryption_level(EncryptionLevel::Aes256)
        .with_permissions(PdfPermissions {
            allow_printing: false,
            allow_copy: false,
            allow_modify_contents: false,
            ..Default::default()
        });
    
    let html = "<html><body><h1>Highly Secure Document</h1></body></html>";
    
    // Use qpdf for strongest encryption (if available)
    let pdf_data = converter
        .convert_html_to_protected_pdf_with_qpdf(
            html, 
            pdf_options, 
            password_options, 
            Some("/tmp")
        )
        .await?;
    
    std::fs::write("highly_secure.pdf", pdf_data)?;
    Ok(())
}

API Reference

Core Types

  • Html2PdfConverter: Main converter for HTML to PDF operations
  • PdfOptions: Configuration for PDF generation (page size, margins, etc.)
  • PasswordOptions: Password and encryption configuration
  • EncryptionLevel: Encryption strength options
  • PdfPermissions: Fine-grained permission control

Conversion Methods

  • convert_html_to_pdf(): Convert HTML string to PDF
  • convert_html_file_to_pdf(): Convert HTML file to PDF
  • convert_url_to_pdf(): Convert web page to PDF
  • convert_html_to_protected_pdf(): Convert HTML to password-protected PDF
  • convert_html_to_protected_pdf_with_qpdf(): Convert with qpdf encryption

Encryption Levels

Level Description Key Length Security
Standard40 RC4 40-bit 40-bit Basic
Standard128 RC4 128-bit 128-bit Good
Aes128 AES 128-bit 128-bit Strong
Aes256 AES 256-bit 256-bit Very Strong

Security Considerations

Encryption Behavior

Important: This library requires qpdf for password protection:

  • With qpdf installed: PDFs are properly encrypted with AES-256 by default
  • Without qpdf: PDFs are generated without encryption and a warning is logged
  • Fallback behavior: The library will attempt qpdf first, then fall back to unencrypted PDF

Encryption Levels

The library supports multiple encryption levels when qpdf is available:

  • AES-256 (default): Strongest encryption, recommended for all use cases
  • AES-128: Strong encryption, good for most applications
  • 128-bit RC4: Legacy encryption, requires --allow-weak-crypto flag
  • 40-bit RC4: Very weak encryption, requires --allow-weak-crypto flag

Production Recommendations

For production use with sensitive data:

  • Always install qpdf for proper encryption
  • Use AES-256 (default) or AES-128 encryption levels
  • Avoid RC4 encryption levels (weak and deprecated)
  • Test encryption by verifying password requirements

Error Handling

use html2pdf_secure::{Html2PdfConverter, Html2PdfError};

#[tokio::main]
async fn main() {
    let converter = Html2PdfConverter::new().await.unwrap();
    
    match converter.convert_html_to_pdf("<html></html>", Default::default()).await {
        Ok(pdf_data) => println!("Success: {} bytes", pdf_data.len()),
        Err(Html2PdfError::ChromeError(msg)) => eprintln!("Chrome error: {}", msg),
        Err(Html2PdfError::EncryptionError(msg)) => eprintln!("Encryption error: {}", msg),
        Err(e) => eprintln!("Other error: {}", e),
    }
}

Examples

Run the included examples:

# Basic usage
cargo run --example basic_usage

# qpdf encryption (requires qpdf installed)
cargo run --example qpdf_encryption

# URL to PDF conversion
cargo run --example url_to_pdf

Testing

Run the test suite:

cargo test

Performance

The crate is designed for efficiency:

  • Reuses Chrome instances when possible
  • Supports concurrent PDF generation
  • Minimal memory footprint for PDF processing

Troubleshooting

Chrome/Chromium Issues

If you encounter Chrome-related errors:

  1. Ensure sufficient system resources
  2. Check Chrome installation
  3. Verify network connectivity for URL conversions

qpdf Integration

If qpdf encryption fails:

  1. Verify qpdf installation: qpdf --version
  2. Check file permissions in temp directory
  3. Ensure sufficient disk space

Common Issues

  • "Chrome browser error": Usually indicates Chrome startup issues
  • "Encryption error": Check password requirements and qpdf availability
  • "Invalid input": Verify HTML syntax and file paths

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Development Setup

git clone https://github.com/yourusername/html2pdf-secure
cd html2pdf-secure
cargo build
cargo test

License

This project is licensed under either of

at your option.