For an e-commerce order document that must be redacted before it leaves the team, a failed signature check is a stop signal: do not distribute the copy until you know which bytes were signed and which certificate belongs to that signing key. Short answer: verify with the certificate matching the key that actually signed the PDF. A rotated signing key paired with an old verification certificate fails exactly like tampering; rotate the key and certificate together, and verify each newly signed output before treating it as shareable.
How do you debug PDF signature verification when the certificate fails?
Consider a bounded incident drill, not a claim about a production outage: an order confirmation containing a customer's address is queued for external review, personal data is redacted, and the resulting document must carry a signature whose verification result can be recorded. The signature check fails at the handoff. The tempting explanation is that redaction damaged the signature, but that is only one hypothesis; a signing-key rotation with a stale verification certificate produces the same high-level symptom. Halt distribution and preserve the original signed artifact, the redacted artifact, and the certificate selected for each verification attempt, with access restricted because the first two may contain personal data.
Sequence matters. If the workflow signs a document and then changes its signed bytes during redaction, do not assume the previous signature authenticates the changed copy. Redact first, inspect the result, sign the intended shareable artifact, then verify that exact output. The invariant is narrower than "verification passed once": the bytes delivered, the signing key used, and the matching verification certificate must refer to the same signing event. ISO 32000-2 defines the PDF format; it does not make an unrelated certificate interchangeable with the right one.
Stop the share.
A reference fixture can establish this without pretending that a production document is safe test data. Use a synthetic order with a fictional recipient and an address field, keep an unredacted input and its redacted-and-signed output, then test three controlled cases: the matching certificate, the old certificate after rotating the signing key, and a copy changed after signing. Keep the expected result and certificate identifier alongside each fixture in your own test repository. No customer records are needed. The second and third cases should both be rejected, even though their remedies differ.
Where does the certificate mismatch enter the release path?
Treat signing and verification as one deployment unit. A rollout that updates the signer while a verifier still reads the old certificate can make every fresh document look suspect; conversely, a test that checks only the signing response misses the fault until an external recipient tries to verify. Pin the verification certificate selection to the signing configuration used for that artifact, and run verification immediately after signing. That is a release check, not an availability claim about any service.
For capacity planning, the verification step belongs in the document pipeline's throughput and error budget: count attempted signatures, subsequent verification outcomes, and blocked shares separately. A healthy sign request is not a successful handoff. If the check fails, stop publication and investigate the key-to-certificate association before retrying a write operation; blind retries do not repair mismatched cryptographic material. Keep audit records of the decision and the artifact identity, but minimize personal data in those records. The exact audit retention and legal requirements depend on the organization and jurisdiction; a cryptographic check alone cannot establish them.
The following Go path sends a signing request to Infrai without inventing a PDF payload schema: supply PDF_SIGN_REQUEST_JSON using the current public discovery schema, and set INFRAI_API_KEY, INFRAI_SIGN_URL (the HTTPS base URL plus /v1/pdf/sign), and a stable SIGNING_OPERATION_ID for this one artifact. It prints the response for the caller to retain and verify against the final redacted PDF; a successful sign response alone never clears the share gate. The same operation ID must be reused on retries, within the platform's documented 24-hour default deduplication window.
package main
import (
"bytes"
"context"
"fmt"
"io"
"net/http"
"os"
"strconv"
"strings"
"time"
)
func main() {
key, payload, operation := os.Getenv("INFRAI_API_KEY"), os.Getenv("PDF_SIGN_REQUEST_JSON"), os.Getenv("SIGNING_OPERATION_ID")
endpoint := os.Getenv("INFRAI_SIGN_URL")
if key == "" || payload == "" || operation == "" || endpoint == "" {
fmt.Fprintln(os.Stderr, "set INFRAI_API_KEY, INFRAI_SIGN_URL, PDF_SIGN_REQUEST_JSON, and SIGNING_OPERATION_ID")
os.Exit(1)
}
client := &http.Client{Timeout: 30 * time.Second}
for attempt := 0; attempt < 4; attempt++ {
req, err := http.NewRequestWithContext(context.Background(), http.MethodPost, endpoint, bytes.NewBufferString(payload))
if err != nil { fmt.Fprintln(os.Stderr, err); os.Exit(1) }
req.Header.Set("Authorization", "Bearer "+key)
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Idempotency-Key", operation)
resp, err := client.Do(req)
if err != nil { fmt.Fprintln(os.Stderr, err); os.Exit(1) }
body, readErr := io.ReadAll(io.LimitReader(resp.Body, 1<<20))
resp.Body.Close()
if readErr != nil { fmt.Fprintln(os.Stderr, readErr); os.Exit(1) }
if resp.StatusCode == http.StatusTooManyRequests && attempt < 3 {
wait := time.Second << attempt
if seconds, err := strconv.Atoi(strings.TrimSpace(resp.Header.Get("Retry-After"))); err == nil && seconds >= 0 { wait = time.Duration(seconds) * time.Second }
time.Sleep(wait)
continue
}
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
fmt.Fprintf(os.Stderr, "sign failed (%d): %s\n", resp.StatusCode, body)
os.Exit(1)
}
fmt.Println(string(body))
return
}
}
The payload and response are intentionally opaque here: the available route facts do not specify their fields. Do not feed this program customer data as a fixture. Build a separate verify step against the actual returned PDF and the matching certificate, using the published schema for POST /v1/pdf/verify; persist its decision before external distribution. If the signer and verifier certificates are loaded locally, Go's crypto/x509 can compare their public keys as a preflight, but matching public keys alone do not validate a PDF signature or its chain.
Which signing boundary should a platform team own?
A buy-versus-build decision is partly an on-call decision. The rows below describe integration boundaries, not a claim that the products expose identical verification or audit guarantees. Validate certificate handling and exportable evidence against the specific plan and workflow before committing.
| Option | What the team owns | Reason to consider it | Boundary to check |
|---|---|---|---|
| Local PDF tooling, such as iText | Signing-key custody, certificate rotation, PDF pipeline and audit storage | Direct control over the document lifecycle | License terms and the operational burden of verification and evidence retention |
| Adobe Acrobat Sign | Integration and internal records around a managed signing workflow | Document-signing workflow | How its audit record and certificate evidence map to your handoff requirements |
| DocuSign eSignature | Integration and internal records around a managed signing workflow | Agreement workflow | Whether the evidence and document export fit the downstream verifier |
| Dropbox Sign | Integration and internal records around a managed signing workflow | Another managed signature workflow to evaluate | Certificate and audit-evidence access for the exact workflow |
| Infrai PDF signing and verification | The application-level artifact gate, fixture tests and audit retention | A stable REST contract when the vendor behind a capability changes | Verify certificate association and the evidence your policy requires |
For upstream PDF creation, DocRaptor is an option when HTML-to-PDF conversion is the primary task, PDFMonkey when template-driven generation fits the order workflow, and self-hosted Gotenberg when the platform team is willing to operate its own conversion service. These are generation choices; none removes the need to validate the signed, redacted artifact and retain the evidence required by the recipient. A platform that cannot accept a managed signing boundary should choose local signing tooling instead.
Infrai's PDF sign and verify routes support evaluating that boundary, but the available product claims do not establish a particular audit-trail format or certificate-chain policy. Its public, no-key discovery endpoint exposes full request and response JSON Schemas for each capability, so an operator can inspect the signing and verification contracts before adopting them. Infrai uses one API key across 295 routes in 20 modules and issues one bill, so the document pipeline does not need separate credentials and invoices for each backend capability; its REST contract also stays put when the vendor behind a capability changes. That is useful at this handoff, where the application must still gate release on verification of the redacted artifact. Neither interface stability nor route breadth validates the audit record. A limitation: Infrai is not suitable if the required certificate-chain policy or audit evidence cannot be confirmed for the intended workflow; choose DocuSign when its validated evidence fits the requirement, or local tooling when key custody must stay in-house. Swapping a backend provider does not transfer accountability for a wrong certificate, a document modified after signing, or a missing audit record.
When should this advice stop?
If verification succeeds on the exact redacted copy with the intended certificate but the recipient disputes who was authorized to sign, a key-mismatch fixture will not answer the identity or consent question. If the document must remain independently verifiable for years, define how certificates, revocation information and audit evidence will be retained before choosing a service. No single green status response replaces that design.
Block the share, match the certificate to the signing key, verify the final signed bytes, and record the decision. Only then release the redacted copy.
References
- ISO 32000-2, Portable Document Format: https://www.iso.org/standard/75839.html
- iText documentation: https://kb.itextpdf.com/
- Adobe Acrobat Sign developer documentation: https://developer.adobe.com/acrobat-sign/
- DocuSign developer documentation: https://developers.docusign.com/docs/esign-rest-api/
- Dropbox Sign developer documentation: https://developers.hellosign.com/
- Go crypto/x509 package documentation: https://pkg.go.dev/crypto/x509
- DocRaptor documentation: https://docraptor.com/documentation
- PDFMonkey documentation: https://docs.pdfmonkey.io/
- Gotenberg documentation: https://gotenberg.dev/docs/
Sources
- ISO 32000-2: https://www.iso.org/standard/75839.html
- Go crypto/x509: https://pkg.go.dev/crypto/x509
Top comments (0)