Skip to main content

Standalone PDF digital-signature library: PAdES/CMS signing (PFX, USB token, Windows store), timestamp, LTV, and the Green-Tick verified appearance — zero external dependencies.

Project description

ATick

ATick

Standalone PDF digital-signature library for Python — PAdES / CMS signing with zero external dependencies.

PyPI Python PAdES Zero deps License: AGPL v3 Last commit


ATick signs PDFs the way Adobe Acrobat and the EU DSS do — PAdES baseline signatures with timestamps and long-term validation — but everything ships inside the one package, so there are no dependencies to install at all. pip install atick and you are done. There's a Python API and a full command-line tool.

import atick

signed = atick.sign_pfx(
    open("doc.pdf", "rb").read(),
    pfx=open("my.pfx", "rb").read(), password="••••",
    style=atick.Style(cn="Aniket Chaturvedi", reason="Approved"),
    placements=[(1, (300, 55, 575, 175))],
    pades=True, timestamp=True, ltv=True,     # PAdES-B-LT
)
open("signed.pdf", "wb").write(signed)

The green tick your readers trust

ATick draws a verified-signature appearance with a green tick. When the certificate is valid and trusted, Adobe Reader / Acrobat shows “Signed and all signatures are valid.”

Adobe — signed and all signatures are valid

Adobe colours that same mark by the signature's real status — you don't draw these, Adobe does:


Valid & trusted
green tick

Validity unknown
yellow “?”

Not verified
“?” not validated

Invalid
red cross

The green tick appears only when the signature is valid and the certificate chains to a root Adobe trusts.


Why ATick

