pypdf-6-encryption-and-form-filling

Sub-skill of pypdf: 6. Encryption and Form Filling.

5 stars

Best use case

pypdf-6-encryption-and-form-filling is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Sub-skill of pypdf: 6. Encryption and Form Filling.

Teams using pypdf-6-encryption-and-form-filling should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/6-encryption-and-form-filling/SKILL.md --create-dirs "https://raw.githubusercontent.com/vamseeachanta/workspace-hub/main/.agents/skills/_archive/data/office/pypdf/6-encryption-and-form-filling/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/6-encryption-and-form-filling/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How pypdf-6-encryption-and-form-filling Compares

Feature / Agentpypdf-6-encryption-and-form-fillingStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Sub-skill of pypdf: 6. Encryption and Form Filling.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# 6. Encryption and Form Filling

## 6. Encryption and Form Filling


```python
"""
PDF encryption, decryption, and form handling.
"""
from pypdf import PdfReader, PdfWriter
from pathlib import Path
from typing import Dict, Optional, List

def encrypt_pdf(
    input_path: str,
    output_path: str,
    user_password: str,
    owner_password: Optional[str] = None,
    permissions: Optional[Dict[str, bool]] = None
) -> None:
    """Encrypt PDF with password protection.

    Args:
        input_path: Source PDF file
        output_path: Destination file
        user_password: Password to open the document
        owner_password: Password for full access (defaults to user_password)
        permissions: Dict of permission flags (print, modify, copy, etc.)
    """
    reader = PdfReader(input_path)
    writer = PdfWriter()

    for page in reader.pages:
        writer.add_page(page)

    # Copy metadata if exists
    if reader.metadata:
        writer.add_metadata(reader.metadata)

    # Default permissions (restrictive)
    default_permissions = {
        'print': True,
        'modify': False,
        'copy': False,
        'annotations': True,
        'forms': True,
        'extract': False,
        'assemble': False,
        'print_high_quality': True
    }

    if permissions:
        default_permissions.update(permissions)

    # Encrypt
    owner_pwd = owner_password or user_password
    writer.encrypt(
        user_password=user_password,
        owner_password=owner_pwd,
        permissions_flag=-1  # All permissions by default
    )

    writer.write(output_path)
    print(f"Encrypted PDF saved to: {output_path}")


def decrypt_pdf(
    input_path: str,
    output_path: str,
    password: str
) -> bool:
    """Decrypt a password-protected PDF.

    Args:
        input_path: Encrypted PDF file
        output_path: Destination file (unencrypted)
        password: Password to decrypt

    Returns:
        True if successful, False otherwise
    """
    try:
        reader = PdfReader(input_path)

        if reader.is_encrypted:
            if not reader.decrypt(password):
                print("Incorrect password")
                return False

        writer = PdfWriter()
        for page in reader.pages:
            writer.add_page(page)

        if reader.metadata:
            writer.add_metadata(reader.metadata)

        writer.write(output_path)
        print(f"Decrypted PDF saved to: {output_path}")
        return True

    except Exception as e:
        print(f"Decryption failed: {e}")
        return False


def get_form_fields(input_path: str) -> Dict[str, Dict]:
    """Get all form fields from a PDF."""
    reader = PdfReader(input_path)
    fields = {}

    if reader.get_fields():
        for name, field in reader.get_fields().items():
            field_type = field.get('/FT', '')
            value = field.get('/V', '')

            fields[name] = {
                'type': str(field_type),
                'value': str(value) if value else '',
                'field': field
            }

    return fields


def fill_pdf_form(
    input_path: str,
    output_path: str,
    field_values: Dict[str, str],
    flatten: bool = False
) -> None:
    """Fill PDF form fields with values.

    Args:
        input_path: Source PDF with form fields
        output_path: Destination file
        field_values: Dictionary of field names and values
        flatten: If True, make form fields uneditable
    """
    reader = PdfReader(input_path)
    writer = PdfWriter()

    # Add pages
    for page in reader.pages:
        writer.add_page(page)

    # Update form fields
    writer.update_page_form_field_values(
        writer.pages[0] if writer.pages else None,
        field_values
    )

    if flatten:
        # Note: Full flatten support may require additional processing
        for page in writer.pages:
            if '/Annots' in page:
                del page['/Annots']

    writer.write(output_path)
    print(f"Form filled and saved to: {output_path}")


def list_form_fields_report(input_path: str) -> str:
    """Generate a report of all form fields in a PDF."""
    fields = get_form_fields(input_path)

    if not fields:
        return "No form fields found in this PDF."

    report = ["PDF Form Fields Report", "=" * 40, ""]

    for name, info in fields.items():
        report.append(f"Field: {name}")
        report.append(f"  Type: {info['type']}")
        report.append(f"  Current Value: {info['value'] or '(empty)'}")
        report.append("")

    report.append(f"Total fields: {len(fields)}")

    return "\n".join(report)


# Example usage
# encrypt_pdf('document.pdf', 'encrypted.pdf', 'mypassword')
# decrypt_pdf('encrypted.pdf', 'decrypted.pdf', 'mypassword')
#
# fields = get_form_fields('form.pdf')
# fill_pdf_form('form.pdf', 'filled_form.pdf', {
#     'name': 'John Doe',
#     'date': '2026-01-17',

*Content truncated — see parent skill for full reference.*

Related Skills

tax-form-navigation-verification

5
from vamseeachanta/workspace-hub

Systematic workflow for verifying tax software calculations against entry guide specifications

tax-form-currency-field-handling

5
from vamseeachanta/workspace-hub

Handle currency field rounding and formatting quirks when entering precise decimal values into tax software forms

multi-format-transaction-parser

5
from vamseeachanta/workspace-hub

Parse and consolidate financial transaction data across multiple CSV formats and years

multi-format-csv-parser-with-deduplication

5
from vamseeachanta/workspace-hub

Parse brokerage CSV exports that exist in multiple formats with overlapping data across files

multi-format-csv-detection-and-deduplication

5
from vamseeachanta/workspace-hub

Detect and handle multiple CSV format versions from the same data source; deduplicate records across format variants

freetaxusa-tax-form-navigation-credits

5
from vamseeachanta/workspace-hub

Pattern for navigating FreeTaxUSA's tax form flow, validating auto-calculated credits, and handling form-specific exemptions

freetaxusa-form-entry-recovery

5
from vamseeachanta/workspace-hub

Handle session timeouts and modal dialogs when entering tax forms in FreeTaxUSA

form-1120-preparation-from-expense-sheet

5
from vamseeachanta/workspace-hub

Map cash-basis expense sheet to Form 1120 schedules for C-Corp tax filing, including revenue reconciliation, Schedule L balance sheet reconstruction without prior returns, and gap identification.

form-1120-cash-basis-reconciliation

5
from vamseeachanta/workspace-hub

Reconcile multiple source documents (invoices, expense sheets, bank statements) to establish authoritative cash-basis revenue and expenses for Form 1120 C-Corp filing

form-1120-cash-basis-filing

5
from vamseeachanta/workspace-hub

Complete Form 1120 preparation for C-Corp cash-basis filers — includes TaxAct Business Online interview flow for Schedule L, M-1, M-2

c-corp-form-1120-reconciliation

5
from vamseeachanta/workspace-hub

Reconcile multi-source corporate tax data to prepare Form 1120 using expense sheet as authoritative source

github-actions-cross-platform-validation-gotchas

5
from vamseeachanta/workspace-hub

Execution-time GitHub Actions pitfalls discovered while fixing cross-platform CI workflows — path-filter non-triggers, Windows shell parsing mismatches, and job-scoped validation.