Table of contents
Namespace: Com\Tecnick\Pdf\Sign
final class Signer
Source: src/Signer.php:60
Package-internal orchestration entry point that ties the CMS builder, the RFC 3161 timestamp codec, and the LTV material collector together behind two host-facing calls. It stays transport-injected and free of file and network access: the host loads keys and owns HTTP (and SSRF protection).
sign() produces the detached CAdES CMS for a document’s ByteRange bytes. For a legacy or PAdES B-B profile that is the plain CMS; for B-T and above it also requests an RFC 3161 signature timestamp and embeds it as the SignerInfo id-aa-signatureTimeStampToken unsigned attribute.
prepare() and buildFromSignature() are the same call split in two, for a signature made outside this process. They apply the same profile rules as sign().
collectValidationMaterial() gathers the certificates, OCSP responses, and CRLs a B-LT or B-LTA document needs, shaped for the DSS emitter. The VRI key is not computed here: it depends on the final signature Contents and belongs to the DSS writer.
Constants
MAX_PATH_CERTIFICATES
Most certificates accepted in the unauthenticated certificate bag of a timestamp token. The same bound Ocsp\Client applies to a response’s certs [0] field, held in Cms\Certificate.
public const MAX_PATH_CERTIFICATES = \Com\Tecnick\Pdf\Sign\Cms\Certificate::MAX_EMBEDDED_CERTIFICATES
Source: src/Signer.php:78
Methods
__construct()
public __construct(
?Builder $builder = null,
?ValidationMaterial $validationMaterial = null,
?Certificate $certificate = null,
bool $checkSignerCertificate = false,
SignedDataVerifier|null $tokenVerifier = null
)
Parameters:
$builder(?Builder)$validationMaterial(?ValidationMaterial)$certificate(?Certificate)$checkSignerCertificate(bool): Refuse to sign with a certificate that had expired, was not yet valid, or whose key usage forbids signing. Off by default, since a host may deliberately re-sign historical content.$tokenVerifier(SignedDataVerifier|null): Resolves the signer certificate of a timestamp token passed to collectValidationMaterial(). The default one requires the ESS signing-certificate attribute RFC 3161 section 2.4.2 asks of a token. Pass one constructed with $allowSha1 to accept a token from a responder that signs with nothing else, or without $requireSigningCertificate for a TSA that emits no such attribute.
Throws:
- Exception: If a default collaborator cannot be constructed.
Source: src/Signer.php:106
buildFromSignature()
Produce the detached CAdES CMS from an externally produced signature.
The second half of sign(). As there, a B-T or higher profile requires the timestamp client and transport, and the RFC 3161 token is requested over the raw signature bytes.
public buildFromSignature(
SigningRequest $request,
string $signature,
list<string> $chainCertsDer,
Config $config,
Client|null $timestamp = null,
callable|null $timestampTransport = null,
string|SignatureEncoding $signatureEncoding = \Com\Tecnick\Pdf\Sign\Cms\SignatureEncoding::Der,
int|null $timestampNow = null
): string
Parameters:
$request(SigningRequest): The request returned by prepare().$signature(string): Signature over Cms\Builder::signaturePayload($request).$chainCertsDer(list<string>): Additional certificates to embed, each as PEM or as DER.$config(Config): Signature profile and digest configuration.$timestamp(Client|null): RFC 3161 codec; required for B-T and above.$timestampTransport(callable|null): Maps a DER TimeStampReq to a DER TimeStampResp; required for B-T and above.$signatureEncoding(string|SignatureEncoding): Encoding of $signature.$timestampNow(int|null): Unix time the token’s genTime is checked against; defaults to the current time.
Returns: string: DER-encoded CMS ContentInfo ready for /Contents injection.
Throws:
- Exception: If the request was prepared under another configuration, a timestamp is required but not configured, the signing certificate fails the optional checks, or the signature does not verify.
Source: src/Signer.php:257
collectValidationMaterial()
Collect the long-term validation material for an ordered certificate chain.
The chain must be ordered leaf-first, each entry followed by its issuer, and the ordering is verified by signature. For every certificate that has an issuer in the chain, OCSP and CRL lookups are attempted against the responder URLs in its AIA extension and the distribution points it names. A certificate with no issuer in the chain gets neither, and every URL skipped for that reason is reported through $onSkip with the NotAttempted code; a self-signed root is not reported. A null transport skips that revocation source. Responses are deduplicated across the whole chain.
A certificate either source reported revoked contributes no material at all, not even the other source’s. The certificate itself stays in the result, and the verdict reaches the caller through $onSkip with the Revoked code.
Each token in $timestampTokens is verified, its embedded TSA certificates are ordered into a path starting at the certificate that signed it, and that path is collected alongside the signer’s chain with the same lookups, as ETSI EN 319 142-1 requires of a B-LT Document Security Store. A bag member outside that path is embedded but not looked up, and its URLs are reported through $onSkip.
public collectValidationMaterial(
list<string> $chainPem,
callable|null $ocspTransport = null,
callable|null $crlTransport = null,
list<string> $timestampTokens = [],
int|null $now = null,
callable|null $onSkip = null
): array{certs: list<string>, ocsp: list<string>, crls: list<string>}
Parameters:
$chainPem(list<string>): Certificates leaf first up to the root, each as PEM or as DER.$ocspTransport(callable|null): Maps (url, DER request) to the DER response, or null to skip OCSP.$crlTransport(callable|null): Maps a url to the CRL bytes, or null to skip CRLs.$timestampTokens(list<string>): DER timestamp tokens whose embedded certificates are added to the material, along with revocation data for the paths they carry.$now(int|null): Unix time the responses are checked against; defaults to the current time. Pass the signing time so a retried or queued signature collects against the same instant it signs for.$onSkip(callable|null): Receives (source, url, reason, code) for every revocation URL whose answer was discarded or never fetched. The code separates a revoked verdict from an unreachable responder.
Returns: array{certs: list<string>, ocsp: list<string>, crls: list<string>}: DSS-ready material.
Throws:
- Exception: If a certificate or a token is not a string, a certificate cannot be parsed, the chain is not ordered leaf-first with each entry followed by its issuer, a token does not verify against a certificate it embeds, or a token embeds more than MAX_PATH_CERTIFICATES certificates.
Source: src/Signer.php:424
prepare()
Build the request whose bytes an external signer has to sign.
The first half of sign(), for a private key this process cannot reach. The digest is of the ByteRange-covered document bytes.
Pass the returned request to Cms\Builder::signaturePayload() for the bytes to sign, then back to buildFromSignature() with the signature. Its toArray()/fromArray() pair carries it across a session or a queue.
public prepare(
string $messageDigest,
string $signerCertDer,
Config $config,
int $signingTime,
array<array-key,string> $extraSignedAttributes = []
): SigningRequest
Parameters:
$messageDigest(string): Digest of the ByteRange content, raw bytes, computed with the profile’s digest algorithm.$signerCertDer(string): DER of the signing certificate.$config(Config): Signature profile and digest configuration.$signingTime(int): Unix timestamp for the signing-time attribute.$extraSignedAttributes(array<array-key,string>): Additional signed attributes as OID => DER-encoded attribute value.
Returns: SigningRequest
Throws:
- Exception: If the digest, the certificate, or an extra attribute is invalid, or the signing certificate fails the optional checks.
Source: src/Signer.php:197
sign()
Produce the detached CAdES CMS for a document’s ByteRange content.
When the profile is B-T or above, the timestamp client and transport are required: the RFC 3161 token is requested over the raw signature bytes and embedded as the id-aa-signatureTimeStampToken unsigned attribute.
public sign(
string $content,
string $signerCertDer,
OpenSSLAsymmetricKey $privateKey,
list<string> $chainCertsDer,
Config $config,
int $signingTime,
Client|null $timestamp = null,
callable|null $timestampTransport = null,
array<array-key,string> $extraSignedAttributes = [],
int|null $timestampNow = null
): string
Parameters:
$content(string): ByteRange-covered document bytes to sign.$signerCertDer(string): DER of the signing certificate.$privateKey(OpenSSLAsymmetricKey): Signing private key (RSA or EC).$chainCertsDer(list<string>): Additional certificates to embed, each as PEM or as DER. Every entry is parsed.$config(Config): Signature profile and digest configuration.$signingTime(int): Unix timestamp for the signing-time attribute.$timestamp(Client|null): RFC 3161 codec; required for B-T and above.$timestampTransport(callable|null): Maps a DER TimeStampReq to a DER TimeStampResp; required for B-T and above.$extraSignedAttributes(array<array-key,string>): Additional signed attributes as OID => DER-encoded attribute value, as prepare() accepts.$timestampNow(int|null): Unix time the token’s genTime is checked against; defaults to the current time. It is the moment the request is made, not the signing time.
Returns: string: DER-encoded CMS ContentInfo ready for /Contents injection.
Throws:
- Exception: If a timestamp is required but not configured, signing fails, or the signing certificate fails the optional checks.
Source: src/Signer.php:147
signaturePayload()
Produce the bytes an external signer has to sign for a prepared request.
A passthrough to Cms\Builder::signaturePayload().
public signaturePayload(SigningRequest $request): string
Parameters:
$request(SigningRequest): The request returned by prepare().
Returns: string: DER SET OF signed attributes, ready to be signed.
Throws:
- Exception: If the digest is unsupported or encoding fails.
Source: src/Signer.php:227
signatureTimestampTokens()
Read back the signature timestamp tokens a CMS carries.
Returns the tokens sign() and buildFromSignature() embed as the id-aa-signatureTimeStampToken unsigned attribute, which is what collectValidationMaterial() takes as its fourth argument.
public signatureTimestampTokens(string $cmsDer): list<string>
Parameters:
$cmsDer(string): The CMS returned by sign() or buildFromSignature().
Returns: list<string>: DER tokens, empty for a B-B or legacy signature.
Throws:
- Exception: If the CMS cannot be parsed.
Source: src/Signer.php:371