# Verify signatures in your own systems

Signature verification checks that the signed bytes match the document, then validates the signer's X.509 certificate against the certificate authority and revocation data. The examples below apply to server-side signatures returned by the signing iframe or hash-signing API. A PAdES PDF contains its signature and certificate inside the file.

## 1. Check a signature when you receive it

Before saving a signing result, check that it belongs to the requested document and approval:

- `documentHash` equals the SHA-256 of the exact document you asked the user to sign.
- `levelOfAssurance` (iframe) or `loa` (hash signing) is the level you requested.
- `userVerified` is `true` for iframe signatures.

Store the complete signing payload with the document and its operation or request ID. It contains the signature, signed hash, timestamp and assurance level needed for later verification.

Download the signer certificate while the user's access token is available. With the `signa-certificate` scope, tokens contain `signa_certificate_url`, `signa_certificate_serial` and `signa_certificate_subject`. An authenticated `GET` to `signa_certificate_url` (`/pki/certificate/me/pem`) returns the certificate in PEM format.

## 2. Validate against the certificate authority

The trust anchor and revocation data are available at these public endpoints:

| Resource | Endpoint | What you get |
|---|---|---|
| CA certificate | `GET /pki/ca-cert` | The trust anchor, in PEM |
| Revocation list | `GET /pki/crl` | The current CRL |
| Certificate status | `GET /pki/ocsp?serialNumber=<serial>` (or `certId=<id>`) | JSON with `status` `good`, `revoked` (with `revocationTime` and `revocationReason`) or `unknown`. You can also `POST` the same parameters as JSON. |

The iframe's `signatureBase64` and hash-signing result's `signature` contain a base64-encoded DER ECDSA signature using P-256. Save the certificate as `signer.pem`, the signature string as `signature.b64` and the original document as `document.pdf`, then run:

```bash
curl -s https://securysign.com/api/pki/ca-cert -o ca.crt
openssl verify -CAfile ca.crt signer.pem                      # the certificate chains to the CA
openssl x509 -in signer.pem -pubkey -noout > signer.pub
base64 -d signature.b64 > signature.der                        # signatureBase64, decoded
openssl dgst -sha256 -verify signer.pub -signature signature.der document.pdf
```

If the [certificate chain](#/docs/api-certificates#3-read-the-signers-certificate) includes an intermediate, save the `certificatePem` from each `intermediate` entry to `intermediates.pem`, one after another. Include that file when checking the signer certificate:

```bash
openssl verify -CAfile ca.crt -untrusted intermediates.pem signer.pem
```

For a PAdES PDF, use a PDF validator that reads the embedded certificate and signature. Configure SecurySign's CA certificate as the trust anchor before validating the signed PDF.

If validation fails, first check that `document.pdf` is the exact signed file and the certificate belongs to the signing key. Evaluate certificate validity and revocation at the relevant signing time: an expired certificate can still verify a signature made while it was valid.

## 3. Read the signer's certificate

Retrieve the customer's certificates using their access token from [single sign-on](#/docs/sso):

```bash
curl https://securysign.com/api/pki/certificates/me \
  -H "Authorization: Bearer $USER_ACCESS_TOKEN"
```

```json
{
  "status": "active",
  "credentialId": "cred_abc123",
  "certificate": {
    "certificateId": 123,
    "commonName": "JANE DOE",
    "serialNumberHex": "4F2A…",
    "validFrom": "2026-09-01 10:00:00",
    "validUntil": "2027-09-01 10:00:00",
    "certificatePem": "-----BEGIN CERTIFICATE-----…"
  }
}
```

A `status: "none"` result means the customer needs to complete [Enrolment](#/docs/enrolment) to obtain a certificate. `GET /pki/certificate/me/pem` downloads the current certificate in PEM format. To retrieve a specific certificate, use `GET /pki/certificate/{id}` with its owner's token; another caller receives `403 Forbidden`.

Use `GET /pki/certificate/{id}/chain` with the owner's token to retrieve the chain. Its `chain` array starts with the `end-entity` certificate, includes an `intermediate` when configured, and ends with the `root`. Each entry identifies its `type`. The same chain is displayed in the web app at `https://securysign.com/#/certificate/<id>/chain`.

See [Manage the certificate](#/docs/enrolment#manage-the-certificate) for renewal and passkey-approved revocation, and the [endpoint schemas](#/docs/api-certificates#endpoints) for complete certificate responses. [Verification](#/docs/verification) covers checks in the web app.
