Signing Worker Protocol

Signature formats

Choose between raw signature values and complete CMS signatures, what each one signs, and what SignatureAPI checks and changes in a CMS

Private beta. Qualified signatures are available on request. Request access and we enable them for your account. SWP/1 is in beta and may change.

Providers return signatures in one of two shapes. Some sign a hash and return the bare signature value. Others build the whole signature themselves and return a CMS (also called PKCS#7) object. SWP/1 accepts both. Your worker picks one per credential with signature_format.

rawcms
Your provider returnsA bare signature value over a hashA complete detached CMS signature
Who builds the CMSSignatureAPIYour provider
The digest is the SHA-256 ofThe signed attributes SignatureAPI buildsThe PDF’s signed byte range
Signer certificate neededIn the credential responseIn the sign response; optional in credential
sign returnssignaturessignatures and certificates
Static certificateSupportedNot supported

Choose a format

  • Use raw when your provider has a “sign hash” call that returns a signature value. This is the default: a credential that doesn’t declare a format is raw.
  • Use cms when your provider’s API returns a finished CMS or PKCS#7 signature and doesn’t expose the bare value. Some remote signing services, which keep the signer’s key in their own qualified signature creation device, work this way. So do some providers that issue the signer’s certificate only at signing time.

You never need to unpack a provider’s CMS to fit the raw format. Return it as it is, with cms.

The format also decides when your worker needs the certificate, which matters for one-shot certificates. See Choose your provider’s model.

Declare the format

Set signature_format in the credential response:

{
    "status": "completed",
    "credential": {
        "id": "cred_7Qk...",
        "signature_format": "cms",
        "max_signature_size": 16384
    }
}

SignatureAPI then sends "signature_format": "cms" in that session’s sign request. It sends the field on a cms sign only, so a sign request without it is raw. authorize carries no format.

What you sign

Every digest is SHA-256, in both formats. Only its input differs.

  • raw. The SHA-256 of the DER-encoded signed attributes that SignatureAPI builds: content type, message digest and the signing-certificate attribute that names your certificate. That attribute is why a raw credential must return its certificate first.
  • cms. The SHA-256 of the PDF’s signed byte range: the whole document except the space reserved for the signature. Your provider uses it as the CMS message-digest attribute, and builds the rest of the signed attributes itself.

The worker still never sees the document. In both formats it receives one digest.

Requirements on a CMS signature

For cms, each value in signatures is a complete CMS ContentInfo, base64. SignatureAPI checks it before it touches the PDF.

RequirementFailure reason
The value decodes as CMS. DER is preferred. BER is accepted and converted to DER before any other check.cms-malformed
Detached signed data: content type id-data, no encapsulated content, exactly one signer, signed attributes present.cms-structure
The signer is the first certificate in your certificates.cms-signer-certificate
The message-digest attribute equals the digest SignatureAPI sent.cms-message-digest
The signing-certificate-v2 attribute is present and names the signer certificate.cms-signing-certificate
The signature verifies over the signed attributes with the signer certificate’s key.cms-signature

SignatureAPI also accepts these variations:

  • signing-time. Accepted and recorded as evidence. Some validators then label the result PAdES non-baseline and may warn. The signature is still valid.
  • Other signed attributes, such as CMSAlgorithmProtection, are tolerated.
  • id-ecPublicKey as the signature algorithm. SignatureAPI rewrites it to the matching ecdsa-with-SHA* algorithm before it verifies.

What SignatureAPI changes

  • Timestamp. SignatureAPI removes any signature timestamp your provider added and adds one from its own timestamp authority. Every certificate you declared must be valid at that timestamp’s time, or the session fails with certificate-not-valid-at-timestamp.
  • Revocation data. Don’t include CRLs or OCSP responses. SignatureAPI adds revocation data to the PDF itself.

SignatureAPI never changes the signed attributes or the signature value.

Signature size

A PDF reserves a fixed space for each signature before the digest is computed. For cms, declare the largest CMS your provider can return, in bytes, with max_signature_size:

  • Allowed values: 1 to 53,248.
  • Default: 24,576, when you leave it out.
  • Headroom: SignatureAPI adds room for its own timestamp and certificates on top.

A CMS larger than the declared size, or the default, fails the session with signature-too-large. Nothing is ever cut short. Declare the largest size your provider really returns, not the smallest you have seen.

raw credentials don’t declare a size. SignatureAPI sizes the space from the certificate chain.

Certificates

A cms sign response must list the certificates, signer first, in certificates. SignatureAPI checks this chain like any other: each certificate is signed by the next, and each was valid when the sign response arrived.

certificates in credential is optional for cms. When you do return it there, the signer certificate in sign must be the same one, or the session fails with signer-certificate-mismatch. Leave it out when your provider issues the certificate during signing.

The signer certificate can then be newer than the signing date written in the PDF, because that date is fixed before the provider signs. The trusted time of the signature is SignatureAPI’s timestamp. Some validators warn about the earlier date. That’s how the format works, not a defect in your worker.