ATick
Zero dependencies the crypto, PFX/PKCS#12, PKCS#11, image decode, timestamp & LTV are all built in — nothing else to install
Four signing back-ends .pfx/.p12 or .pem file · USB token / smart-card / HSM (PKCS#11) · Windows certificate store (its certificate picker)
Full PAdES B-B, B-T, B-LT, B-LTA — recognised by Adobe Acrobat as “PAdES Signature Level”
Indian eSign the full CCA eSign flow (rawrsa / PKCS7 / PKCS7pdf / PKCS7complete)
CLI + API every feature from Python or the terminal (atick …)
Clear errors every failure is a normal Python exception (atick.AtickError) you can catch

Features (A → Z)

Feature How
Sign with a .pfx / .p12 / .pem atick.sign_pfx(pdf, pfx=, password=, …) — PKCS#12 or PEM (key + certs), auto-detected
Date / time format Style(date_format="%Y-%m-%d %H:%M:%S") (any strftime) · date="…" fixed · date="" none
Sign with a USB token / HSM (PKCS#11) atick.sign_pkcs11(pdf, dll=, pin=, serial=, …) · list with atick.pkcs11_list(dll, pin)
Sign with the Windows store (certificate picker) atick.sign_winstore(pdf, thumbprint=None, …)
PAdES levels B-B / B-T / B-LT / B-LTA pades=True + timestamp=True + ltv=True + lta=True
Hash algorithm hash_algo="sha256" | "sha384" | "sha512" (signature = RSA PKCS#1 v1.5)
Timestamp authority a timestamp service is already built in — or use your own with tsa_url= (and tsa_auth=(user, pass) if it needs a login)
Long-term validation (LTV) ltv=True embeds the certificate chain and its revocation (CRL/OCSP) so the signature keeps verifying for years
Multi-page / custom coordinates placements=[(page, (x1,y1,x2,y2)), …]
Signature layout mode="single" (one signature, on one or many pages) · mode="shared" (several fields all showing the same signature). For several independent signatures (different signers/values), sign the document again — see Multi-signatory — or pre-create the fields with atick.prepare_fields(...)
Multi-signatory sign an already-signed PDF again (each person signs in turn). Every signature is its own revision — Adobe shows Rev 1, Rev 2, … — and all of them stay valid. Use a different field_name per signer (auto-handled by default)
Certification (DocMDP) certify=atick.Certify.NO_CHANGES | FORM_FILLING | FORM_FILLING_ANNOTATIONS
Field locking (FieldMDP) lock_fields=["*"] (all) or ["FieldA", …]
Pre-sign checks verify=True (not expired / CRL / OCSP) and trusted_roots=[sha1, …] (chain to a pinned root — built from AIA)
Document metadata atick.set_metadata(pdf, title=, author=, subject=, keywords=, application=, created=, modified=)
Password protection encrypt_password= (+ owner_password=) for the output; open_password= for an encrypted input; atick.decrypt(pdf, pw)
Appearance atick.Style(cn, org, ou, location, reason, text, date, image, …) — auto-fit text, transparent logo
The mark the ? (Adobe greens it), an always-green tick, or nothing — see The mark
CN on the left (Adobe-style) Style(image="cn") — the signer name as text on the left instead of a logo
Distinguished name Style(dn="CN=…, O=…, C=IN") — shown under the "Signed by:" line
Custom-text-only appearance Style(body="*APPROVED*\nby *Aniket*") — only your text; \n = line, *x* = bold
Auto-wrap long names long names wrap to more lines instead of shrinking the font
Invisible signature placements=[] — valid signature, nothing drawn
Sign an already-signed PDF sign again (incremental) — existing signatures stay valid; field name auto-uniquified (Atick_1, Atick_2, …)
Container only prepare_deferred_multi(...) — appearance + empty container, signed later
Document timestamp lta=True adds it while signing; atick.add_doctimestamp(pdf) adds one to an already-signed PDF afterwards (PAdES-B-LTA)
Fast signing revocation cache (ON by default): repeated signing with the same cert reuses CRL/OCSP — atick.set_fast_signing(False) to disable
Indian eSign two-step CCA flow — needs the separate managex-xml-sdk package (pip install managex-xml-sdk) to sign the request XML; then embed (PKCS7*) / embed_rawrsa (rawrsa) the ESP reply
Detached CMS / raw signature atick.cms_pfx(data, pfx, pw) · atick.sign_hash_pfx(data, pfx, pw)
Low-level field API prepare, prepare_fields, sign_field, embed for template / remote-key flows

Install

pip install atick

No other packages are required. (Windows-store signing is Windows-only; everything else is cross-platform.)


The three signing methods

atick.sign_pfx(pdf, pfx=, password=, style=, placements=)              # .pfx / .p12 / .pem (auto-detected)
atick.sign_pkcs11(pdf, dll=, pin=, serial=, style=, placements=)      # USB token / smart-card / HSM
atick.sign_winstore(pdf, style=, placements=, thumbprint=None)           # Windows store (certificate picker)

A PEM file (unencrypted PKCS#8/PKCS#1 key + one or more CERTIFICATE blocks) works in the same sign_pfx call — pass its bytes as pfx= (and password=""); the format is auto-detected.

All three accept the same options: pades=, hash_algo=, timestamp=, tsa_url=, tsa_auth=, ltv=, lta=, certify=, lock_fields=, verify=, trusted_roots=, plus (on sign_pfx) open_password=, encrypt_password=, owner_password=.


The mark

The little icon in the appearance — what Adobe shows for the signature's validity:

atick.Style(cn="…", green_tick=True)     # the "?" mark — Adobe paints it GREEN for a valid+trusted cert, RED if invalid
atick.Style(cn="…", always_check=True)   # our green-tick graphic as the base — Adobe still reds it if the signature is bad
atick.Style(cn="…", green_tick=False)    # no mark at all — a plain, basic signature

Colour the mark with any Python colour: mark_color="#E53935", "blue", (255, 140, 0) — or a gradient mark_gradient=["red", "orange", "yellow"]. The mark is always centred in the appearance.


Custom appearance

atick.Style(cn="Aniket Chaturvedi", image="cn")                       # CN as text on the LEFT (Adobe-style)
atick.Style(cn="Aniket Chaturvedi", dn="CN=Aniket, O=Personal, C=IN") # DN under the "Signed by:" line
atick.Style(body="*APPROVED*\nReviewed by: *Aniket*\nLegally *binding*.")  # ONLY this text; \n = line, *x* = bold
atick.Style(cn="…", image="logo.png")                                 # your own logo (default = ATick logo)
atick.Style(cn="…", image=False)                                      # no logo

Long names wrap onto more lines instead of shrinking the font, so the appearance never overflows.


Fast signing

ON by default. With LTV on, the first signature fetches the certificate's CRL/OCSP; ATick caches it in-memory, so every later signature with the same certificate reuses it instead of re-fetching — a big speed-up for batch / multi-signature runs (≈ 6× in practice). Timestamps are never cached (each must be unique).

atick.set_fast_signing(False)      # always fetch fresh (also clears the cache)
atick.clear_revocation_cache()     # forget cached revocation (e.g. after changing certificate)

Sign an already-signed PDF

signed = atick.sign_pfx(already_signed_pdf, pfx=, password=, style=, placements=)

ATick signs as an incremental update, so existing signatures keep their byte ranges and stay valid. The field name is auto-uniquified (Atick_1, Atick_2, …), so re-signing never collides; pass field_name="…" for a specific name.


Indian eSign (every CCA API version)

eSign needs one extra package. Signing the eSign request XML requires the separate managex-xml-sdk package — pip install managex-xml-sdk. It is only needed for eSign; every other ATick feature works with no extra installs.

A two-step flow — sign the eSign request XML with managex-xml-sdk, then embed the ESP's reply with ATick:

prepared, ctx = atick.prepare_deferred_multi(pdf, style, placements, sub_filter="adbe.pkcs7.detached")
input_hash_hex = bytes(ctx["digest"]).hex()        # the InputHash for the eSign request XML
# ... build the <Esign …> request, sign it with managex-xml-sdk, POST to the ESP, read EsignResp ...
signed = atick.embed(prepared, doc_signature_cms)  # pkcs7 / pkcs7Pdf / pkcs7complete
# rawrsa: atick.embed_rawrsa(prepared, raw_sig, user_cert)

pkcs7Pdf / pkcs7complete responses already carry the chain + revocation + timestamp, so the embedded signature is LTV-complete. See examples/esign/.


PAdES levels

atick.sign_pfx(pdf, pfx=, password=, style=, placements=, pades=True)             # B-B
atick.sign_pfx(pdf, , pades=True, timestamp=True)                                    # B-T
atick.sign_pfx(pdf, , pades=True, timestamp=True, ltv=True)                          # B-LT
atick.sign_pfx(pdf, , pades=True, timestamp=True, lta=True)                          # B-LTA

B-LT/B-LTA embed the complete validation material (chain + CRL + OCSP + VRI + /Extensions /ESIC) so Adobe Acrobat shows “PAdES Signature Level: B-LT” in the advanced signature properties.


Command line

Every feature is available from the terminal too:

atick sign in.pdf out.pdf --pfx my.pfx --password ••• \
      --cn "Aniket Chaturvedi" --reason Approved \
      --timestamp --ltv --always-check --cn-left --dn "CN=Aniket, O=Personal, C=IN" \
      --page 1 --rect 300,55,575,175

atick sign in.pdf out.pdf --pfx my.pfx --password ••• --body "*APPROVED*\nby *Aniket*"  # custom text only
atick sign-token    in.pdf out.pdf --dll lib.dll --pin ••• --serial HEX --ltv
atick sign-winstore in.pdf out.pdf            # opens the Windows certificate picker
atick list-token    --dll lib.dll --pin •••
atick esign-prepare in.pdf prepared.pdf --certify form-annots   # eSign step 1 (prints the InputHash)
atick esign-embed   prepared.pdf response.xml out.pdf           # eSign step 2 (embeds the ESP reply)
atick metadata      in.pdf out.pdf --title "Agreement" --author "Aniket"
atick decrypt       in.pdf out.pdf --password •••
atick version

Run atick <command> -h for the complete option list (or python -m atick …). Every failure is a clean Python atick.AtickError (or a TypeError for a wrong argument) that you can catch.


Examples

Self-contained, runnable scripts live in examples/ (each writes to examples/signed/):

01_sign_pfx · 02_pades_levels · 03_appearance · 04_certify_and_lock · 05_multi_placement · 06_token_pkcs11 · 07_windows_store · 08_deferred_esign · 09_verify_certificate · 10_encrypted · 11_mark_color · 12_metadata · 13_hash_algorithms · 14_field_api · 16_invisible · 17_multi_revision (rev1 → rev2 → rev3) · 18_date_and_pem (date formats + PEM signing) · always_green_tick · green_tick · without_green_tick · make_container · sign_already_signed · document_timestamp · fast_signing · esign/ (eSign 2-step: esign_prepare + esign_embed).

Every example uses only ATick (the esign/ flow also uses your managex-xml-sdk to sign the request XML). Run any with python examples/<name>.py.


Documentation

Full documentation lives in docs/ (Sphinx + Markdown) — installation, signing, PAdES, appearance, certification, eSign, the CLI and the complete API reference. Build it with pip install -r docs/requirements.txt && sphinx-build -b html docs docs/_build. Publishing the package and hosting the docs (Read the Docs, GitHub Pages, …) is covered in PUBLISHING.md.


Errors

Everything raises atick.AtickError (a normal Python exception) you can catch:

try:
    atick.sign_pfx(pdf, pfx=, password="wrong", style=, placements=)
except atick.AtickError as e:
    print("signing failed:", e)

License

ATick is dual-licensed :

  • Free & open source under GNU AGPL-3.0 — use it anywhere, even sell a product built on it, as long as your own source code is open and public (AGPL copyleft).
  • Commercial license — to use ATick in a closed-source product without publishing your code, contact aniketc.pro@gmail.com.

See LICENSING.md for details. © 2026 Aniket Chaturvedi.

Project details


Download files

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

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

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

atick-1.0.5-cp38-abi3-win_arm64.whl (2.3 MB view details)

Uploaded CPython 3.8+Windows ARM64

atick-1.0.5-cp38-abi3-win_amd64.whl (2.4 MB view details)

Uploaded CPython 3.8+Windows x86-64

atick-1.0.5-cp38-abi3-win32.whl (2.4 MB view details)

Uploaded CPython 3.8+Windows x86

atick-1.0.5-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.4 MB view details)

Uploaded CPython 3.8+manylinux: glibc 2.17+ x86-64

atick-1.0.5-cp38-abi3-manylinux_2_17_i686.manylinux2014_i686.whl (2.5 MB view details)

Uploaded CPython 3.8+manylinux: glibc 2.17+ i686

atick-1.0.5-cp38-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (2.4 MB view details)

Uploaded CPython 3.8+manylinux: glibc 2.17+ ARMv7l

atick-1.0.5-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (2.3 MB view details)

Uploaded CPython 3.8+manylinux: glibc 2.17+ ARM64

atick-1.0.5-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl (4.6 MB view details)

Uploaded CPython 3.8+macOS 10.12+ universal2 (ARM64, x86-64)macOS 10.12+ x86-64macOS 11.0+ ARM64

File details

Details for the file atick-1.0.5-cp38-abi3-win_arm64.whl.

File metadata

  • Download URL: atick-1.0.5-cp38-abi3-win_arm64.whl
  • Upload date:
  • Size: 2.3 MB
  • Tags: CPython 3.8+, Windows ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for atick-1.0.5-cp38-abi3-win_arm64.whl
Algorithm Hash digest
SHA256 aa4d41e384cd7737f8139a94f7f2d5c725b4fb8499bacd0a88df60fb6931b0a7
MD5 eae300af2b2b1fa4ab66ade227ad106d
BLAKE2b-256 cca5a22e34a9e56496585e84b0b0de225f4d16510cccdb7998ea8b61bfd85272

See more details on using hashes here.

Provenance

The following attestation bundles were made for atick-1.0.5-cp38-abi3-win_arm64.whl:

Publisher: release.yml on Aniketc068/ATick-build

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file atick-1.0.5-cp38-abi3-win_amd64.whl.

File metadata

  • Download URL: atick-1.0.5-cp38-abi3-win_amd64.whl
  • Upload date:
  • Size: 2.4 MB
  • Tags: CPython 3.8+, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for atick-1.0.5-cp38-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 758359681151599e5ccef0240f14c3e2791b7ace37b3066f088f16e8e7a5cf01
MD5 c2434def2db89b7815b08acb3c0dd0bd
BLAKE2b-256 be3c2fc18b1da2fff08afb9b5689837029c0e39379877b4e6665d5ac634709c6

See more details on using hashes here.

Provenance

The following attestation bundles were made for atick-1.0.5-cp38-abi3-win_amd64.whl:

Publisher: release.yml on Aniketc068/ATick-build

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file atick-1.0.5-cp38-abi3-win32.whl.

File metadata

  • Download URL: atick-1.0.5-cp38-abi3-win32.whl
  • Upload date:
  • Size: 2.4 MB
  • Tags: CPython 3.8+, Windows x86
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for atick-1.0.5-cp38-abi3-win32.whl
Algorithm Hash digest
SHA256 5ce885f8cbcbc88424c883b3278d6589114cef767f55e16d3f744055bd752e2a
MD5 3cb7c5fe37e34545387cb2e0b6ea0a27
BLAKE2b-256 db32ce1915126371228fb2a2e32da3bded5b5ac01c28870e72bea42cfdbab1a1

See more details on using hashes here.

Provenance

The following attestation bundles were made for atick-1.0.5-cp38-abi3-win32.whl:

Publisher: release.yml on Aniketc068/ATick-build

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file atick-1.0.5-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for atick-1.0.5-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 a05f3b94c357fac70bf20f8b5278f91d67c88cdce26964de89c0c21b17eecd65
MD5 bced7af8659bdd07d170eba012e5ed75
BLAKE2b-256 13a776968379e63059f0df2707684ab1436acc8b83adae20fac3943333fe2177

See more details on using hashes here.

Provenance

The following attestation bundles were made for atick-1.0.5-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on Aniketc068/ATick-build

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file atick-1.0.5-cp38-abi3-manylinux_2_17_i686.manylinux2014_i686.whl.

File metadata

File hashes

Hashes for atick-1.0.5-cp38-abi3-manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 4863e70338400cd9130e5ab04328ab3042aeeb651114bcd4b530a201dbff5efe
MD5 6fdaf352d57e393f69fa8a07b8cc0526
BLAKE2b-256 1005ff8120dc3ebbba7a698670ed9cc56942a68caebcc68c53226e79dc8bfbfe

See more details on using hashes here.

Provenance

The following attestation bundles were made for atick-1.0.5-cp38-abi3-manylinux_2_17_i686.manylinux2014_i686.whl:

Publisher: release.yml on Aniketc068/ATick-build

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file atick-1.0.5-cp38-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl.

File metadata

File hashes

Hashes for atick-1.0.5-cp38-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
Algorithm Hash digest
SHA256 f51b843b9af6a87a872b9850ba8e0bd1511e12792394acd3683766906a675797
MD5 f894f0e94a921f9517cd861420eb7c79
BLAKE2b-256 2d82d991e6f248d4628b6f09c8439e4ef3988fb8f6b6c536e1bbd592b64f235e

See more details on using hashes here.

Provenance

The following attestation bundles were made for atick-1.0.5-cp38-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl:

Publisher: release.yml on Aniketc068/ATick-build

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file atick-1.0.5-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for atick-1.0.5-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 9c1842fdf8b6703fa442d325166dfc5f18e6bde0e82d58ca7c62d4acf0c9064e
MD5 1a02003e514094e67b3200fc431e1729
BLAKE2b-256 eda1f393cc4c684713391d3ac727a51d58ce9ac269c2440e5c33e4f0af332518

See more details on using hashes here.

Provenance

The following attestation bundles were made for atick-1.0.5-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: release.yml on Aniketc068/ATick-build

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file atick-1.0.5-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl.

File metadata

File hashes

Hashes for atick-1.0.5-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
Algorithm Hash digest
SHA256 14828ecb986f5500d786bee654cc506904f271938c0126b793362b998d635415
MD5 9f823cc92f9d804f0bcd285ad9ae5531
BLAKE2b-256 03f2fe161da43bf8bc662e3e50cd5d9b5ab72e1a92f0ac652b2fdc2077b0ecab

See more details on using hashes here.

Provenance

The following attestation bundles were made for atick-1.0.5-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl:

Publisher: release.yml on Aniketc068/ATick-build

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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