Introduction
Four years ago, I wrote an article about signing a PDF document using the iTextSharp library. I was surprised by the number of comments and emails I received about it.
Many people asked me for new features and ideas, I didn't have enough time to answer them all for two reasons:
- I had not enough spare time to implement the new features
- I was not able to implement some features they asked for because of the lack of iTextSharp documentation, and some bugs/lacks in older versions.
Now iTextSharp v5.x is out and comes with many new features. This article will only cover the digital signature, encryption, and meta-data manipulation parts. iTextSharp is more than this, it allows you to create and manipulate PDF without using any proprietary library!
I developed iSafePDF for my own needs and tried to implement features that many people asked for: loading certificates from a local user store, time-stamped signature, and PDF encryption (only password encryption is supported right now).
Getting started
You can read my first article about digital signature "E-signing PDF documents with iTextSharp". It describes an old and simple code (the base code of iSafePDF) which is easier to understand.
What you have to know, is that PDF digital signature and encryption provided by iTextSharp library are all PDF standards. this mean that any PDF viewer will be able to read encrypted document (if you provide the encryption password) and check signature without the need to install 3rd party plugin or so.
Using the binary
This article comes with the iSafePDF binary. No setup is needed, all you have to do is to uncompress the zip file and put the exe program somewhere in your disk and then run it.
The document tab
In this tab, you have to choose at least:
- The source file: this is the document you want to sign, the document itself will not be modified.
- The target file: this document will be a copy of the source document to which the signature and encryption will be applied.
If you want, you can modify the document meta-data.
The signature tab
This tab allows you to control the digital signature. If you have locally installed certificates you will see them in the Certificates list. You also have the choice to sign your document using a pfx file if certificates are exported to pfx format (see my first article for more information).
PDF Signature standard allows you to add three fields to the digital signature: the reason, the contact, and the location they are visible when you visualize the digital signature information.
If you want, you can make the signature visible in the document; in this case, it will be put on the first page in the lower left corner (in the next release, I'll add more options to configure visible signatures: position, custom image ...etc).
The PDF standard allows you to use a time stamp authority (TSA); using this feature will make your document signature valid even if the digital signature certificate expires, as the TSA will prove that the certificate was valid when the document was signed.
Notes
Encryption tab
Here, you can choose to activate or not the document encryption; if encryption is active, you need to enter two passwords. The user password allows you to open and read the document, plus do what encryption allows you to do. The owner password allows you to modify encryption options using iSagePDF or another PDF manipulation program. It also allows you to open and read the document.
The source code
You can get the latest source code version from the iSagePDF official site: http://isafepdf.eurekaa.org/.
The most important method in the code is the Sign
method. Please refer to my first article ("E-signing PDF documents with iTextSharp") to read the description of a simpler Sign
method version (without encryption and timestamp).
The old Sign
method used a WINCER_SIGNED
signature type. This method is easier to implement because iTextSharp does all the signature jobs, but this option doesn't allow TSA support. To support TSA, we need to use the SELF_SIGNED
signature type. Using this option gives us more control on the signature process, but then we need to calculate the signature digest. Below is a piece of code from the new Sign()
method implementing the self signed document signature type:
sap.SetCrypto(null, this.myCert.Chain, null, PdfSignatureAppearance.SELF_SIGNED);
...
PdfSignature dic = new PdfSignature(PdfName.ADOBE_PPKLITE,
new PdfName("adbe.pkcs7.detached"));
...
PdfPKCS7 sgn = new PdfPKCS7(this.myCert.Akp,
this.myCert.Chain, null, "SHA1", false);
IDigest messageDigest = DigestUtilities.GetDigest("SHA1");
Stream data = sap.RangeStream;
byte[] buf = new byte[8192];
int n;
while ((n = data.Read(buf, 0, buf.Length)) > 0)
{
messageDigest.BlockUpdate(buf, 0, n);
}
byte[] hash = new byte[messageDigest.GetDigestSize()];
messageDigest.DoFinal(hash, 0);
DateTime cal = DateTime.Now;
byte[] ocsp = null;
if (this.myCert.Chain.Length >= 2)
{
String url = PdfPKCS7.GetOCSPURL(this.myCert.Chain[0]);
if (url != null && url.Length > 0)
ocsp = new OcspClientBouncyCastle(this.myCert.Chain[0],
this.myCert.Chain[1], url).GetEncoded();
}
byte[] sh = sgn.GetAuthenticatedAttributeBytes(hash, cal, ocsp);
sgn.Update(sh, 0, sh.Length);
The piece of code to add TSA is:
byte[] encodedSigTsa = sgn.GetEncodedPKCS7(hash, cal, this.myCert.Tsc, ocsp);
System.Array.Copy(encodedSigTsa, 0, paddedSig, 0, encodedSigTsa.Length);
To support PDF encryption, I added a new class called PDFEncryption
(see PDFEncryption.cs).
I will enumerate all the PDF encryption types:
public enum permissionType {
Assembly = PdfWriter.ALLOW_ASSEMBLY,
Copy = PdfWriter.ALLOW_COPY,
DegradedPrinting = PdfWriter.ALLOW_DEGRADED_PRINTING,
FillIn = PdfWriter.ALLOW_FILL_IN,
ModifyAnnotation = PdfWriter.ALLOW_MODIFY_ANNOTATIONS,
ModifyContent = PdfWriter.ALLOW_MODIFY_CONTENTS,
Printing = PdfWriter.ALLOW_PRINTING,
ScreenReaders = PdfWriter.ALLOW_SCREENREADERS };
The encryption method using a permission list is quite simple with iTextSharp (we use the PDFStamper).
public List<permissionType> Permissions = new List<permissionType>();
...
public void Encrypt(PdfStamper stamper)
{
int permission = 0;
foreach (int i in this.Permissions)
{
permission |= (int)i;
}
stamper.SetEncryption(this.Encryption, this.UserPwd, this.OwnerPwd, permission);
}
The future of iSafePDF
I'm planning to make iSafePDF as complete as possible with new features related to PDF security and encryption. The next release will add more configuration options to visual signature: choose custom signature position, and use a custom image (a scanned signature, for example).
I'll also add a console version, and an API to make batch processing easier, in a future release.
To get the latest binaries/source code of iSafePDF, please visit the official website: http://isafepdf.eurekaa.org/.