Protection PDF File


This script allows to protect the PDF, that is to say prevent people from copying its content, print it or modify it.

Author: Klemen Vodopivec
License: Freeware

SetProtection([array permissions [, string user_pass [, string owner_pass]]])

permissions: the set of permissions. Empty by default (only viewing is allowed).
user_pass: user password. Empty by default.
owner_pass: owner password. If not specified, a random value is used.

The permission array is composed of values taken from the following ones:

* copy: copy text and images to the clipboard
* print: print the document
* modify: modify it (except for annotations and forms)
* annot-forms: add annotations and forms

Remark: the protection against modification is for people who have the full Acrobat product.

If you don’t set any password, the document will open as usual. If you set a user password, the PDF viewer will ask for it before displaying the document. The master password, if different from the user one, can be used to get full access.

Note: protecting a document requires to encrypt it, which increases the processing time a lot. This can cause a PHP time-out in some cases, especially if the document contains images or fonts.
Source

encrypted=false;
$this->last_rc4_key='';
$this->padding="\x28\xBF\x4E\x5E\x4E\x75\x8A\x41\x64\x00\x4E\x56\xFF\xFA\x01\x08".
"\x2E\x2E\x00\xB6\xD0\x68\x3E\x80\x2F\x0C\xA9\xFE\x64\x53\x69\x7A";
}

/**
* Function to set permissions as well as user and owner passwords
*
* - permissions is an array with values taken from the following list:
* copy, print, modify, annot-forms
* If a value is present it means that the permission is granted
* - If a user password is set, user will be prompted before document is opened
* - If an owner password is set, document can be opened in privilege mode with no
* restriction if that password is entered
*/
function SetProtection($permissions=array(),$user_pass='',$owner_pass=null)
{
$options = array('print' => 4, 'modify' => 8, 'copy' => 16, 'annot-forms' => 32 );
$protection = 192;
foreach($permissions as $permission){
if (!isset($options[$permission]))
$this->Error('Incorrect permission: '.$permission);
$protection += $options[$permission];
}
if ($owner_pass === null)
$owner_pass = uniqid(rand());
$this->encrypted = true;
$this->_generateencryptionkey($user_pass, $owner_pass, $protection);
}

/****************************************************************************
* *
* Private methods *
* *
****************************************************************************/

function _putstream($s)
{
if ($this->encrypted) {
$s = $this->_RC4($this->_objectkey($this->n), $s);
}
parent::_putstream($s);
}

function _textstring($s)
{
if ($this->encrypted) {
$s = $this->_RC4($this->_objectkey($this->n), $s);
}
return parent::_textstring($s);
}

/**
* Compute key depending on object number where the encrypted data is stored
*/
function _objectkey($n)
{
return substr($this->_md5_16($this->encryption_key.pack('VXxx',$n)),0,10);
}

/**
* Escape special characters
*/
function _escape($s)
{
$s=str_replace('\\','\\\\',$s);
$s=str_replace(')','\\)',$s);
$s=str_replace('(','\\(',$s);
$s=str_replace("\r",'\\r',$s);
return $s;
}

function _putresources()
{
parent::_putresources();
if ($this->encrypted) {
$this->_newobj();
$this->enc_obj_id = $this->n;
$this->_out('<_putencryption();
$this->_out('>>');
$this->_out('endobj');
}
}

function _putencryption()
{
$this->_out('/Filter /Standard');
$this->_out('/V 1');
$this->_out('/R 2');
$this->_out('/O ('.$this->_escape($this->Ovalue).')');
$this->_out('/U ('.$this->_escape($this->Uvalue).')');
$this->_out('/P '.$this->Pvalue);
}

function _puttrailer()
{
parent::_puttrailer();
if ($this->encrypted) {
$this->_out('/Encrypt '.$this->enc_obj_id.' 0 R');
$this->_out('/ID [()()]');
}
}

/**
* RC4 is the standard encryption algorithm used in PDF format
*/
function _RC4($key, $text)
{
if ($this->last_rc4_key != $key) {
$k = str_repeat($key, 256/strlen($key)+1);
$rc4 = range(0,255);
$j = 0;
for ($i=0; $ilast_rc4_key = $key;
$this->last_rc4_key_c = $rc4;
} else {
$rc4 = $this->last_rc4_key_c;
}

$len = strlen($text);
$a = 0;
$b = 0;
$out = '';
for ($i=0; $i_md5_16($owner_pass);
$owner_RC4_key = substr($tmp,0,5);
return $this->_RC4($owner_RC4_key, $user_pass);
}

/**
* Compute U value
*/
function _Uvalue()
{
return $this->_RC4($this->encryption_key, $this->padding);
}

/**
* Compute encryption key
*/
function _generateencryptionkey($user_pass, $owner_pass, $protection)
{
// Pad passwords
$user_pass = substr($user_pass.$this->padding,0,32);
$owner_pass = substr($owner_pass.$this->padding,0,32);
// Compute O value
$this->Ovalue = $this->_Ovalue($user_pass,$owner_pass);
// Compute encyption key
$tmp = $this->_md5_16($user_pass.$this->Ovalue.chr($protection)."\xFF\xFF\xFF");
$this->encryption_key = substr($tmp,0,5);
// Compute U value
$this->Uvalue = $this->_Uvalue();
// Compute P value
$this->Pvalue = -(($protection^255)+1);
}
}

?>

Example
This example shows how to allow only printing.

SetProtection(array('print'));
$pdf->Open();
$pdf->AddPage();
$pdf->SetFont('Arial');
$pdf->Write(10,'You can print me but not copy my text.');
$pdf->Output();
?>

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s