This guide explains how to verify digital signatures in PDF documents using the Vanilla.PDF C API.
For a complete working example, see verify.c.
Overview
PDF digital signatures use PKCS#7 (CMS) format to store cryptographic signatures. Verification involves:
- Cryptographic verification - Verify the signature matches the document content
- Certificate chain validation - Validate the signer's certificate against trusted roots
- Algorithm strength check - Detect weak algorithms (MD5, SHA-1, small keys)
- Time validation - Optionally validate certificate at signing time
Verification Status Codes
The verification result includes a status code indicating the outcome:
| Status | Description |
SignatureStatus_Valid | Signature is cryptographically valid and certificate chain is trusted |
SignatureStatus_Invalid | Signature verification failed (content modified or wrong key) |
SignatureStatus_CertificateExpired | Signing certificate has expired |
SignatureStatus_CertificateNotYetValid | Certificate not yet valid (future start date) |
SignatureStatus_CertificateUntrusted | Certificate chain does not lead to a trusted root |
SignatureStatus_WeakAlgorithm | Weak cryptographic algorithm detected |
SignatureStatus_DocumentModified | Document modified after signing |
Weak Algorithm Detection
The verifier detects the following weak algorithms:
Weak Digest Algorithms:**
MD2, MD4, MD5, SHA-1, MD5-SHA1
Weak Signature Algorithms:**
- MD2/MD4/MD5 with RSA
- SHA-0 with RSA/DSA
- SHA-1 with RSA/DSA/ECDSA
RIPEMD-160 with RSA, MDC2 with RSA
Weak Key Sizes:**
- RSA keys < 2048 bits
- DSA keys < 2048 bits
- EC keys < 256 bits
Creating a Trust Store
Create a trusted certificate store and load certificates:
RETURN_ERROR_IF_NOT_SUCCESS(TrustedCertificateStore_Create(&trust_store));
if (certs_path != NULL) {
printf("Loading trusted certificates from: %s\n", certs_path);
RETURN_ERROR_IF_NOT_SUCCESS(TrustedCertificateStore_LoadFromDirectory(trust_store, certs_path));
} else {
printf("Loading system default trusted certificates\n");
RETURN_ERROR_IF_NOT_SUCCESS(TrustedCertificateStore_LoadSystemDefaults(trust_store));
}
Configuring Verification Settings
Configure verification behavior with custom settings:
RETURN_ERROR_IF_NOT_SUCCESS(SignatureVerificationSettings_Create(&settings));
if (skip_certificate_validation) {
printf("WARNING: Skipping certificate chain validation (insecure)\n");
RETURN_ERROR_IF_NOT_SUCCESS(SignatureVerificationSettings_SetSkipCertificateValidation(settings,
VANILLAPDF_RV_TRUE));
}
if (allow_weak_algorithms) {
printf("Allowing weak cryptographic algorithms\n");
RETURN_ERROR_IF_NOT_SUCCESS(SignatureVerificationSettings_SetAllowWeakAlgorithmsFlag(settings,
VANILLAPDF_RV_TRUE));
}
if (check_signing_time) {
printf("Checking certificate validity at signing time\n");
RETURN_ERROR_IF_NOT_SUCCESS(SignatureVerificationSettings_SetCheckSigningTimeFlag(settings,
VANILLAPDF_RV_TRUE));
}
const boolean_type VANILLAPDF_RV_TRUE
Represents the boolean true value.
Available settings:
SetSkipCertificateValidation - Skip X509 chain validation (testing only)
SetAllowWeakAlgorithmsFlag - Allow MD5, SHA-1, small keys
SetCheckSigningTimeFlag - Validate cert at signing time instead of current time
Verifying a Signature
Call the verification API and inspect the results:
RETURN_ERROR_IF_NOT_SUCCESS(SignatureVerificationResult_GetStatus(result, &status));
RETURN_ERROR_IF_NOT_SUCCESS(SignatureVerificationResult_IsSignatureValid(result, &is_signature_valid));
RETURN_ERROR_IF_NOT_SUCCESS(SignatureVerificationResult_IsDocumentIntact(result, &is_document_intact));
RETURN_ERROR_IF_NOT_SUCCESS(SignatureVerificationResult_IsCertificateTrusted(result, &is_cert_trusted));
RETURN_ERROR_IF_NOT_SUCCESS(SignatureVerificationResult_GetSignerCommonName(result, &signer_name));
RETURN_ERROR_IF_NOT_SUCCESS(SignatureVerificationResult_GetMessage(result, &message_buffer));
error_type CALLING_CONVENTION DigitalSignatureExtensions_Verify(DigitalSignatureHandle *signature, DocumentHandle *document, TrustedCertificateStoreHandle *trusted_store, SignatureVerificationSettingsHandle *settings, SignatureVerificationResultHandle **result)
Verify the digital signature in a PDF document.
Represents memory stored data.
const boolean_type VANILLAPDF_RV_FALSE
Represents the boolean false value.
int8_t boolean_type
Boolean type supported in C.
Definition c_types.h:31
SignatureVerificationStatusType
Overall status of signature verification.
Definition c_signature_verifier.h:37
Command Line Usage
The vanillapdf.tools CLI provides signature verification:
# Basic verification (uses system trust store)
vanillapdf.tools verify -f document.pdf
# Skip certificate validation (for self-signed certificates)
vanillapdf.tools verify -f document.pdf --skip-certificate-validation
# Allow weak algorithms (for legacy documents)
vanillapdf.tools verify -f document.pdf --allow-weak-algorithms
# Check certificate at signing time
vanillapdf.tools verify -f document.pdf --check-signing-time
# Use custom certificate directory
vanillapdf.tools verify -f document.pdf -c /path/to/trusted/certs
# Combine options
vanillapdf.tools verify -f document.pdf \
--allow-weak-algorithms \
--check-signing-time
Security Recommendations
- Always use system trust store - Let the OS manage trusted root certificates
- Avoid
--skip-certificate-validation - Only use for testing self-signed certificates
- Avoid
--allow-weak-algorithms - Only enable when absolutely necessary for legacy documents
- Use
--check-signing-time - For old documents where certificates may have expired
- Keep certificates updated - Ensure your system's certificate store is current
- See also
- verify.c
-
TrustedCertificateStore_Create
-
SignatureVerificationSettings_Create
-
SignatureVerifier_Verify