Remote PDF Digital Signature (External Signature) in C#

To digitally sign a PDF using an external signature provider (e.g. a Remote Signature Service), the PDF data in hashed, the hash is sent to the Remote Signature Service and the resulting signed hash returned by the Remote Signature Service is incorporated on the PDF digital signature block.

To prepare the PDF signature block, the public part of the certificate (the .CER, .CRT) file must be available before performing the remote signature.

void DigitallySignPDFFile(string unsignedDocument, string signedDocument)
{
    PdfSignature ps = new PdfSignature("");

    //load the PDF document
    ps.LoadPdfDocument(unsignedDocument);

    //use SHA-256 hash algorithm
    ps.HashAlgorithm = SignLib.HashAlgorithm.SHA256;

    //the public part of the certificate must be loaded to prepare the digital signature
    //it is the .CER, .CRT, .PEM public part of the certificate
    //it can be exported from an already signed file 
    //it can be obtained from the Certification Autority that issued the certificate

    //set the certificate
    ps.DigitalSignatureCertificate = new X509Certificate2("certificatePublicPart.cer");

    //the hash is sent to the Remote Signature Server and the signed hash
    //is received and added to the PDF digital signature block
    ExternalSignature exSignature = new ExternalSignature();
    //bind the external signature engine with the library
    DigitalCertificate.UseExternalSignatureProvider = exSignature;

    //write the signed file
    File.WriteAllBytes(signedDocument, ps.ApplyDigitalSignature());
}

// Create the external signature using a third party engine. 
// The class must be inherited from SignLib.Certificates.IExternalSignature interface and 
// it must implements the method public byte[] ApplySignature(byte[] dataToSign, Oid oid)
public class ExternalSignature : Certificates.IExternalSignature
{
    private byte[] GetSignedHashFromRemoteServer(byte[] hashToSign)
    {
        //TODO: the byte[] hashToSign is sent to the Remote Signature Server
        //and the signed hash is returned

        //the byte[] hashToSign is sent to the Remote Signature Server
        return Encoding.UTF8.GetBytes("The byte[] hashToSign is sent to the Remote Signature Server and the signedHash returned by the Server will be added on the digital signature");
    }

    public byte[] ApplySignature(byte[] dataToSign, Oid oid)
    {
        //the hash algorithm is considered SHA-256

        //create the PDF data hash
        HashAlgorithm hashAlg = SHA256.Create();

        //calculate the hash of the PDF data
        byte[] pdfDataHash = hashAlg.ComputeHash(dataToSign);

        //the signed hash sent by the Remote Signature Server and 
        //the signature result is added on the PDF signature block
        return GetSignedHashFromRemoteServer(pdfDataHash);
    }
}

See also: