Digital signatures in PDF

From
Jump to: navigation, search

Overview

Digial signatures do have the same power like their physical counterparts, but instead can be added without taking a pen or even without having a person signing the paper. They are based on so-called digital certificates, similar to those used for data encryption. It's a complex subject and we won't go to various mathematical aspects behind it, while will rather describe its difference from the regular signatures and how one can get PDF documents signed this way.

A list below shows some of the very important differences between regular and digital signatures:

  • digital signature guarantees the integrity of the document, it's not possible to change its content after the signing without the person reading the document noticing it
  • with digital signatures the identity of the person is easier to validate, so you always know who signed the document and when, it's possible to use an external timestamp server for getting a correct timestamp during the signing
  • digital means paperless, so no need to print something and the document may remain digital during its lifetime
  • digital signning can be automated, so it becomes possible for companies to process millions of documents very fast without a need for a manual labor, so bills, forms, orders can be signed without any human intervention by a company's signature if needed
  • it's possible to have digital signatures long term validated (LTV signatures) and documents suitable for archiving using the OCSP and CRL responses from the signing authority embedded during the signing

The PDF specification explains this subjecy in details in section 12.8 “Digital Signatures”, so if you're interested in under the hood tech the information given there can't be underestimated. Apitron PDF Kit implements all you need to sign PDF documents digitally, and the typical signing workflow is described in details below.

Digital signature in PDF usually consists of a signature field (implemented by a SignatureField class) added to FixedDocument.AcroForm collection in Fixed layout API or FlowDocument.Fields collection in Flow layout API and optionally its visual representation on one or more pages added using the corresponding widget annotation object implemented by a SignatureFieldView class.

LTV signatures

Long term validation signatures are quite specific, they are the same as normal signatures but intented for somehow longer archiving or processing without one having an ability to make a validation request to the original authority that issued the signing certificate. That's said they should carry all the information necessary to validate them with themselves. OCSP and CRL responses are the things that can be embedded into the signature and help to validate it later in case the issuing authority is out of the business or inaccessible. In practice, however, you'd rarely find an OCSP response with a validity for more than a few hours after the time the request has been made, so LTV signature's validity is heavily dependend on the signing authority.

CAdES signatures

A class CAdESSignature provides support for the advanced signatures defined by the further development of the cryptographics message syntax (CMS) standard. A digital signature, technically implemented based on CAdES has the status of an advanced electronic signature.

If it's a CAdES signature then,

  • it is uniquely linked to the signer
  • it is capable of identifying signer
  • only the signer has control of the data used for the creation of the signature
  • if the data attached to the signature has been changed after the signing, then it can be identified

A resulting property of CAdES is that digitally signed documents can remain valid for long periods, even if the signer later attempts to deny the validity of the signature. It's appears to be a better alternative to LTV signatures.

Signing using smart cards and cryptographic tokens

For signing you need a private key associated with a digital certificate, but sometimes the only thing your customers have is a some kind of cryptographics token: an USB device or a smart card implementing for example PKCS#11 standard - a platform independent cryptographics token interface, and they don't have any ability to get the direct access to the private key itself. Usually token providers supply drivers compatible with windows crypto API or tokend-based solution for a linux-based system, so you can actually call the signing routines provided by the token and Apitron PDF Kit supplies a specific interface you could implement to handle your particular case. It's called ISignatureServiceProvider and if you need a time stamp for you signatures you'd have to also implement ITimeStampingAuthority interface.

Validate signatures in PDF documents

Validation is a complex task which includes checking the revokation status of the certificates used for signing and integrity of the PDF document's content. Application developers prefer to implement cert's validity checks themselves, so Apitron PDF Kit implements only the second part, thus allowing to quickly check if the content of the document remains non tampered. For doing so you may iterate through the document's fields by using the FixedDocument.AcroForm property of the FixedDocument object and checking the IsValid property of every SignatureField found. It's shown in the following code sample.

Code samples

Sign PDF document with a digital certificate

The code below creates a signature object from a self-signed x509 certificate with a password set, and adds SHA256 RSA signature to the target document. It also creates its visual representation that looks as a handwritten signature, using an image XObject. Any PDF document can contain several signatures and they all can be easily added using either Fixed layout API or Flow layout API provided by the Apitron PDF Kit. If you use a self-signed certificate and it’s not added to the list of the trusted certificates then the reader may warn you that it couldn't validate the certificate used for signing the document.

// create output PDF file
using (FileStream outputStream = new FileStream("security.pdf", FileMode.Create, FileAccess.ReadWrite))
{
    // create new PDF document
    FixedDocument document = new FixedDocument();
    // add empty page
    document.Pages.Add(new Page());
    
    // register signature image
    document.ResourceManager.RegisterResource(new
    Image("signatureImageJoe","signatureImage.png"));
    
    // create signature field and add to the document
    SignatureField signatureField = new SignatureField("mySignature");
    document.AcroForm.Fields.Add(signatureField);
    
    // set signature certificate that will be used to sign the document
    using (Stream signatureStream = new FileStream("johndoe.pfx", FileMode.Open, FileAccess.Read)) 
    {
        signatureField.Signature = Signature.Create(new Pkcs12Store(signatureStream, "password"));
    }
    
    // create annotation object representing a signature
    SignatureFieldView signatureView = new SignatureFieldView(signatureField,new
    Boundary(10,800,150,830));
    signatureView.ViewSettings = new SignatureFieldViewSettings()
    {
        Graphic = Graphic.Image,
        GraphicResourceID = "signatureImageJoe",
        Description = Description.None
    };
    
    // add visual representation of the signature onto PDF page
    document.Pages[0].Annotations.Add(signatureView);
    document.Save(outputStream);
}
 

