Skip to main content

Sign and verify PDF (PAdES), XML (XAdES) and arbitrary files (CAdES/.p7s) with a Uruguayan national ID card (cédula) via PKCS#11. Standards-based; not affiliated with AGESIC.

Project description

cedula-uy-pdf-sign

cedula-uy-pdf-sign banner

Sign and verify PDF (PAdES), XML (XAdES) and arbitrary files (CAdES/.p7s) locally using a Uruguayan national ID card (cédula) through PKCS#11. Standards-based signatures that verify with standard validators, with local chain validation to the Uruguayan national root.

PyPI version Python versions License: Apache 2.0 DeepWiki

⚠️ Disclaimer: This is an experimental, community-maintained project. It is not affiliated with or endorsed by AGESIC, is not officially certified, and does not guarantee the legal validity of the signatures it produces. Use at your own risk. See Legal and compliance for details.

Quick start

Requires Linux with the Uruguayan cédula PKCS#11 middleware installed. The full smart-card setup is in Requirements and Setup on Arch Linux.

uv tool install cedula-uy-pdf-sign     # install
firmauy list-tokens                    # verify the card is detected
firmauy sign-pdf input.pdf                 # sign -> input_firmado.pdf (prompts for the PIN)
firmauy verify-pdf input_firmado.pdf       # verify (offline, chain to the national root)

Overview

cedula-uy-pdf-sign provides a local, developer-oriented workflow for signing and verifying documents and files with a Uruguayan national ID card (cédula) using PKCS#11 middleware: PDF (PAdES), XML (XAdES) and arbitrary files (CAdES/.p7s).

