LibreSign / LibreSign/libresign

Separate PKCS#12 credential requirements from the sign engine contract

Open
#8,346 4 comments 0 reactions 1 assignee View on GitHub

@Rolf39 is already working on this.

Since Sep 11, 2026.

backend good first issue php
Dominant language
PHP
Stars
818
Forks
146
Avg merge
11h 31m
Merged PRs (30d)
326

Description

This is part of #8335.

LibreSign currently has a common sign engine contract, but part of this contract is tied to the way the existing signing flow receives signing credentials.

The current PDF and detached PKCS#7 signing paths receive PKCS#12/PFX credential material inside LibreSign and use a password when needed.

Today, ISignEngineHandler contains both general signing operations and methods used to provide and access this PKCS#12/PFX credential.

External signing will use a different credential ownership model. LibreSign may know the signer certificate and certificate chain, but the private key must remain in the external signing service, HSM or another external component.

Before adding that new lifecycle, separate the methods that require LibreSign to receive PKCS#12/PFX credential material from the common handler contract.

Goal

Create a dedicated contract for the PKCS#12/PFX credential requirements used by the current signing implementation.

This issue must:

  1. create a dedicated interface for the current PKCS#12/PFX credential methods;
  2. remove exactly those methods from ISignEngineHandler;
  3. make the existing SignEngineHandler implement the new interface;
  4. preserve all current signing behavior.

This issue does not define or implement the external signing lifecycle.

Current structure

Today the shared contract includes methods for both signing operations and PKCS#12/PFX credential access:

classDiagram
    class ISignEngineHandler {
        <<interface>>
        +setInputFile()
        +getInputFile()
        +setCertificate()
        +getCertificate()
        +readCertificate()
        +setPassword()
        +getPassword()
        +sign()
        +getSignedContent()
        +getSignatureParams()
        +setSignatureParams()
        +getCertificateChain()
        +getLastSignedDate()
    }

    class SignEngineHandler
    class Pkcs12Handler
    class Pkcs7Handler

    ISignEngineHandler <|.. SignEngineHandler
    SignEngineHandler <|-- Pkcs12Handler
    SignEngineHandler <|-- Pkcs7Handler

Expected change

Create:

lib/Handler/SignEngine/IPkcs12SignEngineHandler.php

with:

interface IPkcs12SignEngineHandler extends ISignEngineHandler {
	public function setCertificate(string $certificate): self;
	public function getCertificate(): string;
	public function readCertificate(): array;
	public function setPassword(string $password): self;
	public function getPassword(): string;
}

Remove exactly these declarations from ISignEngineHandler:

setCertificate()
getCertificate()
readCertificate()
setPassword()
getPassword()

Then update:

lib/Handler/SignEngine/SignEngineHandler.php

from:

abstract class SignEngineHandler implements ISignEngineHandler

to:

abstract class SignEngineHandler implements IPkcs12SignEngineHandler

Do not move or rewrite the existing implementations of these methods.

Do not rename the existing methods.

Resulting structure

classDiagram
    class ISignEngineHandler {
        <<interface>>
        +setInputFile()
        +getInputFile()
        +sign()
        +getSignedContent()
        +getSignatureParams()
        +setSignatureParams()
        +getCertificateChain()
        +getLastSignedDate()
    }

    class IPkcs12SignEngineHandler {
        <<interface>>
        +setCertificate()
        +getCertificate()
        +readCertificate()
        +setPassword()
        +getPassword()
    }

    class SignEngineHandler
    class Pkcs12Handler
    class Pkcs7Handler

    ISignEngineHandler <|-- IPkcs12SignEngineHandler
    IPkcs12SignEngineHandler <|.. SignEngineHandler

    SignEngineHandler <|-- Pkcs12Handler
    SignEngineHandler <|-- Pkcs7Handler

ISignEngineHandler remains the contract used by the current signing architecture.

IPkcs12SignEngineHandler adds the requirements of signing implementations that receive the current PKCS#12/PFX credential material inside LibreSign.

This separation does not define the contract that external signing will use.

The external signing lifecycle may require a different abstraction because signing will happen through separate prepare, external-sign and finalize steps.

About certificate information

Do not move getCertificateChain() from ISignEngineHandler in this issue.

