Signature Module Refactoring & Built-in Signature Validation API
We continue the improvements to our Signatures module, elevating the developer experience; The iText Core 8.0.5 release adds a built in API for Digital Signature validation!
We have added the new SignatureValidator
class, as well as the ValidationReport
class. Implementing the SignatureValidator
is quite straightforward, as you will see in the code snippets below.
A (very brief) overview of Digital Signatures
Before discussing how our new SignatureValidator
works, I want to briefly review the purpose and mechanics of digital signatures in general.
Why do we need to use digital signatures?
The purpose of a digital signature is to provide several assurances:
Integrity; The signed PDF we are viewing is exactly the same as it was at the time of signing.
Authenticity; The identity of who signed the PDF should be verifiable.
Non-repudiation; The verified individual who signed the PDF should not be able to deny doing such.
Time of signing; Confirmation of the date and time the document was signed.
How digital signatures use PKI
In PDF, Digital Signatures are created using PKI (public key infrastructure) cryptography. PKI involves the generation of two related keys; A private key that should be kept secret and secure, (we use this key to do the actual signing), and a public key that is used to create a certificate that is then embedded into the digital signature and used for verification. The certificate additionally contains an expiration date, details about the identity of the signer, as well as information about who issued the certificate.
When a PDF Document is signed, all of the bytes within the file (except for the digital signature itself) are hashed, and put into a message digest and the hash is signed using the private key. Integrity is verified using the affiliated public key to check the signed data cryptographically, any change made to the document will change the hash, alerting to the fact that the document has been modified.
Now, the public key can only verify which private key was used to make a digital signature, but we still need to verify the identity of the signer, how do we assure Authenticity? If the digital signature was generated with a self-signed certificate, we unfortunately cannot verify Authenticity nor Non-repudiation, to do this, the signer needs to engage a certificate authority that will confirm their identity.
CAs, Trust Anchors, and the certificate chain
A Certificate Authority (CA) is an entity that issues, validates, and revokes public key certificates, but why should we trust them? Good question. The answer is - we don’t. There are a small number of entities that are Trust Anchors, which are Certificate Authorities that have absolute trust that is taken on faith, and does not need to be cryptographically derived or verified.
To verify the identity within the certificate in our digital signature, and assure Authenticity, we need to trace a path all the way to a trust anchor. We verify the certificate within the digital signature with the CA that issued it, we then have to verify the CA’s certificate with its issuing authority - so on and so forth until we reach a trust anchor, this path is called a certificate chain.
Timestamps, and expiration dates
As the certificate chain is being built, in addition to checking the Authenticity of the signer, it is also checking each certificate’s expiration date, as well as revocation data.
The expiration date is confirmed by involving a Timestamp Authority (TSA), that accepts your signed hash, and signs it using their own private key, and adds a timestamp that we can trust, and can use to confirm that the certificate is not expired. One of the reasons an expiration date is relevant to digital signing, is because cryptographic standards are ever improving. The Integrity assurance is only as strong as the hash used to encrypt the document, and we want to make sure that new digital signatures are created using modern and secure cryptographic standards.
Certificate revocation
The last assurance is Non-repudiation. As we mentioned PKI involves two related keys; one is public, the other is private. If this private key were to ever become compromised, it is critical that its owner reports this so the private key can be added to a revocation list, which will renders its paired certificate invalid prior to its expiration date. Other reasons a key-pair might be added to a revocation list could be if an organization has gone out of business, or changed hands legally. The revocation list is checked by each CA within the certificate chain, if the revocation check passes it is legally assumed that the owner of the key-pair is indeed the party that produced the digital signature. If the revocation check fails, that certificate can no longer be used to legally create digital signatures.
However - it is important to note, currently expired or revoked certificates do not invalidate previous digital signatures that were created prior to the certificate being expired or revoked. Let’s discuss an example of this:
Alice opens her business in January 2024, she generates her certificate so that she can digitally sign all of the invoices and other documents she needs to run her business. On July 1, 2024 Alice’s business merges with a similar business, it’s an exciting time for Alice! Due to this legal change of status, Alice’s certificate is added to the revocation list, and a new certificate is generated to reflect the new business entity. All the digital signatures Alice used to sign her invoices from January through the end of June 2024 are still legally valid! As of July 1, 2024 Alice can no longer use her original certificate to generate new digital signatures, she must use the new certificate that reflects the current legal entity of the business.
Multiple digital signatures
One last thing I want to cover briefly - What about multiple digital signatures?
PDF does not enable digital signatures to be added in parallel, they have to be added in series, and the order does indeed matter. However, won’t the addition of a second digital signature AFTER the completion of the first invalidate it? There is a specific process that does need to be followed to ensure that prior digital signatures remain intact after the addition of subsequent digital signatures. The way we achieve that is we update the document by appending it, which preserves all of the original bytes, and thusly preserves the hash. If the digital signature is added without appending it, the entire document is re-written, the bytes within the message digest change, the hash is invalidated, and the previous digital signature will indeed be flagged as invalid.
Our new dedicated Validation API
Our signature validation process begins at the end of the document, it validates the most recent digital signature first, then reviewing any additional signatures one-by-one in reverse-chronological order. It is important to validate digital signatures in this order, because the timestamp of the digital signature is the data used to determine what content that digital signature is verifying, as well as the expiration date. We begin with the most recent digital signature, we get its timestamp, use that data to validate that signature, and then each previous signature in turn. We then proceed to verify the certificate chain all the way to the trust anchor.
All of this information can be accessed by using the ValidationReport
. In addition to the results of the validation process, the developer can access a list of all failures encountered, as well as a log of all messages encountered during validation.
Java:
public void validateDigitalSignature() throws IOException {
PdfDocument document = new PdfDocument(new PdfReader("docWithDigitalSignatures.pdf"));
SignatureValidator signatureValidator = builder.buildSignatureValidator(document);
ValidationReport report = signatureValidator.validateSignatures();
//returns the result of the validation process - VALID, INVALID, or INDETERMINATE
report.getValidationResult();
//returns all failures recognized during the validation process
report.getFailures();
//returns a list of failures relating to certificate validation
report.getCertificateFailures();
//returns all log messages reported during the validation process
report.getLogs();
//returns log messages reported during the validation process relating to certificate validation
report.getCertificateLogs();
}
.NET:
public void ValidateDigitalSignature() {
PdfDocument document = new PdfDocument(new PdfReader("docWithDigitalSignatures.pdf"));
SignatureValidator signatureValidator = builder.BuildSignatureValidator(document);
ValidationReport report = signatureValidator.ValidateSignatures();
//returns the result of the validation process - VALID, INVALID, or INDETERMINATE
report.GetValidationResult();
//returns all failures recognized during the validation process
report.GetFailures();
//returns a list of failures relating to certificate validation
report.GetCertificateFailures();
//returns all log messages reported during the validation process
report.GetLogs();
//returns log messages reported during the validation process relating to certificate validation
report.GetCertificateLogs();
}
Our previous updates to the Sign module include:
In the iText 8.0.3 release we added
PadesTwoPhaseSigningHelper
; a helper class enabling fast and easy two-step signing.The iText 8.0.2 release saw the addition of the
PdfPadesSigner
class to enable convenient application of PAdES baseline levels, as well as the addition of theSignatureFieldAppearance
API.In the iText 8.0.1 release we added algorithm agnostic signing and validation, to enable use of algorithms that aren’t directly supported by iText, but supported by the underlying Bouncy Castle cryptographic library.
With the iText 8.0.0 release we introduced our intentions of improving the sign module! We included a brand new implementation of BouncyCastle, including integration of two new modules:
bouncy-castle-adapter
, andbouncy-castle-fips-adapter
to assist usage of the BouncyCastle FIPS API. We also added a number of new features and support for the latest cryptographic related extensions to PDF 2.0. Including support for SHA-3 hash functions as specified in ISO/TS 32001, as well as support for modern elliptical curves from ISO/TS 32002.