The CLI tool is invoked as firmauy and supports:

  • signing individual PDF documents
  • batch-signing multiple PDFs with a single PKCS#11 session
  • signing XML documents, individually or in batch (XAdES-BES, enveloped)
  • signing arbitrary files, individually or in batch (CAdES-BES detached .p7s, CMS/PKCS#7)
  • verifying signed PDF, XML and detached .p7s files locally, with chain validation to the national root
  • configuring the visible signature position
  • selecting the signature page
  • discovering available PKCS#11 tokens and certificates
  • non-interactive PIN sources for controlled automation workflows

Requirements

Hardware

  • Smart card reader compatible with your OS
  • Uruguayan ID card (cédula) with active certificate

Operating system

This tool targets Linux and is primarily developed and tested on Arch Linux.

Other Linux distributions may work if the required smart card stack, PKCS#11 middleware, and Python environment are correctly configured.

Windows and macOS are not supported.

Python

Python 3.10 or newer.

PKCS#11 middleware

The default PKCS#11 module expected by this tool is:

/usr/lib/pkcs11/libgclib.so

On Arch Linux, this is provided by the cedula-uruguay-pkcs11 AUR package.

Setup on Arch Linux

1. Install smart card stack

sudo pacman -S pcsclite ccid pcsc-tools opensc
sudo systemctl enable --now pcscd

2. Install PKCS#11 library for the Uruguayan ID card

Install the PKCS#11 module from AUR:

yay -S cedula-uruguay-pkcs11
# or manually:
# https://aur.archlinux.org/packages/cedula-uruguay-pkcs11

This is a community-maintained AUR package that repackages the official cédula drivers distributed by the Uruguayan government. It is not an official government package.

It provides the default PKCS#11 module used by this tool:

/usr/lib/pkcs11/libgclib.so

Use version 7.5.0-2 or later; older versions could crash the process when a wrong PIN was entered.

Installation

Installation with uv

uv tool install cedula-uy-pdf-sign

Usage

The CLI tool is invoked as firmauy.

CLI help

Use --help on any command to see all available options:

firmauy --help
firmauy sign-pdf --help
firmauy sign-pdf-batch --help

Sign a single PDF

firmauy sign-pdf input.pdf output_signed.pdf

The tool will prompt for the PKCS#11 PIN interactively.

If the output path is omitted, the signed file is saved as:

<input>_firmado.pdf

Custom signature position

firmauy sign-pdf input.pdf output_signed.pdf --x1 20 --y1 20 --x2 225 --y2 90

Specify page

Pages are 0-indexed. Use -1 to sign the last page.

firmauy sign-pdf input.pdf output_signed.pdf --page 0

Non-interactive PIN

PIN can be supplied without an interactive prompt via --pin-source:

# From an environment variable
firmauy sign-pdf input.pdf output_signed.pdf --pin-source env --pin-env-var MY_PIN

# From stdin
echo "1234" | firmauy sign-pdf input.pdf output_signed.pdf --pin-source stdin

# From a file descriptor
firmauy sign-pdf input.pdf output_signed.pdf --pin-source fd --pin-fd 3

Choose the source by security context (most to least contained):

Source Use for Why
prompt manual use the PIN is only typed; never on disk, argv or env
fd secure automation a dedicated file descriptor you control; not in argv or env
stdin controlled automation not in argv, but a literal echo "$PIN" | can leak to shell history or process lists
env closed/isolated environments only last resort: environment variables are inherited by child processes, readable via /proc/<pid>/environ and ps eww, and can surface in core dumps, container inspection and CI logs

⚠️ However the PIN is supplied, avoid having it appear in shell history, process lists or logs.

Timestamping (TSA, optional)

Embed a trusted timestamp from a Time Stamping Authority (RFC 3161), available on sign-pdf, sign-pdf-batch, sign-any and sign-any-batch (producing the -T level: PAdES-T / CAdES-T):

firmauy sign-pdf input.pdf output_signed.pdf --tsa-url https://your-tsa/endpoint
firmauy sign-any contract.zip --tsa-url https://your-tsa/endpoint   # CAdES-T

Credentialed TSAs. For a TSA that requires authentication, firmauy supports HTTP Basic auth and arbitrary headers (e.g. a Bearer token / API key). The password is read from an environment variable, never from the command line:

# HTTP Basic auth (password from an env var)
TSA_PW='secret' firmauy sign-any contract.zip \
  --tsa-url https://your-tsa/endpoint --tsa-user alice --tsa-pass-env TSA_PW

# Bearer token / API key via a custom header (repeatable)
firmauy sign-any contract.zip --tsa-url https://your-tsa/endpoint \
  --tsa-header "Authorization: Bearer $TOKEN"

TSA timestamping is optional and is not required for the standard Uruguayan cédula signing flow. It adds independent, trusted-time evidence to the signature and involves an external network request to the TSA.

Any public RFC 3161 TSA works here for a technical timestamp; a qualified timestamp requires credentials from an accredited provider (which is what --tsa-user / --tsa-header are for). Client-certificate (mTLS) TSAs are not supported.

Sign batch

Sign multiple PDFs with a single PKCS#11 session. The card PIN is entered only once.

# Explicit file list
firmauy sign-pdf-batch file1.pdf file2.pdf file3.pdf --output-dir ~/signed

# Whole directory
firmauy sign-pdf-batch --input-dir ~/docs --output-dir ~/signed

# Whole directory, recursively
firmauy sign-pdf-batch --input-dir ~/docs --recursive --output-dir ~/signed

# Both can be combined
firmauy sign-pdf-batch extra.pdf --input-dir ~/docs --output-dir ~/signed

Output files are named <original-name>_firmado.pdf by default.

Change the suffix with --suffix:

firmauy sign-pdf-batch --input-dir ~/docs --output-dir ~/signed --suffix _signed

The output directory is created automatically if it does not exist.

All options available for sign-pdf (position, PIN source, reason, TSA, etc.) are also available for sign-pdf-batch.

⚠️ This tool produces cryptographic signatures. Legal validity depends on applicable regulations and use context.

Make sure you have reviewed all documents before signing them in batch.

Sign an XML document (XAdES)

Sign an XML document with the cédula, producing a standards-based XAdES-BES enveloped signature following the XAdES specification (ETSI EN 319 132). It verifies with standard XAdES validators and is suitable for signing structured documents such as electronic fiscal documents (CFE / facturación electrónica).

firmauy sign-xml input.xml output_signed.xml

If the output path is omitted, the signed file is saved as <input>_firmado.xml.

Token discovery, certificate selection and PIN handling work exactly like the PDF commands, so the same options apply: --token-label, --cert-id, --pin-source (with --pin-env-var / --pin-fd), --timezone and --overwrite.

# Non-interactive PIN, same as the PDF commands
echo "1234" | firmauy sign-xml input.xml output_signed.xml --pin-source stdin

Signature profile produced:

  • Format: XAdES-BES, enveloped; the <ds:Signature> is appended as the last child of the document root, with a single reference over the whole document (URI="").
  • Canonicalization: inclusive C14N 1.0 (REC-xml-c14n-20010315).
  • Algorithms: RSA-SHA256 signature, SHA-256 digests.
  • Signed properties: signing time, signing-certificate digest and data-object format.

⚠️ This is the XAdES-BES level (no trusted timestamp). The produced signature is cryptographically valid and conforms to the XAdES standard; legal and regulatory validity depends on your use case and applicable rules.

Sign multiple XML documents (batch)

Sign many XML files with a single PKCS#11 session (the card PIN is entered only once). This mirrors sign-pdf-batch for PDFs and is convenient for bulk workflows such as electronic invoicing.

# Explicit file list
firmauy sign-xml-batch file1.xml file2.xml --output-dir ~/signed

# Whole directory (add --recursive to descend into subfolders)
firmauy sign-xml-batch --input-dir ~/docs --output-dir ~/signed

For unattended bulk signing, supply the PIN non-interactively (entered once for the whole batch), exactly as with the other commands:

# PIN from an environment variable
firmauy sign-xml-batch --input-dir ~/docs --output-dir ~/signed \
  --pin-source env --pin-env-var MY_PIN

# PIN from stdin
echo "1234" | firmauy sign-xml-batch --input-dir ~/docs --output-dir ~/signed --pin-source stdin

Output files are named <original-name>_firmado.xml by default; change it with --suffix. The output directory is created automatically. All the sign-xml options (token, certificate and PIN selection, --timezone, --overwrite) also apply.

Make sure you have reviewed all documents before signing them in batch.

Sign any file (CAdES / .p7s)

Sign any file (not just PDF or XML) with the cédula, producing a standards-based CAdES-BES detached signature (RFC 5652 CMS / PKCS#7), following ETSI EN 319 122. This completes the AdES triad alongside PAdES (PDF) and XAdES (XML).

firmauy sign-any contract.zip

The signature is detached: the original file is left untouched and the signature is written to a separate .p7s. If the output path is omitted, it is saved next to the input as <input-name>.p7s (e.g. contract.zipcontract.zip.p7s).

Token discovery, certificate selection and PIN handling work exactly like the PDF/XML commands, so the same options apply: --token-label, --cert-id, --pin-source (with --pin-env-var / --pin-fd), --tsa-url and --overwrite.

# Non-interactive PIN, same as the other commands
echo "1234" | firmauy sign-any contract.zip --pin-source stdin

Signature profile produced:

  • Format: CAdES-BES, detached (RFC 5652 CMS / PKCS#7); the original bytes are not embedded.
  • Algorithms: RSA-SHA256 signature, SHA-256 message digest.
  • Signed attributes: content type, message digest and signing-certificate-v2 (the CMS counterpart of the XAdES SigningCertificate).

It verifies with standard CMS tooling, e.g. openssl cms -verify -binary -inform DER -in contract.zip.p7s -content contract.zip, or with firmauy verify-any (see below).

⚠️ This is the CAdES-BES level (no trusted timestamp). Passing --tsa-url embeds a trusted timestamp (CAdES-T), at the cost of contacting that external TSA. The produced signature is cryptographically valid and conforms to the CMS/CAdES standard; legal and regulatory validity depends on your use case and applicable rules.

Sign multiple files (batch)

Sign many files with a single PKCS#11 session (the card PIN is entered only once), mirroring the PDF and XML batch commands.

# Explicit file list
firmauy sign-any-batch a.zip b.bin report.docx --output-dir ~/signed

# Whole directory (add --recursive to descend into subfolders)
firmauy sign-any-batch --input-dir ~/docs --output-dir ~/signed

# Restrict to a glob (e.g. only .zip files)
firmauy sign-any-batch --input-dir ~/docs --glob '*.zip' --output-dir ~/signed

Each output is named <original-name>.p7s inside --output-dir (the directory is created automatically). The PIN can be supplied non-interactively (entered once for the whole batch) with --pin-source, exactly as with the other commands. All the sign-any options (token, certificate and PIN selection, --tsa-url, --overwrite) also apply.

Make sure you have reviewed all files before signing them in batch.

Verify a signed XML

Verify a signed XAdES XML locally: signature integrity plus the certificate chain up to the Uruguayan national root. No smart card is needed to verify.

The national CA certificates are bundled with the package (each verified against a pinned fingerprint), so chain validation works offline, out of the box, with no setup needed:

# Verify (integrity + chain to the national root): bundled CAs are used automatically
firmauy verify-xml signed.xml

# Only check signature integrity, skip the certificate chain
firmauy verify-xml signed.xml --no-trust

# Override the trust anchors with your own (PEM bundle: root + intermediates)
firmauy verify-xml signed.xml --ca-file my-cas.pem

# Also check certificate revocation via CRL/OCSP (needs network)
firmauy verify-xml signed.xml --check-revocation

Trust anchors are resolved in order: --ca-file, then the cache (firmauy fetch-cas), then the bundled certificates. With --no-trust, verification reports signature integrity only (level 1).

It reports a per-check breakdown and an overall indication:

  • VALID integrity holds and the chain is trusted up to the national root.
  • INDETERMINATE the signature is intact, but the chain is not trusted (e.g. an unknown issuer) or trust was skipped with --no-trust.
  • INVALID the signature is broken or the document was modified after signing.

Exit codes: 0 VALID, 1 INVALID, 2 INDETERMINATE.

What it checks: the SignedInfo signature, each reference digest (so any change to the document is detected), the XAdES signing-certificate binding, and the certificate chain to a trusted root (RFC 5280 path validation).

Revocation (CRL/OCSP) is off by default (offline). Enable it with --check-revocation, which fetches revocation data and fails the chain if the certificate is revoked or that data cannot be obtained.

⚠️ For cédula signatures, --check-revocation currently cannot succeed: the leaf certificate's CRL distribution point is on the Ministerio del Interior server (ca.minterior.gub.uy), which has been decommissioned and returns HTTP 501. Since revocation is hard-fail, unreachable revocation data fails the chain. Use the default (no --check-revocation) until the CRL endpoint is restored.

⚠️ Limitations: since XAdES-BES carries no trusted timestamp, certificate validity and revocation are evaluated at verification time, not at signing time. The bundled national CA certificates expire (2031) and can be rotated by the issuer; re-run firmauy fetch-cas to refresh from the network, or use --ca-file.

Trust anchors: bundled, with pinned fingerprints

The package bundles these certificates as built-in trust anchors (public certificates, see data/PROVENANCE.md); fetch-cas can refresh them from the sources below. Every certificate (bundled, cached, downloaded, or supplied via --ca-file / --from-file) is verified against a pinned SHA-256 fingerprint, and the intermediate is additionally checked to be signed by the root, so the origin of the bytes never matters.

Certificate Source(s), tried in order
AC Raíz Nacional de Uruguay (AGESIC) https://www.uce.gub.uy/acrn/acrn.cer
AC Ministerio del Interior (intermediate) https://ca.minterior.gub.uy/certificados/MICA.cer (official), then https://crt.sh/?d=29172099 (fallback)

Note on the intermediate source. The Ministerio del Interior CA repository (ca.minterior.gub.uy) has been decommissioned and now returns HTTP 501 for every request, and AGESIC's trust-list page still points at that dead URL. fetch-cas therefore falls back to the byte-identical copy in the public Certificate Transparency log (crt.sh), retrying transient errors. This is safe regardless of the source: the bytes are accepted only if they match the pinned fingerprint below and are signed by the pinned root. If the official server is restored, it is used first.

fetch-cas is optional: verification already uses the bundled certificates; it only refreshes a per-user cache. If you do run it and crt.sh is flaky, you can seed the intermediate from a local copy with --from-file instead of downloading. The fingerprint pin makes the file's origin irrelevant; a copy that doesn't match a pin is ignored and downloaded instead:

# Seed the intermediate from a local file; the root still downloads (it is reliable)
firmauy fetch-cas --from-file mica.pem

# Fully offline: supply both (a bundle, or repeat --from-file)
firmauy fetch-cas --from-file acrn.pem --from-file mica.pem

Any certificate matching a pinned fingerprint is taken from the supplied file(s) instead of being downloaded. (The cédula middleware does not install these certificates, and the package already bundles them, so you rarely need this.)

Pinned fingerprints (SHA-256 of each certificate, DER):

root (ACRN):        5533a0401f612c688ebce5bf53f2ec14a734eb178bfae00e50e85dae6723078a
intermediate (MICA): a29cad5c89aa49cff81f17f45c42fd44685510246d9ab5d031448e2fda2517be

You can audit them yourself:

# Root, from the official source:
curl -s https://www.uce.gub.uy/acrn/acrn.cer | openssl x509 -noout -fingerprint -sha256
# SHA256 Fingerprint=55:33:A0:40:...:8A  (same bytes, openssl prints them upper-case with colons)

# Intermediate, from the Certificate Transparency log:
curl -s -A "firmauy (+https://pypi.org/project/cedula-uy-pdf-sign)" "https://crt.sh/?d=29172099" \
  | openssl x509 -noout -fingerprint -sha256
# SHA256 Fingerprint=A2:9C:AD:5C:...:BE

Verify a signed PDF

Verify the signatures in a signed PDF (PAdES) locally, mirroring verify-xml:

firmauy verify-pdf signed.pdf
firmauy verify-pdf signed.pdf --no-trust
firmauy verify-pdf signed.pdf --ca-file my-cas.pem
firmauy verify-pdf signed.pdf --check-revocation

For each signature it checks integrity (intact and cryptographically valid), coverage (whether the signature covers the whole file or content was added afterwards), and the certificate chain to the national root. Trust anchors work exactly like verify-xml (bundled by default; override with --ca-file).

Same indication model (VALID / INDETERMINATE / INVALID) and exit codes as verify-xml. When a PDF has multiple signatures, the overall indication is the worst one.

Verify a detached signature (.p7s)

Verify a detached CAdES/.p7s signature over a file, mirroring verify-xml / verify-pdf. Because the signature is detached, both the original file and its .p7s are required:

# Defaults to <input>.p7s next to the file (integrity + chain to the national root)
firmauy verify-any contract.zip

# Pass the signature path explicitly
firmauy verify-any contract.zip contract.zip.p7s

# Only check signature integrity, skip the certificate chain
firmauy verify-any contract.zip --no-trust

# Use your own trust anchors / also check revocation (needs network)
firmauy verify-any contract.zip --ca-file my-cas.pem
firmauy verify-any contract.zip --check-revocation

It checks integrity (the signed bytes hash to the embedded digest and the signature is cryptographically valid) and the certificate chain to the national root. Trust anchors work exactly like verify-xml (bundled by default; override with --ca-file). A detached CMS signature has no PDF-style coverage notion: it signs exactly the bytes it is verified against.

Same indication model (VALID / INDETERMINATE / INVALID) and exit codes as verify-xml.

About verification (scope and limitations)

verify-xml, verify-pdf and verify-any perform a local, technical verification based on open standards (XMLDSig / XAdES, PAdES, CMS / CAdES, X.509 path validation per RFC 5280, and CRL/OCSP), anchored to the Uruguayan national root.

  • This is not the official validator and does not provide an official or legally binding validation. For legal validity, use the official channels.
  • On the decisive questions (integrity, cryptographic validity, chain to the national root, revocation) the result should agree with any standards-conformant validator, because it follows the same standards and the same PKI, not because it reproduces any specific tool.
  • It is a focused implementation: it does not cover every XAdES / PAdES profile or policy feature (for example signature policies or long-term / archival levels), so verdicts may differ from other validators on edge cases.

A VALID result is a technical assessment, not a statement of legal validity.

Discover tokens and certificates

List all visible PKCS#11 tokens:

firmauy list-tokens

List certificates available on a token:

firmauy list-certs

Security considerations

  • Never pass the PIN directly as a command-line argument.
  • Prefer interactive PIN entry for manual use.
  • For automation, prefer protected file descriptors or controlled environments.
  • Review every document before signing it.
  • Use batch signing only in trusted workflows.
  • Keep your smart card, reader, PIN, and PKCS#11 middleware under your own control.

Privacy

This tool is designed to run entirely locally.

It does not collect, transmit, or store any user data externally.

All cryptographic operations are performed on the user's machine and/or the connected smart card.

Note: Optional features such as timestamping (TSA) may involve external network requests, depending on user configuration.

Note: the signing commands print a summary that includes identifying data (signer name, certificate issuer, certificate serial number and PKCS#11 key ID). This stays on your machine, but in batch or automated pipelines that output can end up in CI or centralized logs. Pass --quiet (-q) to the sign-pdf, sign-pdf-batch, sign-xml, sign-xml-batch, sign-any and sign-any-batch commands to suppress that block while still signing.

Signature verification

For authoritative verification, especially for any legal or official purpose, use the official validator provided by AGESIC (no affiliation implied):

https://firma.gub.uy/

This tool also verifies signatures locally (firmauy verify-pdf / verify-xml / verify-any, with chain validation to the Uruguayan national root, no smart card needed; see Usage). That is a convenient technical check, not a replacement for the official validator.

Note that a successful technical verification does not by itself imply legal validity for every use case. See Legal and compliance.

Additional notes

  • The default visual signature appearance was modeled on real documents signed with the Uruguayan ID card.
  • This project focuses on practical interoperability rather than strict compliance with any specific implementation.

Legal and compliance

This project is copyright-registered, experimental, community-maintained, and not officially certified.

It is intended for developers and technically proficient users who understand the implications of using smart cards, PKCS#11 middleware, and digital signatures.

This project:

  • is not affiliated with or endorsed by AGESIC
  • does not claim official certification or compliance
  • does not guarantee the legal validity of generated signatures
  • is provided for technical and educational purposes

While it uses standard cryptographic mechanisms and aims to align with Uruguayan digital signature practices, the generated signatures should not be assumed valid for legal or regulatory use without independent verification. Users are solely responsible for ensuring that generated signatures meet any legal or regulatory requirements applicable to their use case.

Intended use

Local, developer-oriented signing and verification using a Uruguayan ID card through PKCS#11. It is especially aimed at users who want to:

  • sign PDFs (PAdES), XML documents (XAdES), and arbitrary files (CAdES/.p7s) locally
  • verify those signatures locally, including the certificate chain to the national root
  • understand and reproduce a PKCS#11-based signing workflow
  • experiment with smart card integration on Linux
  • build automation around signing and verification under their own responsibility

It is not intended to replace official, certified, or legally guaranteed signing platforms.

Scope

This tool focuses on technical integration with PKCS#11: signing (PDF/PAdES, XML/XAdES, files/CAdES) and local, standards-based verification, including certificate-chain validation to the Uruguayan national root.

It is not an official validator: it does not consult the official trust-service status list (TSL) or evaluate accreditation / qualified status, provide legal guarantees, or replace certified signing platforms.

Copyright / software registration

This software has been registered as a computer program with the Uruguayan Dirección Nacional de la Propiedad Industrial y Registro de Software.

The registration was published in the official Boletín de la Propiedad Industrial Nº 357:

  • Entry: Software (w/000235)
  • Filing date: 2026-04-15
  • Applicant: Carlos Andrés Planchón Prestes [UY]
  • Title: cedula-uy-pdf-sign
  • Classification: Programa de ordenador
  • Official publication: Boletín de la Propiedad Industrial Nº 357

This registration concerns the authorship of the software as a copyrighted work. It does not imply official certification, endorsement, legal validity of generated signatures, or regulatory compliance of any specific use case. See Legal and compliance.

Development

The project uses uv for environment and dependency management.

# Clone the repository
git clone https://github.com/carlosplanchon/cedula-uy-pdf-sign.git
cd cedula-uy-pdf-sign

# Create the environment and install dependencies (runtime + dev)
uv sync

# Run the test suite (PKCS#11 integration tests need SoftHSM2, see below)
uv run pytest

# Run the CLI from the working tree
uv run firmauy --help

The package source lives under src/cedula_uy_pdf_sign/; tests under tests/.

Developing without the real card (SoftHSM2)

Entering the wrong PIN too many times blocks the cédula, so you should not develop against the real card. Instead, you can run the full signing pipeline against a software PKCS#11 token (SoftHSM2) that mimics a cédula closely enough to exercise token discovery, certificate selection, PIN handling and signing.

# Arch Linux: install the software token + tooling
sudo pacman -S softhsm opensc openssl

# Provision a throwaway "fake cédula" token under ./.softhsm
bash scripts/dev-softhsm-setup.sh

The script prints ready-to-run firmauy list-certs / firmauy sign-pdf commands pointing at the SoftHSM module. The resulting PDF is a cryptographically valid signature, but it will not validate as a cédula signature on firma.gub.uy (the issuing CA is a local fake, by design). Reset everything with rm -rf .softhsm.

The token persists under .softhsm, so this doubles as a normal development loop: run firmauy by hand as often as you like (signing test PDFs, trying signature positions with --x1/--y1/..., exercising sign-pdf-batch, reproducing a reported bug) while iterating on the code, without the card and without risking PIN lockout. The real card is then only needed for a final validation run and for middleware-specific behaviour.

The same setup powers the end-to-end integration tests (tests/test_integration_pkcs11.py, test_integration_xades.py, test_integration_cms.py) that exercise the real PKCS#11 path: signing PDF (PAdES), XML (XAdES) and arbitrary files (CAdES/.p7s) plus cryptographic verification of the result, and the selection/error branches that are unsafe to reproduce on the real card (expired certificate, certificate without a private key, multiple tokens, certificate scoring and --cert-id override). They are skipped automatically when SoftHSM2 / OpenSC / OpenSSL (or signxml) are not installed, so uv run pytest works either way.

Contributing & reporting issues

Bug reports, questions, and pull requests are welcome.

Feel free to open an issue on GitHub.

Acknowledgements

  • @nicolasgutierrezdev: provided reference for the signature appearance inspired by signatures generated using the Uruguayan ID card (cédula), and helped test the XAdES (XML) signing feature.

License

This project is licensed under the Apache License 2.0.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cedula_uy_pdf_sign-0.9.0.tar.gz (74.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

cedula_uy_pdf_sign-0.9.0-py3-none-any.whl (55.3 kB view details)

Uploaded Python 3

File details

Details for the file cedula_uy_pdf_sign-0.9.0.tar.gz.

File metadata

  • Download URL: cedula_uy_pdf_sign-0.9.0.tar.gz
  • Upload date:
  • Size: 74.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for cedula_uy_pdf_sign-0.9.0.tar.gz
Algorithm Hash digest
SHA256 ecc0e506a247b55a04a7de9cf1e4691464e867dc74f5affc38ee2ff11884b645
MD5 cf22c741bbeb71c5f6fa20b533483fe6
BLAKE2b-256 db1133fd0b23990b14daf160159d4cb0ae963ba86292b5a2e17c1cf3733c79e1

See more details on using hashes here.

File details

Details for the file cedula_uy_pdf_sign-0.9.0-py3-none-any.whl.

File metadata

File hashes

Hashes for cedula_uy_pdf_sign-0.9.0-py3-none-any.whl
Algorithm Hash digest
SHA256 ae43a3132a043a8f45157f8491fcefdf5467788a98f51281e310be53c3345781
MD5 2f4909dfcb9eb34b64fae74bc52c3669
BLAKE2b-256 e256ca903d6a534ef4559e616f07010e5c53e5e389f8c594629de9c30f332207

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page