Certificate information is not the same as ownership of the private key.

External signing may also need the signer certificate and certificate chain even though LibreSign never receives the private key.

This issue is specifically about separating the current PKCS#12/PFX credential ownership requirements.

Compatibility

This is an internal contract refactor only.

Existing runtime behavior must remain unchanged.

In particular:

  • Pkcs12Handler must continue handling the current PDF signing flow;
  • Pkcs7Handler must continue producing detached PKCS#7 (.p7s) signatures;
  • PKCS#12/PFX handling must behave as before;
  • password handling must behave as before;
  • SignEngineFactory must remain unchanged;
  • SignFileService must remain unchanged;
  • existing handler selection must remain unchanged.

Do not change the semantics of any existing signing method.

Tests

Add focused tests for the new contract without duplicating existing signing behavior tests.

Verify that:

  • IPkcs12SignEngineHandler extends ISignEngineHandler;
  • SignEngineHandler implements IPkcs12SignEngineHandler;
  • Pkcs12Handler satisfies IPkcs12SignEngineHandler;
  • Pkcs7Handler satisfies IPkcs12SignEngineHandler.

Existing tests for Pkcs12Handler, Pkcs7Handler and SignEngineFactory must continue passing without behavioral changes.

Do not duplicate tests that already verify PDF signing, detached PKCS#7 signing or extension-to-handler resolution.

Why this helps #8335

The existing signing implementation receives PKCS#12/PFX credential material directly inside LibreSign.

External signing has a different ownership model: certificate information may be available to LibreSign, but the private key remains outside LibreSign.

Moving the credential-specific methods out of ISignEngineHandler prevents possession of PKCS#12/PFX credential material from being treated as a requirement of every future signing architecture.

This issue deliberately stops at that boundary.

The prepare/finalize design for external signing is also being discussed in:

https://github.com/jeidison/signer-php/issues/25

Scope boundaries

Please keep this change focused.

Do not:

  • change SignEngineFactory;
  • change SignFileService;
  • change PfxProvider;
  • define the external signing contract;
  • add prepare/finalize external signing methods;
  • add an external signing handler;
  • move getCertificateChain() or other unrelated methods from ISignEngineHandler;
  • change PKCS#12/PFX credential storage;
  • change password handling;
  • change PDF signing behavior;
  • change detached PKCS#7 signing behavior;
  • add CSC or ICP-Brasil PSC support;
  • add provider configuration;
  • add frontend or API changes;
  • move signing logic between existing handlers.

If another method appears to belong in the PKCS#12-specific contract, please discuss it in this issue before moving it.

Good first issue

This is a focused backend refactor with the expected architecture already defined.

The main work is:

  • create IPkcs12SignEngineHandler;
  • move exactly the five credential/password method declarations listed above from ISignEngineHandler to the new interface;
  • update SignEngineHandler to implement the new interface;
  • add focused tests for the new interface relationship;
  • confirm that the existing signing tests continue to pass.

No signing algorithm, PDF processing, factory refactor, external provider integration, database migration, frontend change or API design is required.

A contributor does not need to design the external signing architecture to complete this issue.

Please keep the implementation limited to the boundaries described above. If a larger refactor appears necessary, discuss it in this issue first.

Additional context
  • If you have questions, feel free to ask in this issue.
  • Give a ⭐️ star to this repository if you find LibreSign useful and would like to support the project.
  • You can also join our community: https://t.me/LibreSign

Done when

  • IPkcs12SignEngineHandler exists and extends ISignEngineHandler.
  • The five PKCS#12/PFX credential methods listed above are declared by IPkcs12SignEngineHandler.
  • These five methods are no longer declared by ISignEngineHandler.
  • Other existing ISignEngineHandler methods remain unchanged.
  • SignEngineHandler implements IPkcs12SignEngineHandler.
  • Current PDF signing behavior is unchanged.
  • Current detached PKCS#7 signing behavior is unchanged.
  • SignEngineFactory behavior and contract are unchanged.
  • SignFileService behavior and contract are unchanged.
  • Focused tests protect the new interface relationship.
  • The existing signing test suite continues to pass.
  • No external signing lifecycle or implementation is introduced.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.