crypt

package
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 26, 2026 License: Apache-2.0 Imports: 13 Imported by: 0

Documentation

Overview

Package crypt provides PDF encryption and decryption support.

This package implements the Standard Security Handler as defined in ISO 32000-2:2020 section 7.6. It supports:

  • RC4-128: RC4 encryption with 128-bit keys (V2/R3, deprecated)
  • AES-128: AES encryption with 128-bit keys (V4/R4)
  • AES-256: AES encryption with 256-bit keys (V5/R6, recommended)

Reading Encrypted PDFs

To decrypt an encrypted PDF, create a StandardHandler from the encryption dictionary, authenticate with a password, then use the handler to decrypt strings and streams:

handler, err := crypt.NewStandardHandler(encryptDict, documentID)
if err != nil {
    return err
}

key, err := handler.Authenticate(password)
if err != nil {
    return err // Invalid password
}

// Decrypt strings and streams
decrypted, err := handler.DecryptString(str, ref)

Writing Encrypted PDFs

To encrypt a PDF when writing, create an Encrypter with the desired algorithm and passwords:

enc, err := crypt.NewEncrypter("AES-256", opts, documentID)
if err != nil {
    return err
}

// Add encryption dictionary to trailer
trailer.Set("Encrypt", enc.EncryptionDict())

// Encrypt strings and streams during serialization
encrypted, err := enc.EncryptString(data, ref)

Index

Constants

View Source
const (
	// PermPrint allows printing the document (bit 3, R2+).
	// For R3+, this allows low-resolution printing only.
	PermPrint int32 = 1 << 2 // 4

	// PermModifyContents allows modifying the document contents (bit 4, R2+).
	PermModifyContents int32 = 1 << 3 // 8

	// PermExtractContent allows copying or extracting text and graphics (bit 5, R2+).
	PermExtractContent int32 = 1 << 4 // 16

	// PermModifyAnnotations allows adding or modifying text annotations
	// and filling interactive form fields (bit 6, R2+).
	// For R3+, if PermFillForms is also set, allows filling forms even
	// without this permission.
	PermModifyAnnotations int32 = 1 << 5 // 32

	// PermFillForms allows filling in existing form fields (bit 9, R3+).
	// This is independent of PermModifyAnnotations.
	PermFillForms int32 = 1 << 8 // 256

	// PermExtractAccessible allows extracting text and graphics for
	// accessibility purposes (bit 10, R3+).
	PermExtractAccessible int32 = 1 << 9 // 512

	// PermAssembleDocument allows assembling the document: inserting,
	// rotating, or deleting pages and creating bookmarks (bit 11, R3+).
	PermAssembleDocument int32 = 1 << 10 // 1024

	// PermPrintHighRes allows high-resolution printing (bit 12, R3+).
	// Without this, printing is limited to low resolution (150 dpi).
	PermPrintHighRes int32 = 1 << 11 // 2048
)

Permission bit flags as defined in ISO 32000-2:2020 Table 22. These are the bit positions (1-indexed in spec, using 0-indexed here).

The /P entry in the encryption dictionary is a 32-bit integer where each bit controls a specific permission. A bit value of 1 means the permission is GRANTED.

Variables

View Source
var (
	// ErrInvalidPassword is returned when authentication fails.
	ErrInvalidPassword = errors.New("invalid or incorrect password")

	// ErrUnsupportedEncryption is returned for encryption versions we don't support.
	ErrUnsupportedEncryption = errors.New("unsupported encryption version or revision")

	// ErrMissingEncryptionParams is returned when required encryption parameters are missing.
	ErrMissingEncryptionParams = errors.New("missing required encryption parameters")
)

Standard errors for encryption operations.

Functions

func AllPermissionsValue

func AllPermissionsValue(revision int) int32

AllPermissionsValue returns the /P value with all permissions granted. This is useful for creating documents with no restrictions.

func HasPermission

func HasPermission(p int32, perm int32) bool

HasPermission checks if a specific permission bit is set in the /P value.

Types

type Algorithm

type Algorithm int

Algorithm specifies the encryption method to use when creating encrypted PDFs.

const (
	// RC4_128 uses RC4 with 128-bit keys (PDF 1.4+, V2/R3).
	// Not recommended for new documents due to RC4 weaknesses.
	RC4_128 Algorithm = iota

	// AES128 uses AES with 128-bit keys (PDF 1.5+, V4/R4).
	// Provides better security than RC4 but AES-256 is preferred.
	AES128

	// AES256 uses AES with 256-bit keys (PDF 1.7 ext 3+, V5/R6).
	// Recommended for maximum security. Uses the modern R6 key derivation.
	AES256
)

func (Algorithm) KeyLength

func (a Algorithm) KeyLength() int

KeyLength returns the encryption key length in bytes for the algorithm.

func (Algorithm) String

func (a Algorithm) String() string

String returns the human-readable name of the algorithm.

