Password Protected PDFsHow to Remove or Set Passwords For Free

Tax day here in the US is Monday, April 18th this year. As an adult who also owns and runs a business, I let a professional handle my taxes each year. They do a better job thank I and—frankly—they seem to enjoy it far more than I ever will.

When my taxes are ready, they email me a password-protected PDF and ask me to sign it. I love that they are taking my security serious-ish. However, macOS' Preview app won't let me drop an optical signature on the PDF because they also set an owner password to keep me from mucking about with their carefully crafted figures.

Luckily, I figured out a way to use commonly-available open source tooling—vis-a-vis Ghostscript,—to strip these portable documents of their passwords and allow me to sign them.

Removing Passwords

To open the file protected.pdf, protected with the password sekrit, and write an unprotected version to unprotected.pdf, use this:

gs -q -dNOPAUSE -dBATCH \
   -sDEVICE=pdfwrite -sPDFPassword=sekrit \
   -sOutputFile=unprotected.pdf protected.pdf

The -q silences some of the additional output. Drop it to see what you're missing!

The -dBATCH and -dNOPAUSE are pretty standard for command-line work. The former causes gs to exit after the last file is processed (rather than awaiting additional commands from standard input). The latter keeps it from pausing after each page. The -sFOO=bar flags set processing instructions; the first defines the password for reading the file. The second sets the path to write the unprotected PDF to.

If, like me, you hate typing things, you can combine three of the above flags into a single flag: -o:

gs -q \
   -sDEVICE=pdfwrite -sPDFPassword=sekrit \
   -o unprotected.pdf protected.pdf

This handy little flag signals to Ghostscript that you are operating in non-interactive mode, so it tuns on the NOPAUSE and BATCH options for you, and uses the value you give to -o as the OutputFile processing parameter. That's what I call value.

Adding Passwords

You may find yourself starting with an unprotected document and want to add a password, either for the implicit encryption that gives you (hello, email!) or for more advanced content control:

gs -q -sDEVICE=pdfwrite \
   -sOwnerPassword=open-sesame \
   -sUserPassword=sekrit \
   -o locked.pdf unprotected.pdf

This gives us a password-protected PDF, but once the user password has been supplied (and we can read the document) we find that we have the ability to modify it, print it, etc. If that's what you want, great! Otherwise, we can avail ourselves of the permissions system that Adobe built into PDF 1.3 and beyond.

Permissions are set using a 32-bit number, signed and in two's-complement format. The two least significant bits are required to be 0, and the highest 20 bits must be set to 1, as must bits 7 and 8.

1111 1111 1111 1111 1111 .... 11.. ..00

Those unset 8 bits encode permissions, where 1 means "granted" and 0 means "withheld." The full list can be found in the PDF 1.7 reference, in Table 3.20, pp123-124. For illustration, let's remove all permissions except "screen display":

1111 1111 1111 1111 1111 0000 1100 0000

This translates to the hexadecimal 32-bit integer 0xfffff0c0—each block of 1111 is an f, each 0000 is 0x0, and 1100 is c ($8 + 4 = 12$). In decimal (unsigned integer), that's 4294963392, but since this is a two's-complement signed integer (per Adobe, and they oughta know), it's actually -3904.

gs -q -sDEVICE=pdfwrite \
   -sOwnerPassword=open-sesame -sUserPassword=sekrit \
   -dEncryptionR=3 -dPermissions=-3904 \
   -o locked.pdf test.pdf

(Note: the reason we used -dPermissions instead of -sPermissions is because the permissions flag is numeric, and we did not want Ghostscript to set our permissions to the 5 UTF-8 octets -, 3, 9, 0, and 4.)

Here's what locked.pdf looks like when you open it up in Preview on a Mac:

Screenshot of macOS' Preview application, opening a PDF with a user password set.  A dialog in the foreground informs the user that the document is locked, and provides a text box for entry of the user (or owner) password.

After supplying the user password of sekrit, we can see the contents of the PDF (a lovely mandala in the example document I was using):

Screenshot of the locked PDF in Preview, but now we can see what's in it.

As soon as we try to modify the document, for example, to draw on it with the pen:

Screenshot of Preview asking the user for the owner password, since the user tried to draw on the document, thus modifying it.

At this point we must specify the owner password, since we're trying to modify the document in contravention with the permissions (i.e. no changes allowed) set in the document.

And finally, as the owner, we can make changes.

Screenshot of Preview, having been given the owner password, allowing edits to be made against the previously protected document.

Neat, eh?

Looking for More?

If you're interested in diving a bit deeper, here are the resources I found useful while putting this essay together:

Section 3.5.2 of the PDF 1.7 reference covers the Standard Security Header, which defines the owner/user passwords, access permissions that can be restricted to one or both parties, and more. It starts on p120, about halfway down the page. Interestingly, it has this admonition against placing full faith in these "access permissions":

Note: Once the document has been opened and decrypted successfully, the application has access to the entire contents of the document. There is nothing inherent in PDF encryption that enforces the document permissions specified in the encryption dictionary. It is up to the implementors of PDF consumer applications to respect the intent of the document creator by restricting user access to an encrypted PDF file according to the permissions contained in the file.

I found this write-up (original here) on PDF 1.3+ and the Standard Security Handler. I found it enlightening.

While chasing down some printed reference on PDF (ironic, I know), I came across John Whitington, founder of Coherent Graphics in the UK. He wrote a piece of software that I have yet to explore, called Coherent PDF, and its manual is available online (in PDF of course). He also wrote A Machine Made This Book which also looks interesting.

For Ghostscript in particular, I leaned pretty heavily on the High Level Output Devices reference documentation, specifically section 6 for PDF files (i.e. PDFWRITE). You can also find this document in the Ghostscript source distribution, should their docs site go missing in the next few decades.

If you'd like some simple PDF documents to play with permissions and password addition / removal on, here's an unprotected.pdf, and its protected.pdf counterpart. The owner and user passwords match the arguments used in the shell examples above: owner is open-sesame and user is sekrit.

James (@iamjameshunt) works on the Internet, spends his weekends developing new and interesting bits of software and his nights trying to make sense of research papers.

Currently exploring Kubernetes, as both a floor wax and a dessert topping.