Skip to main content
Digital certifications cryptographically prove that a PDF has not been tampered with since certification and identify the certifier. They are required or expected for contracts, regulatory filings, legal documents, and compliance workflows. Forme supports PKCS#7 detached signatures using X.509 certificates, implemented in pure Rust with no external signing service.
In 0.9.0, signature was renamed to certification and signPdf() to certifyPdf() to better reflect the cryptographic nature of the operation (PKCS#7 certification vs e-signatures). The old names still work as deprecated aliases. See the migration guide.

Certifying at Render Time

Pass the certification prop on the Document component to certify the PDF during rendering. You need an X.509 certificate and its corresponding RSA private key in PEM format.
import { readFileSync } from 'fs';
import { Document, Page, Text } from '@formepdf/react';
import { renderDocument } from '@formepdf/core';

const certificatePem = readFileSync('./cert.pem', 'utf-8');
const privateKeyPem = readFileSync('./key.pem', 'utf-8');

const pdfBytes = await renderDocument(
  <Document
    title="Service Agreement"
    certification={{
      certificatePem,
      privateKeyPem,
      reason: 'Approved',
      location: 'San Francisco, CA',
      contact: 'legal@acme.com',
    }}
  >
    <Page size="Letter" margin={54}>
      <Text style={{ fontSize: 24, fontWeight: 700 }}>Service Agreement</Text>
      <Text style={{ fontSize: 10, lineHeight: 1.6, marginTop: 12 }}>
        This agreement is entered into as of March 29, 2026...
      </Text>
    </Page>
  </Document>
);

Certification Props

PropTypeRequiredDescription
certificatePemstringYesX.509 certificate in PEM format.
privateKeyPemstringYesRSA private key in PEM format (PKCS#8).
reasonstringNoReason for certification (e.g., “Approved”, “Reviewed”). Shown in signature details.
locationstringNoCertification location (e.g., “San Francisco, CA”).
contactstringNoCertifier contact information (e.g., email address).
The signature prop is still accepted as a deprecated alias for certification.

Standalone Certification via certifyPdf()

Use certifyPdf() to certify an existing PDF without re-rendering it:
import { certifyPdf } from '@formepdf/core';
import { readFileSync, writeFileSync } from 'fs';

const pdfBytes = readFileSync('contract.pdf');
const certificatePem = readFileSync('./cert.pem', 'utf-8');
const privateKeyPem = readFileSync('./key.pem', 'utf-8');

const certifiedPdf = await certifyPdf(pdfBytes, {
  certificatePem,
  privateKeyPem,
  reason: 'Approved',
  location: 'San Francisco, CA',
  contact: 'legal@acme.com',
});

writeFileSync('certified-contract.pdf', certifiedPdf);
signPdf() is still exported as a deprecated alias for certifyPdf().

Certification via the Hosted API

Use POST /v1/certify to certify a PDF via the hosted API. You can pass inline PEM data or reference a saved certificate by ID. See the Certify API reference for full details and code examples.

Visible vs Invisible Signatures

By default, Forme applies an invisible signature. The signature is embedded in the PDF’s metadata and can be verified in the signature panel of any PDF viewer, but nothing appears on the page itself. To add a visible signature annotation, set visible: true and specify the position and size:
<Document
  certification={{
    certificatePem,
    privateKeyPem,
    reason: 'Approved',
    visible: true,
    x: 350,
    y: 700,
    width: 200,
    height: 50,
  }}
>
  {/* ... */}
</Document>
The visible annotation displays the signer’s common name (from the certificate) at the specified position. Coordinates are in points from the bottom-left corner of the page.
PropTypeDefaultDescription
visiblebooleanfalseWhether to show a visible signature annotation.
xnumber0X coordinate in points from the left edge.
ynumber0Y coordinate in points from the bottom edge.
widthnumber200Width of the visible signature in points.
heightnumber50Height of the visible signature in points.
Visible signature appearance text uses the built-in Helvetica font, limited to Latin characters. This is a PDF specification constraint on form field appearances.

Known Limitations

  • RSA keys only. Only RSA private keys are supported. ECDSA, Ed25519, and other key types are not supported. If you pass a non-RSA key, you will get a clear error message.
  • Leaf certificate only. Only the signing certificate is embedded in the signature. Intermediate CA certificates are not included. PDF viewers may show “unknown signer” if they cannot build the full chain to a trusted root.
  • No timestamp authority (TSA). Signatures do not include a trusted timestamp from a TSA server. The signing date is set from the server clock but is not cryptographically verified by a third party.
  • No Long-Term Validation (LTV). CRL and OCSP responses are not embedded. Signature validity cannot be verified after the signing certificate expires.
  • One signature per render. Each render operation applies a single signature. To apply multiple signatures (e.g., co-signers), certify sequentially using the /v1/certify endpoint.
  • Self-signed certificates show “unknown signer” in Acrobat. This is expected. Acrobat only trusts certificates from its trusted root store. Self-signed certs are fine for testing and internal workflows.
  • Helvetica only in signature appearance text. Visible signature annotations use the PDF built-in Helvetica font. Custom fonts are not supported in signature form field appearances.