func (Algorithm) VersionRevision

func (a Algorithm) VersionRevision() (version, revision int)

VersionRevision returns the PDF encryption version and revision for the algorithm.

type CryptFilter

type CryptFilter struct {
	// CFM is the crypt filter method:
	//   - /V2: RC4 encryption
	//   - /AESV2: AES-128 encryption with 16-byte key
	//   - /AESV3: AES-256 encryption with 32-byte key
	//   - /None: Identity (no encryption)
	CFM core.Name

	// Length is the key length in bytes.
	Length int
}

CryptFilter describes a crypt filter used in V4+ encryption.

type Encrypter

type Encrypter interface {
	// EncryptionDict returns the encryption dictionary to be added to the trailer.
	EncryptionDict() *core.Dictionary

	// FileEncryptionKey returns the derived file encryption key.
	FileEncryptionKey() []byte

	// EncryptString encrypts a PDF string for a specific object.
	EncryptString(data []byte, ref core.Reference) ([]byte, error)

	// EncryptStream returns a WriteCloser that encrypts stream data.
	EncryptStream(w io.Writer, ref core.Reference) (io.WriteCloser, error)

	// Version returns the encryption version (1, 2, 4, or 5).
	Version() int

	// Revision returns the encryption revision (2, 3, 4, 5, or 6).
	Revision() int
}

Encrypter handles PDF encryption for writing.

An Encrypter generates the encryption dictionary entries and provides methods to encrypt strings and streams when serializing a PDF document.

func NewEncrypter

func NewEncrypter(algorithm string, opts EncrypterOptions, documentID []byte) (Encrypter, error)

NewEncrypter creates an Encrypter for the specified algorithm.

The algorithm parameter determines the encryption method:

  • "AES-256" or "AESV3": AES-256 with R6 key derivation (recommended)
  • "AES-128" or "AESV2": AES-128 with R4 (V4/R4)
  • "RC4-128" or "V2": RC4 with 128-bit keys (V2/R3, not recommended)

The documentID should be a random 16-byte value that uniquely identifies the document. If nil, a random ID will be generated.

func NewEncrypterFromHandler

func NewEncrypterFromHandler(h *StandardHandler) (Encrypter, error)

NewEncrypterFromHandler creates an Encrypter that re-uses the file encryption key and dictionary entries from an authenticated StandardHandler. This allows incremental saves to re-encrypt modified objects with the same key as the original document, preserving the existing passwords and permissions.

The handler must have been authenticated before calling this function.

type EncrypterOptions

type EncrypterOptions struct {
	// UserPassword is required to open the document.
	// An empty string allows opening without a password.
	UserPassword string

	// OwnerPassword grants full access regardless of permissions.
	// If empty, defaults to UserPassword.
	OwnerPassword string

	// Permissions is the encoded permission flags (from Permissions.Encode()).
	Permissions int32

	// EncryptMetadata controls whether metadata is encrypted.
	// Default: true
	EncryptMetadata bool
}

EncrypterOptions configures encryption for a new PDF document.

type Error

type Error struct {
	// Version is the encryption version (1, 2, 4, or 5).
	Version int

	// Revision is the encryption revision (2, 3, 4, 5, or 6).
	Revision int

	// Message describes what went wrong.
	Message string

	// Err is the underlying error, if any. Use [errors.Unwrap] or [errors.Is]
	// to check for wrapped sentinel errors.
	Err error
}

Error represents an encryption error with version context. It implements the error interface and supports error wrapping via errors.Unwrap.

Version and Revision identify the PDF encryption algorithm:

  • V1/R2: RC4 with 40-bit key (deprecated)
  • V2/R3: RC4 with variable key length
  • V4/R4: RC4 or AES-128 with crypt filters
  • V5/R5,R6: AES-256

func NewError

func NewError(version, revision int, msg string) *Error

NewError creates a new encryption Error with version context.

func NewErrorf

func NewErrorf(version, revision int, format string, args ...any) *Error

NewErrorf creates a new encryption Error with a formatted message.

func WrapErrorf

func WrapErrorf(version, revision int, err error, format string, args ...any) *Error

WrapErrorf wraps an existing error with version context and a formatted message.

func (*Error) Error

func (e *Error) Error() string

Error returns a formatted error message including version information.

func (*Error) Unwrap

func (e *Error) Unwrap() error

Unwrap returns the underlying error for use with errors.Is and errors.As.

type Handler

type Handler interface {
	// Authenticate checks the password and derives the encryption key.
	// Returns the derived key on success, or ErrInvalidPassword if authentication fails.
	Authenticate(password string) ([]byte, error)

	// DecryptString decrypts a PDF string object.
	// The ref parameter is the indirect reference of the object containing this string.
	DecryptString(s core.String, ref core.Reference) ([]byte, error)

	// DecryptStream returns a reader that decrypts stream data on-the-fly.
	// The ref parameter is the indirect reference of the stream object.
	DecryptStream(r io.Reader, ref core.Reference) (io.Reader, error)

	// Permissions returns the permission flags from the /P entry.
	Permissions() int32

	// Version returns the encryption version (1, 2, 4, or 5).
	Version() int

	// Revision returns the encryption revision (2, 3, 4, 5, or 6).
	Revision() int
}

