Encryption and signing

Simple encryption

If the argument is a string object, it is used as the User password to the PDF. The argument can also be an instance of the class reportlab.lib.pdfencrypt.StandardEncryption, which allows more finegrained control over encryption settings

pisaStatus = pisa.CreatePDF(
        sourceHtml,
        encrypt="MyPassword",
        dest=resultFile)

Complex encryption

The StandardEncryption constructor takes the following arguments:

def __init__(self, userPassword,
    ownerPassword=None,
    canPrint=1,
    canModify=1,
    canCopy=1,
    canAnnotate=1,
    strength=40):

The userPassword and ownerPassword parameters set the relevant password on the encrypted PDF. The boolean flags canPrint, canModify, canCopy, canAnnotate determine wether a user can perform the corresponding actions on the PDF when only a user password has been supplied. If the user supplies the owner password while opening the PDF, all actions can be performed regardless of the flags

from reportlab.lib import pdfencrypt
enc=pdfencrypt.StandardEncryption("rptlab",canPrint=0)
pisaStatus = pisa.CreatePDF(
        sourceHtml,
        encrypt=enc,
        dest=resultFile)

Signing pdf

CreatePDF now has a signature parameter that allow to pass signature configuration

Simple Signing

Signature use Pyhanko internally, so signature parameter allow many of the available configurations on that documentation.

The control parameters are required:

  • engine: Possible options pkcs12, pkcs11, simple, define what engine load for manage certificates.

  • type: Possible options lta and simple, define the mode for signing

  • passphrase: Password to decrypt private key (not required on pkcs11).

Note

passphrase is always required, because None value prevents signing and empty string failed

signature={
    'engine': 'simple',
    'type': 'simple',
    'passphrase': 'mypassword',
    'key': 'enckey.pem',
    'cert': 'cert.pem',
    'ca_chain': 'chain.pem'
}
pisaStatus = pisa.CreatePDF(
        sourceHtml,
        signature=signature,
        dest=resultFile)

ca_chain: Could be a list or Path, define the chain of trust

PKCS12 Signing

pfx_file: String or Path to pkcs12 file.

signature={
    'engine': 'pkcs12',
    'type': 'simple',
    'pfx_file': 'yourpkcs12file.p12',
    'passphrase': 'yourpassword'
}

PKCS11 Signing

Note

You need to install pyHanko[pkcs11]

Must of the above settings are form

You configure PdfSignatureMetadata using meta keyword, and ValidationContext using validation_context. In my test use of ca_chain append root certificates to signature, and other_certs allow to append chain certificates that are ignored from ca_chain when build pdf signature.

signature={
    'engine': 'pkcs11',
    'type': 'lta',
    'lib_location': "/usr/lib/x64-athena/libASEP11.so",
    'tsa': "http://tsa.example.com/tsa/",
    'slot_no': 0,
    #'token_label': 'ChipDoc',
    'user_pin': '000000',
    'cert_label':  'cetificate label on smartcard',
    'key_label': 'key label label on smartcard',
    'meta': {
        'use_pades_lta': True,
        'signer_key_usage': {'digital_signature', 'non_repudiation'},
    },
    'ca_chain': ["/path/to/ca.pem" ],
    'validation_context': {'revocation_mode': "hard-fail",
                           'trust_roots':
                               ['/path/to/ca/in/certitificate.pem' ],
                           'other_certs':['/path/to/external_chains.pem' ],
                           'retroactive_revinfo': True,
                           'crls': ['http://your.crl', '/path/to/file.crl']}
}