RELEASE: What's New in Summer 2024

Implementing Digital Rights Management using a Custom Security Handler

By Roger Dunham | 2024 Aug 02

Sanity Image
Read time

4 min

Summary: Keeping your valuable PDF content secure for paying customers can be a challenge. Avoid the pitfalls of basic password protection with Apryse's DRM solution. The PDFTronCustomSecurityHandler encrypts files and enforces permissions, allowing you to control access, annotations, and more - all while preventing unauthorized sharing.

Introduction

Copied to clipboard

Imagine that your business model is based on customers paying for the content of PDFs that you create. Maybe it’s a financial report, or part of an online teaching course, or even the script for a play.

In some way what you want is Digital Rights Management (DRM), the ability to control who can do what with your PDF content.

In each case, what matters is that you:

  • Allow your customers to easily access the content.
  • Prevent non-customers from being able to access the content.

One obvious way is to password-protect the file. You then tell your customers what the password is, and they enter that in order to view the file. It’s a simple system and works with many PDF viewers, but it is inconvenient to your legitimate users, and if the password becomes known then anyone can access the content whether or not they are a paying customer.

You could reduce the risk of password becoming publicly known by having a different one for each customer or adding a watermark to the PDF, making it possible to identify the source of a leak, even if that was via someone taking screenshots of the protected document. You could then potentially use the threat of legal action to encourage your customers to keep the documents and passwords secure. But, in reality, taking customers to court is not a way to keep them happy and is also likely to become very expensive.

And to further complicate things, you might want to control what your customers can do with the file; perhaps you want them to be able to print the file but not be able to edit it, or vice versa. Document permissions can be specified for a PDF, but they are not universally enforced and can potentially be removed as a way of bypassing them. Digital rights management can help manage these issues by providing more robust and flexible solutions for controlling access and permissions for your digital content.

In this article, we will look at one way to solve this problem, based entirely on Apryse software, with no need for third-party DRM solutions.

Introducing the PDFTronCustomSecurityHandler

Copied to clipboard

The PDFTronCustomSecurityHandler allows you to encrypt the PDF in a way that requires more than just the password to decrypt it.

Even if you know the password and try to open it in a generic PDF reader, you won’t be able to, and you may just get rather unhelpful errors.

Blog image

Figure 1 - The dialog that appears when you try to open a PDF with custom security in Acrobat.

Blog image

Figure 2 - The dialog that appears when you try to open a PDF with custom security in Edge.

Blog image

Figure 3 - The dialog that appears when you try to open a PDF with custom security in Chrome.

Blog image

Figure 4 The dialog that appears when you try to open a PDF with custom security in Xodo.com - at least here it gives you a hint as to what the problem is.

With a dedicated viewer which has been configured to use a Custom Security Handler can be created very easily using either the Apryse SDK or Apryse WebViewer then the file can be opened as if it were just an everyday kind of PDF.

Blog image

Let’s look at how we would implement this.

Encrypting the PDF

Copied to clipboard

The encryption can be formed in a wide range of languages and frameworks – including JavaScript, Python, C#, C++, Go, Ruby, PHP and Java. In this article we will use JavaScript, but the ideas are the same regardless of which language you are using.

The following code is taken from a Node.js based server that has an endpoint that takes the name of the file as a request parameter. That name is then used to identify where the file is located (via inputPath).

const main = async () => { 
 
  const doc = await PDFNet.PDFDoc.createFromFilePath(inputPath); 
  const my_custom_id = 215453; 
  const custom_handler = await PDFNet.PDFTronCustomSecurityHandler.create(my_custom_id); 
 
  // Set a new password required to open a document 
  const my_password = 'test'; 
  custom_handler.changeUserPasswordUString(my_password); 
 
  // Note: document takes the ownership of custom_handler. 
  await doc.setSecurityHandler(custom_handler); 
  await doc.save( 
   outputPath, 
   PDFNet.SDFDoc.SaveOptions.e_remove_unused, 
  ); 
 }; 

Let’s look at how it works.

 

After initializing PDFNet (the code for which is not shown), a PDFDoc object is created from the file at the specified path.

A Custom Security Handler is then created, initialized with an ID (which is a 32-bit integer, in this example, 215453). This number could be the same for all customers, or a unique value could be used for each one.