Handler provides an interface for PDF encryption and decryption.

PDF supports multiple encryption methods, but the Standard Security Handler (filter name /Standard) is by far the most common. It uses RC4 or AES encryption with password-based authentication.

type Permissions

type Permissions struct {
	// Printing permissions
	Print        bool // Allow printing (low-resolution for R3+)
	PrintHighRes bool // Allow high-resolution printing (R3+)

	// Content modification permissions
	ModifyContents    bool // Allow modifying document contents
	ModifyAnnotations bool // Allow adding/modifying annotations and form fields
	AssembleDocument  bool // Allow inserting, rotating, or deleting pages (R3+)

	// Content extraction permissions
	ExtractContent    bool // Allow copying text and graphics
	ExtractAccessible bool // Allow extraction for accessibility purposes (R3+)

	// Form permissions
	FillForms bool // Allow filling form fields (even if ModifyAnnotations is false, R3+)
}

Permissions represents document permission flags from a PDF.

PDF permissions control what operations are allowed on an encrypted PDF. These settings are enforced when opening a document with the user password. Opening with the owner password grants full access regardless of these settings.

Note: PDF permissions are advisory and can be bypassed by malicious software. They provide a level of protection for compliant PDF readers only.

func AllPermissions

func AllPermissions() Permissions

AllPermissions returns Permissions with all operations enabled. Use this for documents that should have no restrictions beyond encryption.

func DecodePermissions

func DecodePermissions(p int32, revision int) Permissions

DecodePermissions converts the int32 /P entry value to Permissions. The revision parameter determines how to interpret certain bits.

For revision 2, PrintHighRes is set equal to Print, and FillForms, ExtractAccessible, and AssembleDocument default to the most permissive interpretation of their related R2 permissions.

func FormFillingPermissions

func FormFillingPermissions() Permissions

FormFillingPermissions returns permissions suitable for form documents. Allows form filling and printing, but prevents other modifications.

func RestrictedPermissions

func RestrictedPermissions() Permissions

RestrictedPermissions returns typical "view-only" permissions. Allows printing and accessibility extraction, but prevents modifications and content copying.

func ViewOnlyPermissions

func ViewOnlyPermissions() Permissions

ViewOnlyPermissions returns the most restrictive permissions. Only allows viewing and accessibility extraction.

func (Permissions) Encode

func (perms Permissions) Encode(revision int) int32

Encode converts Permissions to the int32 /P entry value. The revision parameter determines which permission bits are applicable.

For revision 2, only Print, ModifyContents, ExtractContent, and ModifyAnnotations are meaningful. Other permissions are ignored.

For revision 3 and higher, all permission flags are encoded.

type StandardHandler

type StandardHandler struct {
	// contains filtered or unexported fields
}

StandardHandler implements the PDF Standard Security Handler.

This is the encryption method used by most encrypted PDFs. It supports:

  • V1 (R2): RC4 with 40-bit key (deprecated)
  • V2 (R3): RC4 with variable key length (40-128 bits)
  • V4 (R4): RC4 or AES-128 with crypt filters
  • V5 (R5, R6): AES-256

func NewStandardHandler

func NewStandardHandler(encryptDict *core.Dictionary, documentID []byte) (*StandardHandler, error)

NewStandardHandler creates a new StandardHandler from an encryption dictionary.

The encryptDict is the /Encrypt dictionary from the PDF trailer. The documentID is the first element of the /ID array in the trailer.

func (*StandardHandler) Authenticate

func (h *StandardHandler) Authenticate(password string) ([]byte, error)

Authenticate checks the password and derives the encryption key.

func (*StandardHandler) Clear

func (h *StandardHandler) Clear()

Clear securely zeroes all sensitive key material.

func (*StandardHandler) DecryptStream

func (h *StandardHandler) DecryptStream(r io.Reader, ref core.Reference) (io.Reader, error)

DecryptStream returns a reader that decrypts stream data.

func (*StandardHandler) DecryptString

func (h *StandardHandler) DecryptString(s core.String, ref core.Reference) ([]byte, error)

DecryptString decrypts a PDF string object.

func (*StandardHandler) EncryptMetadata

func (h *StandardHandler) EncryptMetadata() bool

EncryptMetadata returns whether metadata is encrypted.

func (*StandardHandler) Permissions

func (h *StandardHandler) Permissions() int32

Permissions returns the permission flags.

func (*StandardHandler) Revision

func (h *StandardHandler) Revision() int

Revision returns the encryption revision.

func (*StandardHandler) Version

func (h *StandardHandler) Version() int

Version returns the encryption version.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL