Skip to content

ENH: add sign command#165

Merged
Lucas-C merged 14 commits into
py-pdf:mainfrom
moormaster:feat/add-sign-command
Oct 10, 2025
Merged

ENH: add sign command#165
Lucas-C merged 14 commits into
py-pdf:mainfrom
moormaster:feat/add-sign-command

Conversation

@moormaster
Copy link
Copy Markdown
Contributor

  • adds sign command to create signed pdfs using a PKCS12 .p12 key
  • integration of fdpf2 lib is possible but not in a "clean and documented" way
    The annotation for the signature needs to calculate its hash value from the contents and the certificate. When using fpdf2 no contents are present in the newly created FPDF instance. To sign the contents from an existing pdf some magic must be done:
    • In OutputProducer.bufferize() - output.py:877 the signing of the contents needs to be suppressed / deferred until the actual pdf contents have been merged.
      -> _sign_key = None is set before serializing the FPDF instance.
    • After merging signing is done by using an fpdf-internal method fpdf.sign.sign_content() - sign.py:45 which replaces the placeholders in the signature annotation
    • PdfWriter() alters the placeholders inside of the signature annotation.
      -> For sign_content() to succeed the placeholders must be search&replaced back into their original form how sign_content() expects them to look like
  • unit test use signing-certificate.crt and signing-certificate.p12 taken from https://github.com/py-pdf/fpdf2

@moormaster moormaster force-pushed the feat/add-sign-command branch from d5ca716 to b6ce05e Compare October 9, 2025 09:01
@moormaster moormaster marked this pull request as ready for review October 9, 2025 09:02
@moormaster moormaster mentioned this pull request Oct 9, 2025
7 tasks
Comment thread docs/user/subcommand-sign.md Outdated
Comment thread docs/user/subcommand-sign.md
Comment thread tests/test_sign.py
Comment thread pdfly/sign.py
Comment thread pdfly/sign.py Outdated
Comment thread pdfly/sign.py Outdated
Comment thread pdfly/sign.py Outdated
Comment thread pdfly/sign.py Outdated
Comment thread pdfly/sign.py Outdated
Copy link
Copy Markdown
Member

@Lucas-C Lucas-C left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you very much @moormaster for working on this feature 👍

I made a few comments as feedback

@moormaster moormaster force-pushed the feat/add-sign-command branch 2 times, most recently from e9ac7e2 to 774ebd4 Compare October 9, 2025 17:47
@Lucas-C
Copy link
Copy Markdown
Member

Lucas-C commented Oct 10, 2025

Could you also please add a mention of this new feature in CHANGELOG.md as part of this PR?

I'll answer your comments in a few hours, can't do it right now, but thank you for all your work on this 👍

@moormaster moormaster force-pushed the feat/add-sign-command branch from 774ebd4 to 0f65948 Compare October 10, 2025 11:49
@moormaster moormaster changed the title FEAT: add sign command ENH: add sign command Oct 10, 2025
@moormaster
Copy link
Copy Markdown
Contributor Author

Could you also please add a mention of this new feature in CHANGELOG.md as part of this PR?

Added an entry to CHANGELOG.md and fixed commit message & PR title: FEAT -> ENH

Lucas-C
Lucas-C previously approved these changes Oct 10, 2025
@Lucas-C
Copy link
Copy Markdown
Member

Lucas-C commented Oct 10, 2025

I think this is ready to merged, as soon as the CI pipeline is ✅ 🙂
It's currently failing due to a typing error on Generator[FPDF]:

E   TypeError: Too few arguments for typing.Generator; actual 1, expected 3

Good job really on this PR 👍

Also, have you tested signing a PDF and then sign it again with pdfly sign?
Does it fail? Does it produce a new PDF with a distinct signature?

Comment thread CHANGELOG.md Outdated
@Lucas-C
Copy link
Copy Markdown
Member

Lucas-C commented Oct 10, 2025

@allcontributors please add @moormaster for code

@allcontributors
Copy link
Copy Markdown
Contributor

@Lucas-C

I've put up a pull request to add @moormaster! 🎉

@moormaster
Copy link
Copy Markdown
Contributor Author

Also, have you tested signing a PDF and then sign it again with pdfly sign? Does it fail? Does it produce a new PDF with a distinct signature?

I guess this would currently generate a broken pdf - When fully generating a pdf with fdpf2 the fpdf.sign() method prevents itself from being called multiple times on the same document.

The sign command of pdfly should check for an existing signature annotation and refuse to add another signature in this case + another unit test to test this behaviour.

@moormaster moormaster force-pushed the feat/add-sign-command branch 3 times, most recently from c61d887 to e530e86 Compare October 10, 2025 13:39
@moormaster moormaster force-pushed the feat/add-sign-command branch 3 times, most recently from 982470c to 574b931 Compare October 10, 2025 14:59
@moormaster
Copy link
Copy Markdown
Contributor Author

I guess I might have fixed all the PR related CI failures. I did not focus on the python 3.8 pipeline since that python version already reached its end-of-life.

Added a unit test to ensure that attempts to sign an already signed pdf will be denied.

@moormaster moormaster force-pushed the feat/add-sign-command branch 3 times, most recently from 9b60757 to 7ef3758 Compare October 10, 2025 15:14
@Lucas-C
Copy link
Copy Markdown
Member

Lucas-C commented Oct 10, 2025

I guess I might have fixed all the PR related CI failures. I did not focus on the python 3.8 pipeline since that python version already reached its end-of-life.
Added a unit test to ensure that attempts to sign an already signed pdf will be denied.

Great 👍
Regarding Python 3.8, I'm removing it from the test matrix in PR #171

@moormaster moormaster force-pushed the feat/add-sign-command branch from 7ef3758 to a3f2a42 Compare October 10, 2025 15:19
@Lucas-C Lucas-C force-pushed the feat/add-sign-command branch from a3f2a42 to 89918d3 Compare October 10, 2025 15:29
@Lucas-C
Copy link
Copy Markdown
Member

Lucas-C commented Oct 10, 2025

I'm rebasing the branch so that you benefit from the removal of Python3.8 & Python3.9 in the pipeline test matrix.

There's now just this single ruff error that's blocking:

 pdfly/sign.py:19:1: UP035 [*] Import from `collections.abc` instead: `Generator`
   |
17 | from contextlib import contextmanager
18 | from pathlib import Path
19 | from typing import Generator, Optional, Union
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP035
20 | 
21 | import fpdf.sign
   |
   = help: Import from `collections.abc`

@moormaster
Copy link
Copy Markdown
Contributor Author

pdfly/sign.py:19:1: UP035 [*] Import from collections.abc instead: Generator

Fixed

@Lucas-C Lucas-C merged commit 0e84aa3 into py-pdf:main Oct 10, 2025
8 checks passed
@moormaster moormaster deleted the feat/add-sign-command branch October 10, 2025 17:30
@Lucas-C
Copy link
Copy Markdown
Member

Lucas-C commented Oct 13, 2025

This new command has been included in the latest 0.5.0 release: https://github.com/py-pdf/pdfly/releases/tag/0.5.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants