Cuminas DjVu SDK for .NET Framework
Handling Secure DjVu

Creating Secure DjVu from Normal DjVu

The following code illustrates the flow to create Secure DjVu file:

securedjvu.cs
Copy Code
using System;
using DjVu;
namespace SecureDjVu
{
  class SecureDjVu
  {
    static void Main(string[] args)
    {
      // TODO: ADD app's license script here or REMOVE the following line
      LicenseManager.LicenseScript = "......";

      using (Document doc = new Document(args[0]))
      {
        using (SecurityProvider secProv = SecurityProvider.CreatePWD1("admin"))
 
        {
          // admin can do anything (owner)
          UserPropertySet admin = secProv.CurrentUserPropertySet;
          admin.Password = "admin-password";
          admin.PrivsAndProps[PrivsAndProps.Owner] = true;
 
          // user1 can do print only
          UserPropertySet user1 = secProv.UserPropertySets.AddUserPropertySet("user1");
          user1.Password = "user1-password";
          user1.PrivsAndProps[PrivsAndProps.Print] = true;
 
          // user2 can do print/save only
          UserPropertySet user2 = secProv.UserPropertySets.AddUserPropertySet("user2");    
          user2.Password = "user2-password";
          user2.PrivsAndProps[PrivsAndProps.Export] = true;
          user2.PrivsAndProps[PrivsAndProps.Print] = true;
 
          doc.SaveAs(args[1], secProv);
        }
      }
    }
  }
}

Open a Secure DjVu File

Secure DjVu typically protects its content by user IDs and their associated passwords. And the actual authentication takes place when some of the content is about to load onto the memory. In other words, if the program only opens a secure DjVu file by a Document Constructor, it does not invoke authentication process. The approach is good for certain kind of applications which do not care about the actual contents.

When a Document object decodes a protected part of a Secure DjVu file, it invokes Document.AuthenticateUser Event. If the object does not set any handlers to it, the authentication process will fail. If the authentication succeeds, Document.AuthenticationSucceeded Event is invoked.

The following code is a minimum sample to resave (decrypt) a Secure DjVu file to a DjVu file:

authsdjv.cs
Copy Code
using System;
using DjVu;

namespace AuthSecureDjVu
{
  class AuthSecureDjVu
  {
    static void Main(string[] args)
    {
      // TODO: ADD app's license script here or REMOVE the following line
      LicenseManager.LicenseScript = "......";

      using (Document doc = new Document(args[0]))
      {
        // authentication event handler
        doc.AuthenticateUser += authenticateUser;
       
        // save in plain DjVu file
        doc.SaveAs(args[1]);
      }
    }
   
    static void authenticateUser(object sender, CredentialEventArgs e)
    {
      Console.WriteLine("Authentication Event Handler Called!");
      e.UserId = "mike";
      e.Password = "mike's password";
    }
  }
}

Owner Privileges

The sample above is not a perfect sample. Save functions such as Document.SaveAs Method is only allowed if the user has either PrivsAndProps.Export or PrivsAndProps.Owner privilege; otherwise the method throws an exception during the saving process.

You can also determine whether the user has certain privileges or not by checking Document.SecurityProvider Property. The following code illustrates how to do this:

authsdjv2.cs
Copy Code
using System;
using DjVu;
namespace DecodingSecureDjVu2
{
  class DecodingSecureDjVu2
  {
    static void Main(string[] args)
    {
      // TODO: ADD app's license script here or REMOVE the following line
      LicenseManager.LicenseScript = "......";

      using (Document doc = new Document(args[0]))
      {
        // authentication event handler
        doc.AuthenticateUser += (sender, e) => {
          Console.WriteLine("Authentication Event Handler Called!");
          e.UserId = "admin";
          e.Password = "admin-password";
        };
 
        // determine whether the user can export or not
        UserPropertySet userProps = doc.SecurityProvider.CurrentUserPropertySet;
        if (userProps.PrivsAndProps.IsPermitted(PrivsAndProps.Export))
        {
          // save in plain DjVu file
          doc.SaveAs(args[1]);
        }
        else
        {
          Console.WriteLine("Save is not allowed.");
        }
      }
    }
  }
}

Privileges and Properties

Secure DjVu controls user's permission by predefined privileges and properties. As it is already explained above, each user is assigned a set of privileges and properties. For the full list of privileges and properties and their definitions, see PrivsAndProps Enumeration.

Security Enforcement on Viewer/Decoder Applications

DjVu# and its underlying DjVu SDK, incorporates implicit security enforcement layer on certain functions such as Save methods. If the user does not have PrivsAndProps.Export, Save methods throws certain exception according to the Save behavior. But DjVu#/DjVu SDK  could not block extraction of textual information and/or images, which results in export, copy or print on the application. Therefore, applications should implement explicit security checks before doing such actions.

This is one of the requirement on applications to support Feature.SecureDjVuDecode. If your application does not implement security checks correctly, Cuminas nerver permits use of Feature.SecureDjVuDecode. For more information about Feature.SecureDjVuDecode, see Cuminas License System.

Expiry Control

Secure DjVu file may have expiry on either the document level or the user level. When opening a Secure DjVu file, the application is responsible to check the expiry. The following flagment checks the expiry:

Copy Code
// Checking expiry (flagment)
bool IsExpired(SecurityProvider secProv)
{
  if (secProv == null)
    return false; // no security

  if (secProv.CurrentUserPropertySet.IsPermitted(PrivsAndProps.Owner))
    return false; // owner can open even expired documents
  return secProv.IsExpired;
}
// Throwing exception if expired
void ThrowIfExpired(SecurityProvider secProv)
{
  if (IsExpired(secProv))
    throw new Exception(string.Format("The document is expired on {0}", secProv.Expiry));
}

Security Enforcement on GUI Applications

GUI application typically has buttons or menues to invoke certain actions such as export (save), copy or print. The applications should disable these parts according to security enforcement by DjVu#/DjVu SDK.

The following flagment illustrates typical usage of enabling buttons:

Copy Code
// Typical GUI control sample (flagment)
void EnforceSecurity(UserPropertySet user)
{
  bool fullCtrl = user.IsPermitted(PrivsAndProps.Owner);
  saveButton.Enabled = fullCtrl || user.IsPermitted(PrivsAndProps.Export);
  printButton.Enabled = fullCtrl || user.IsPermitted(PrivsAndProps.Print);
  copyTextsButton.Enabled = copyImageRegionButton.Enabled  = fullCtrl || user.IsPermitted(PrivsAndProps.Copy);
}

Re-encoding Secure DjVu

If the user, who opens the Secure DjVu file, has PrivsAndProps.Owner, the user can modify the security configuration for users. Because the Document.SecurityProvider Property returns unmodifiable SecurityProvider object, you should create a modifiable copy of it before editing the security configuration. The following code illustrates the flow to re-encode Secure DjVu:

reencsecdjvu.cs
Copy Code
using System;
using DjVu;
namespace ReEncodeSecureDjVu
{
  class ReEncodeSecureDjVu
  {
    static void Main(string[] args)
    {
      // TODO: ADD app's license script here or REMOVE the following line
      LicenseManager.LicenseScript = "......";
 
      using (Document doc = new Document(args[0]))
      {
        // authentication event handler
        doc.AuthenticateUser += (sender, e) => {
          Console.WriteLine("Authentication Event Handler Called!");
          e.UserId = "admin";
          e.Password = "admin-password";
        };
 
        // modify security configuration
        using (SecurityProvider secProv = doc.SecurityProvider.CreateEditableCopy())
        {
          // modify an existing user
          UserPropertySet user = secProv.UserPropertySets["mike"];
          // remove Owner privilege
          user.PrivsAndProps[PrivsAndProps.Owner] = false;
          // add Print privilege
          user.PrivsAndProps[PrivsAndProps.Print] = true;
         
          // add a user, who can only print the document
          user = secProv.UserPropertySets.AddUserPropertySet("user1");
          user.Password = "user1-password";
          user.PrivsAndProps[PrivsAndProps.Print] = true;
 
          // re-encode as Secure DjVu
          doc.SaveAs(args[1], secProv);
        }
      }
    }
  }
}
See Also
Send Feedback