Refactor JSignPdf hash compatibility handling to use the upstream wrapper
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 5/5
- Estimated time
- Over a week
- Newbie friendliness
- 25/100
Research direction
First check the upstream prerequisite, jsignpdf-php issue 70, and review its released contract and tests. Then read lib/Handler/SignEngine/JSignPdf/HashAlgorithmResolver.php and JSignPdfHandler.php alongside the named resolver unit and handler integration tests; map how policy-selected hashes and PDF handling reach the wrapper. Done means the released wrapper is qualified, redundant compatibility workarounds are removed, and signing, TSA independence, existing signatures and DocMDP behavior pass the specified checks.
Written by the indexing model from the issue text.
Description
Context
LibreSign currently handles JSignPdf-specific signature hash and PDF-version compatibility in:
lib/Handler/SignEngine/JSignPdf/HashAlgorithmResolver.phplib/Handler/SignEngine/JSignPdf/JSignPdfHandler.php
The existing implementation combines two different responsibilities:
- Resolving LibreSign's effective administrative signature hash policy.
- Working around algorithm and PDF-version limitations specific to JSignPdf.
The second responsibility should be handled by the jsignpdf-php wrapper so consuming applications do not need to maintain equivalent implementation-specific logic.
Goal
Refactor LibreSign's existing JSignPdf signing integration to delegate hash and PDF-version compatibility handling to the upstream PHP wrapper.
Preserve LibreSign's administrative policies, existing signing workflows, TSA configuration and document integrity.
Do not introduce another signing engine.
Upstream prerequisite
Implementation blocked by:
https://github.com/JSignPdf/jsignpdf-php/issues/70
The upstream issue defines safe signature hash selection and PDF-version compatibility handling in jsignpdf-php.
The final refactoring must use a compatible released version that provides the required behavior.
Do not implement duplicate compatibility logic in LibreSign merely to work around an unfinished upstream implementation.
Responsibility boundaries
LibreSign remains responsible for
- Resolving the effective signature hash policy.
- Enforcing system, group and request-level policy rules.
- Selecting the algorithm requested for a signing operation.
- Applying application-specific security restrictions.
- Configuring the TSA digest independently.
- Selecting the existing signing engine.
- Reporting signing failures appropriately.
The default system signature algorithm is SHA-256.
An algorithm resolved from the effective application policy must be treated as an explicit choice when passed to the wrapper, even if the user did not provide a request-level override.
The JSignPdf PHP wrapper is responsible for
- Handling JSignPdf-specific algorithm limitations.
- Evaluating compatibility with PDF versions and signing modes.
- Applying verified, safe compatibility strategies.
- Preserving explicitly requested algorithms.
- Rejecting unsupported combinations with actionable errors.
- Avoiding silent algorithm substitutions or unsafe PDF transformations.
Implementation
Once the upstream functionality is released and qualified:
- Review the implemented wrapper contract and available tests.
- Update
jsignpdf/jsignpdf-phpthrough the establishedLibreSign/3rdpartydependency workflow. - Update the corresponding LibreSign submodule reference.
- Pass the algorithm selected by LibreSign's effective policy to the wrapper.
- Remove JSignPdf-specific algorithm compatibility rules that are now handled upstream.
- Remove or simplify redundant PDF-version handling.
- Preserve LibreSign's administrative policy and TSA configuration.
- Update the affected tests and validate the integrated behavior.
Do not manually edit generated vendored dependency files.
HashAlgorithmResolver refactoring
Review the current methods:
HashAlgorithmResolver::forSignature()HashAlgorithmResolver::requiresPdfVersionUpgradeForSha256()HashAlgorithmResolver::forTsa()
The first two contain JSignPdf-specific compatibility behavior that should be delegated to the wrapper when its new contract supports this.
forTsa() resolves LibreSign's independent timestamp hash policy and must not be removed merely because signature hash compatibility has moved upstream.
The resulting implementation may retain a simplified resolver if it continues to provide a useful application-policy boundary.
Avoid duplicating wrapper behavior or introducing unnecessary abstractions.
PDF-version handling
Review the existing methods in JSignPdfHandler:
extractPdfVersion()normalizePdfVersion()replacePdfVersion()
The current implementation includes direct replacement of the PDF version header.
Evaluate whether these workarounds remain necessary after the upstream change.
Do not preserve or introduce header-only transformations as a substitute for a structurally valid PDF conversion.
Any supported signing operation must preserve previous valid signatures, incremental revisions and applicable DocMDP restrictions.
Unsupported scenarios must produce clear failures rather than silent compatibility downgrades.
Compatibility and security
Review behavior for:
- SHA-1, SHA-256, SHA-384 and SHA-512.
- RIPEMD160 where permitted by the existing policy and supported by the runtime.
- PDFs older than version 1.6.
- PDF 1.6, 1.7 and supported later versions.
- Unknown or malformed PDF versions.
- Documents with existing signatures.
- Incremental updates and DocMDP restrictions.
- Visible and invisible signatures.
- Independent TSA digest configuration.
The current implementation can select a different algorithm from the configured one in some cases.
Do not silently preserve those substitutions merely to maintain existing unit-test expectations.
Evaluate any compatibility change explicitly and document its rationale in the implementation PR.
The goal is predictable signing behavior, not unconditional acceptance of every legacy input.
Tests
Review and update:
tests/php/Unit/Handler/SignEngine/JSignPdf/HashAlgorithmResolverTest.phptests/php/Integration/Handler/SignEngine/JSignPdf/JSignPdfHandlerTest.php
Remove tests that only validate obsolete implementation-specific workarounds and replace them with tests of the application-to-wrapper contract.
Verify that:
- The effective administrative hash policy is resolved correctly.
- The selected signature algorithm reaches the wrapper unchanged.
- Explicit policy choices are preserved or rejected clearly.
- Default SHA-256 policy behavior remains correct.
- Unsupported combinations result in actionable errors.
- TSA digest selection remains independent.
- Supported legacy PDF scenarios continue working safely.
- Previous valid signatures remain valid.
- Applicable DocMDP restrictions are respected.
- Visible and invisible signing continue working.
- The Native signing engine remains unaffected.
Use representative PDF fixtures and independently validate signed outputs where needed.
Run applicable PHPUnit, static-analysis, formatting and mutation-testing checks.
Documentation scope
This is primarily an internal integration refactoring.
Do not add implementation details, compatibility decision tables or development history to LibreSign's README or user documentation.
Update existing administrator documentation only if the externally observable behavior of signing configuration changes.
Record implementation decisions and technical evidence in the PR and relevant tests.
Out of scope
- Refactoring the Native signing engine.
- Migrating Native signing to a different SignerPHP library.
- Moving LibreSign's administrative policy into
jsignpdf-php. - Changing ownership of TSA configuration.
- Implementing cryptographic algorithms inside LibreSign.
- Introducing new signing engines.
- Remote signing, CSC or eIDAS integration.
- Unrelated signing workflow changes.
Acceptance criteria
- The upstream functionality is available in a compatible released package.
- LibreSign consumes and qualifies that implementation.
- Redundant JSignPdf-specific compatibility logic is removed.
- Administrative hash policy resolution remains in LibreSign.
- Explicit algorithm choices are preserved or rejected clearly.
- Legacy PDF compatibility follows the qualified upstream contract.
- No unsafe version transformation is introduced or retained.
- Previous valid signatures and applicable restrictions remain intact.
- TSA digest selection remains independent.
- Existing signing workflows pass regression tests.
- The Native engine remains unaffected.
- Applicable quality checks pass.
- Documentation changes, if any, are limited to actual public behavior changes.
- Dominant language
- PHP
- Stars
- 828
- Forks
- 159
- Avg merge
- 7h 53m
- Merged PRs (30d)
- 523
Getting set up
Starts the project's dev container in your browser, under your own GitHub account.
- No Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from LibreSign/libresign
-
Difficulty 1/5 Under an hour Newbie friendliness 83/100
LibreSign/libresign#9007 · 1 reaction ·
Maintainers usually reply within 1 day
-
backend enhancement php
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Maintainers usually reply within 1 day
-
Validation page says "This document is valid" for a document with no signaturePossibly taken @maia-andre claimed this 8 days ago. Open
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
Maintainers usually reply within 1 day
-
good first issue
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
LibreSign/libresign#8284 · 5 comments ·
Maintainers usually reply within 1 day
-
backend php
Difficulty 4/5 3-5 days Newbie friendliness 48/100
Maintainers usually reply within 1 day
All issues in LibreSign/libresign
Similar issues
-
Difficulty 1/5 Under an hour Newbie friendliness 84/100
WordPress/hosting-handbook#506 ·
Maintainers usually reply within 2 days
-
Installing a plugin with composer_packages installs dev dependencies and breaks the autoloader (Error 500)Possibly taken @Boy132 claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
Maintainers usually reply within 1 day
-
nginx: static-file locations drop the security headers, and the dotfile deny is matched after themOpenbug Low Security
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Maintainers usually reply within 1 day
-
Difficulty 1/5 Under an hour Newbie friendliness 78/100
backdrop-contrib/commerce#60 ·
-
Difficulty 1/5 Under an hour Newbie friendliness 76/100