How do I implement custom PDF security (C/C++)?

Q: I want to implement custom PDF security (using PDFNet for C/++).
How can I derive a class from SecurityHandler and implement
SecurityHandler’s interface? Is there any example for me to reference?
-----
A: In order to implement a custom security handler in C/C++ you need
to derive a class from SecurityHandler and implement SecurityHandler’s
interface. For a description of SecurityHandler's methods consult
'SecurityHandler.h'.

A good starting point for your project would be the this code example
in EncTest sample project (the one that implements MySecurityHandlers
class; http://www.pdftron.com/net/samplecode.html#EncTest). A class
derived from a SecurityHandler will usually override one or more
methods from the following list:

Clone - must be implemented in every derived class.
Authorize
AuthorizeFailed
GetAuthorizationData
EditSecurityData
FillEncryptDict

A custom security handler should also implement a factory method. For
example:

static TRN_SecurityHandler MySecurityHandler::Create(const char* name,
int key_len, int enc_code) {
  MySecurityHandler* ret = new MySecurityHandler (key_len, enc_code);
  // Explicitly specify which methods are overloaded.
  ret->SetDerived(
         has_CloneProc |
         has_AuthFailedProc |
         has_GetAuthDataProc |
          has_FillEncDictProc);
  return (TRN_SecurityHandler) ret->mp_handler;
}

Please note that in the factory method you need to explicitly specify
which methods are overloaded using SecurityHandler::SetDerived()
method.

In order for PDFNet to invoke your custom security handler you should
register it using PDFNet::RegisterSecurityHandler(), usually just
after PDFNet::Initialize() is called:

// Register standard security. Required only once per application
session.
PDFNet::RegisterSecurityHandler("Standard", "Standard Security",
MySecurityHandler::Create);
PDFNet::RegisterSecurityHandler("Sprint", "MySecurity",
MySecurityHandler::Create);

For applications that need to implement custom security handler the
most relevant method is FillEncryptDict. This method will be called
when an encrypted document is saved. The method fills the document's
Encryption dictionary with whatever information the security handler
wants to store in the document.

The following is a sample implementation for FillEncryptDict that
simply renames the filter name (as a result PDF documents saved using
this handler will not open in Acrobat or any other PDF consumer):

Obj MySecurityHandler::FillEncryptDict(SDFDoc& doc) {
  TRN_Obj r;
  TRN_SecurityHandlerFillEncryptDict(mp_handler, doc.mp_doc, &r);
  Obj enc_dict(r);
  if (enc_dict) enc_dict.PutName( "Filter", "MySecurity" );
  return enc_dict;
}

Of course this particular handler could be easily cracked by renaming
the filter name to 'Standard' (e.g. using a low-level utility such as
CosEdit (http://www.pdftron.com/cosedit)), however the same approach
can be used to implement more advanced security handlers (in this case
the user could store additional data in the enc_dict such as strings,
numbers, dictionaries, or arrays).

A customer asked similar question for C#, where you can do the following to have Standard security, but with a custom filter name.

var handler = new StdSecurityHandler(128, 2); handler.ChangeUserPassword("test"); doc.SetSecurityHandler(handler); doc.Save(output_path, SDFDoc.SaveOptions.e_linearized); // file is now encrypted Obj o = doc.GetTrailer().FindObj("Encrypt"); o.PutName("Filter", "MyCustomFilterName"); // optionally add custom string. Strings on the Encrypt dictionary are never encrypted //o.PutString("MyKey", "MyValue"); doc.Save(output_path, SDFDoc.SaveOptions.e_linearized); // now file is encrypted the same way, but with custom filter name.