Note that this is part of a series where we use APDFL to extract or recreate the information contained in the Adobe Acrobat’s Document Properties tab.
Recreating this tab, the security tab, required examining hundreds of different PDFs in order to distill the secret sauce behind this tab. I may not have come up with Coca-cola‘s closely-guarded recipe, but I can give your off-brand cola a run for its money. At least when it comes to PDF Password security; Certificate Security and Adobe LiveCycle Rights Management would require plugins to APDFL which simply are not available to us, and so that functionality will remain unexamined. Nobody really uses it anyway.
The basic formula is that you can do anything to a PDF that is not encrypted or signed, but if the file is password protected, then a bunch of abilities to manipulate the file are taken away unless granted back by twiddling some bits; alternatively once a file is signed, you can’t modify it in such a way as to break the signature (that includes certifying the document, signing a signature field, or applying Usage Rights) but with Usage Rights you can toggle some rights with or without encrypting the file.
Confused yet? Don’t worry, it will all become as clear as mud once we start digging into the code that reproduces the Security Tab’s information content. So let’s get started.
The first item is determining the Security method for which as previously mentioned, there are only two possibilities available to us:
If we have Security data, we have a password-protected file, if not we don’t. Moving on.
Determining which version of Acrobat can open a password-protected file largely keys off of which Revision of the Security data we are examining, but in a couple of cases, we need to also look at another piece of the Security data to figure out the correct Acrobat version:
Next, we need to figure out if the document’s metadata was left unencrypted or not (something that was not possible in early revisions of the Standard Security algorithm):
Before we get to the bit-twiddling within the security data, we need to see if there’s a Perms entry in the root catalog as there are additional boolean values we will need to consider.
Basically, we are looking for a DocMDP entry under perms to indicate that the PDF has been certified, or we are looking for either UR3 or UR to indicate that the PDF has Reader-enabling Usage Rights. If it does have Usage Rights, then we are going to assume that they lack certain rights until we find mention of those rights in the TransFormParams.
Now, on to the bit-twiddling. The first one is easy enough and the rest essentially build ever more Baroque ornamentation on top of this structure:
if there’s no Security data or if the pdPermPrint bit is set, then printing the document will be allowed. Otherwise, not.
Changing the Document:
Only allowed if there’s no signature or the pdPermEdit flag is set. The Usage Rights signature overrides the pdPermEdit flag. but note:
Document Assembly: basically the same as Changing the Document, but in some Revisions, there is also a pdPrivPermDocAssembly bit flag to consider:
Content Copying and Content Copying for Accessibility: The first is straightforward, the latter has another bit to consider, and let’s throw in PDDocPermRequest() into the mix even though it hasn’t been useful up until now.
Page Extraction is all PDDocPermRequest:
But back to bit-twiddling for commenting:
Filling of form fields, Signing, and Creation of Template Pages all key off of mostly the same flags, except for Creation of Template Pages which also pays attention to the pdPermEdit flag since adding new pages will alter the structure of the document, otherwise these fields only differ by the Usage Rights granted or not.
Lastly, we report whether the document has a signature which caused these values to be altered:
The full code for this sample app is here.