Next, a user password (which is needed to open the document) is added. In this example the password is ‘test’. A password is not required but is a useful extra layer of security.

The PDFDoc object then has its security handler specified as the new Custom Security Handler.

The rest of the code is used to define what is done with the protected file. In this example it is saved to a known location (which is then read and returned in the response object), but it could instead be saved into a memory buffer which could then be returned directly within the response.

Technical note: The security is not added until the file is saved to file or into a memory buffer.

That’s it.

Decrypting the file

Copied to clipboard

The file is now in a format where just knowing the “Open Document” password is not enough.

As we saw at the start of this article, attempting to open it in a generic PDF reader will fail. Instead, it is necessary to use a tool that knows how to create a Custom Security Handler, and which knows the correct custom_id needed to initialize it.

As an example, let’s look at decrypting the file within the browser.

For this example, we will use a React and Vite WebViewer sample but add a dedicated Input element to allow the user to select the file that should be opened.

import WebViewer from '@pdftron/webviewer'; 
import { useEffect, useRef } from 'react'; 
import './App.css'; 
 
function App() { 
 const viewerDiv = useRef<HTMLDivElement>(null); 
 
 useEffect(() => { 
  WebViewer({ 
   licenseKey: '[Your license key], 
   path: 'lib', 
  }, viewerDiv.current as HTMLDivElement).then((instance) => { 
   const input = document.getElementById('file_upload') as HTMLInputElement; 
   if (input) { 
    input.addEventListener('change', () => { 
     // Get the file from the input 
     if (input.files) { 
      const file = input.files[0]; 
      //@ts-ignore 
      instance.UI.loadDocument(file, { filename: file.name, password:'test', customHandlerId: 215453 }); 
     } 
    }); 
   } 
  }); 
 }, []) 
 return ( 
  <> 
   <label htmlFor="file_upload">Choose A file</label> 
   <input type="file" id="file_upload" name="file_upload" accept=".pdf" /> 
   <div className='webviewer' ref={viewerDiv}></div> 
  </> 
 ) 
} 

In this case the code is much simpler than the way we needed to encrypt the file. Even though the PDF is protected using a custom security handler, it is only necessary to specify the customHandlerId (and the correct ID) when calling instance.UI.loadDocument in order to use it. Everything else is done behind the scenes for you.

You can, if you wish, also include the password (as done here) as an argument when loading the document. Doing so would mean that the file will open without further interaction from the user.

If you prefer to have customers enter the password, then simply don’t include the password as an option when calling instance.UI.loadDocument. In that case, the user must manually enter the password before reading the document.

Blog image

Figure 5 - The result of using the sample code. In this example the password was not included in the code, so the user will need to manually enter the password before the file opens.

While in this sample I used an input element to select the file that was opened, in practice, you would likely want to select the file to be opened via some other mechanism that fits with your overall architecture.

Trying to Beat the System

Copied to clipboard

When you implement a mechanism to enforce DRM, some people will doubtless try to bypass it.

One of the benefits of using WebViewer in this way is that the PDF is still protected by the custom security handler even when it is ‘open’. In the event that a user downloads the PDF in an attempt to share it, then the file will still not be usable outside of the application.

Blog image

Figure 6 - Downloading a protected file from WebViewer results in a file thta is still protected, just as it should be.

While the user could potentially print the file (either to paper or as a PDF), that is also easy to prevent by removing the Print option from the WebViewer hamburger menu.

Better still though, if you wanted, you could allow users to add annotations to the file, perhaps notes for themselves, which can be saved, but can only be reopened in the dedicated version of WebViewer. Once again, the file is protected by the custom security handler.

Blog image

Figure 7 - An example of a comment added to the PDF which was then saved and reopened.

Of course, you might wish to be able to view the protected PDFs in a general-purpose PDF reader. In that case you can use a custom security handler to decrypt the file and remove the security, then save the unprotected file. Those files can then be used as you please but will also be shareable to people that are not your paying customers.

Conclusion

Copied to clipboard

Implementing a DRM system to protect the content of PDFs that you create can be complicated. However, the Apryse system offers an easy solution. There is documentation as well as other blog articles and videos to help you get started quickly.

The technology is necessarily complex, so if you run into problems then reach out to us on Discord.

Sanity Image

Roger Dunham

Share this post

email
linkedIn
twitter