Images below show the resulting signature view and signature properties panel, note that it says that the signature is LTV, that's because the signing certificate is self-signed:

Sign PDF document


Signature properties panel


Sign PDF document multiple times with different digital certificates

If you need to sign the PDF document multiple times, just add additional signatures in the same way as you add one. See the sample code below demonstrating this technique.

public void SignPDFDocumentMultipleTimes()
{   
    // open existing document for update
    using (Stream inputStream = new FileStream("signed document.pdf",
        FileMode.Open,FileAccess.ReadWrite))
    {
        using (FixedDocument doc = new FixedDocument(inputStream))
        {
            // register signature image resource
            doc.ResourceManager.RegisterResource( new Image("signatureImage",  "signatureImage.png"));
            doc.ResourceManager.RegisterResource( new Image("signatureImage2", "signatureImage2.png"));
            
            // create first signature field and initialize it using a stored certificate
            SignatureField signatureField = new SignatureField("signature");
            using (Stream signatureDataStream = File.OpenRead("JohnDoe.pfx"))
            {
              signatureField.Signature=Signature.Create(new Pkcs12Store(signatureDataStream,
                 "password"));
            }
            
            // create second signature field and initialize it using a stored certificate
            SignatureField signatureField2 = new SignatureField("signature2");
            using (Stream signatureDataStream = File.OpenRead("JaneDoe.pfx"))
            {
             signatureField2.Signature=Signature.Create(new Pkcs12Store(signatureDataStream,
                 "password"));
            }
            
            // add signature fields to the document
            doc.AcroForm.Fields.Add(signatureField);
            doc.AcroForm.Fields.Add(signatureField2);
            
            // create first signature view using the image resource
            SignatureFieldView signatureView = new SignatureFieldView(signatureField, new Boundary(10, 750, 110, 800));
            signatureView.ViewSettings.Graphic = Graphic.Image;
            signatureView.ViewSettings.GraphicResourceID = "signatureImage";
            signatureView.ViewSettings.Description = Description.None;
            
            // create second signature view using the image resource
            SignatureFieldView signatureView2 = new SignatureFieldView(signatureField2, new Boundary(120, 750, 220, 800));
            signatureView2.ViewSettings.Graphic = Graphic.Image;
            signatureView2.ViewSettings.GraphicResourceID = "signatureImage2";
            signatureView2.ViewSettings.Description = Description.None;
            
            // add views to page annotations collection
            doc.Pages[0].Annotations.Add(signatureView);
            doc.Pages[0].Annotations.Add(signatureView2);
            
            // save as incremental update
            doc.Save();
        }
    }
}
 

This code performs an incremental update on a PDF file and signs it using several signatures. See the image below demonstrating the result:

Sign PDF document multiple times


Sign PDF document using Flow layout API

The Flow layout API is not limited to just creating the documents, it has full support for PDF forms and of course for signing. The code below shows how to sign a newly created PDF document using Flow layout API. It looks similar to the fixed layout sample except is uses SignatureControl content element which creates a placeholder for the actual widget annotation (signature view).

public void SignDocumentUsingFlowLayout()
{
    //  create output document
    using (Stream outputStream = File.Create("signed document.pdf"))
    {
        ResourceManager resourceManager = new ResourceManager();
        
        // register signature image resource
        resourceManager.RegisterResource(new Apitron.PDF.Kit.FixedLayout.Resources.XObjects.Image("signatureImage", "signatureImage.png"));
        
        // create flow document
        FlowDocument doc = new FlowDocument(){Margin = new Thickness(10)};
        
        // create signature field and initialize it using a stored
        // password protected certificate
        SignatureField signatureField = new SignatureField("signature");
        using (Stream signatureDataStream = File.OpenRead("JohnDoe.pfx"))
        {
          signatureField.Signature=Signature.Create(new Pkcs12Store(signatureDataStream, "password"));       
        }
       
        // create signature view using the image resource
        SignatureFieldView signatureView = new SignatureFieldView(signatureField, new Boundary(10, 750, 110, 800));
        signatureView.ViewSettings.Graphic = Graphic.Image;
        signatureView.ViewSettings.GraphicResourceID = "signatureImage";
        signatureView.ViewSettings.Description = Description.None;    
       
        // set signature field's view
        signatureField.Views.Add(signatureView);
        
        // add signature field to a document
        doc.Fields.Add(signatureField);
        
        // add text and signature control representing the signature
        doc.Add(new TextBlock("Signed using Apitron PDF Kit for .NET"));       
        doc.Add(new SignatureControl("signature"){Width = 100, Height = 50});
        
        // save document
        doc.Write(outputStream,resourceManager);   
    }
}
 
Sign PDF document using Flow layout API

Validate digital signatures in PDF document

The code below checks whether the document has changes added after signing. It doesn’t validate the certificate itself because such algorithm is not defined in PDF specification and it’s up to the user to decide whether certificate can be trusted or not.

using (FileStream inputStream = new FileStream("security.pdf", FileMode.Open, FileAccess.Read))
{
    // open password protected PDF document
    FixedDocument document = new FixedDocument(inputStream);
    
    // check all signature fields
    foreach (SignatureField signatureField in document.AcroForm.Fields.OfType<SignatureField>())
    {
        Console.WriteLine("Signature found: {0}", signatureField.IsValid ? "Valid" : "Invalid"); 
    }
}
 

Output produced by this code is shown below, input file used was generated by this sample:

Validate digitally signed PDF document