Using OraPDFProtect

This tutorial contains examples that demonstrate the usage of DidiSoft OraPDFProtect (ORA_PDF_PROTECT) PL/SQL package. For some of the functions of the package you will need a X.509 certificate or a .pkcs12/.pfx (Personal Information Exchange) file with a private key and a certificate chain.

Table of contents

PDF usage restrictions and Owner Password

The PDF encryption capabilities provided by ORA_PDF_PROTECT are similar to those available in Oracle® Report Builder. When encrypting a PDF document, certain usage limitations can be specified. The usage rights limitations are defined as constants (using the same names as those in Report Builder):

ORA_PDF_PROTECT.ALL_PERMISSIONS All permissions are granted
ORA_PDF_PROTECT.NOCOPY Prohibits copying or extracting content from the document
ORA_PDF_PROTECT.NOASSEMBLY Prohibits insert or delete pages
ORA_PDF_PROTECT.NOFILLIN Prohibits filling form fields or signature fields
ORA_PDF_PROTECT.NOSCREENREADERS Prohibits extracting text and graphics for accessibility support
ORA_PDF_PROTECT.NOMODIFYANNOTATIONS Prohibits adding or modifying text annotations and fill form fields
ORA_PDF_PROTECT.NOMODIFYCONTENTS Prohibits modifying the contents of the document
ORA_PDF_PROTECT.NOPRINTING Prohibits printing the PDF
ORA_PDF_PROTECT.NOHIRESPRINTING Allow printing only at a low resolution

The usage rights are accompanied with an Owner Password – a special password that can be used later to modify the PDF usage restrictions.

Encrypt PDF with a password

A password protected PDF file uses a User Password (not to be mistaken with the Owner Password), and only those who know it can open the PDF document. The example below will demonstrate the overloaded versions of the ENCRYPT_PDF method where usage rights can also be specified for the output PDF file.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
DECLARE 
  -- input PDF BLOB read handle
  pdf_file_handle BFILE;
  -- input PDF BLOB
  pdf_blob BLOB;  
  -- output encrypted PDF BLOB
  encrypted_pdf_blob BLOB;
 
  -- PDF permissions and password
  user_password VARCHAR2(200);
  owner_password VARCHAR2(200);
  pdf_permissions INTEGER;  
BEGIN
    DBMS_LOB.createtemporary(pdf_blob, TRUE);
    pdf_file_handle := BFILENAME('SSH_KEYS_DIR', '1.pdf'); -- directory name must be Upper case
 
    -- load the data into a BLOB
    DBMS_LOB.OPEN(pdf_file_handle, DBMS_LOB.LOB_READONLY);
    DBMS_LOB.LoadFromFile( pdf_blob, pdf_file_handle, DBMS_LOB.GETLENGTH(pdf_file_handle) );
    DBMS_LOB.CLOSE(pdf_file_handle);
 
    user_password := 'test123';
    owner_password := 'my password';
    pdf_permissions := ORA_PDF_PROTECT.NOCOPY + 
                              ORA_PDF_PROTECT.NOASSEMBLY +
                              ORA_PDF_PROTECT.NOMODIFYCONTENTS;
 
    encrypted_pdf_blob := ORA_PDF_PROTECT.ENCRYPT_PDF(pdf_blob, user_password, owner_password, pdf_permissions);
END;
/

Encrypt PDF with a X.509 certificate

Encrypting a PDF with a X.509 certificate is similar to encrypting with a password, but instead of a User Password a X.509 certificate is used. In order to open such encrypted PDF, the private key corresponding to the X.509 certificate will be needed.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
DECLARE 
  -- file read handle
  file_handle BFILE;
  -- input PDF BLOB
  pdf_blob BLOB;  
  -- output encrypted PDF BLOB
  encrypted_pdf_blob BLOB;
 
  -- X.509 certificate
  cert_blob BLOB;    
BEGIN
    pdf_blob := ... load PDF INTO a BLOB
 
    -- load X.509 certificate into a BLOB
    file_handle := BFILENAME('KEYS_DIR', 'DidiSoftEood.crt');    
    DBMS_LOB.createtemporary(cert_blob, TRUE);
    DBMS_LOB.OPEN(file_handle, DBMS_LOB.LOB_READONLY);
    DBMS_LOB.LoadFromFile( cert_blob, file_handle, DBMS_LOB.GETLENGTH(file_handle) );
    DBMS_LOB.CLOSE(file_handle);
 
    encrypted_pdf_blob := ORA_PDF_PROTECT.ENCRYPT_PDF(pdf_blob, cert_blob);
END;
/

Sign PDF

A digital signature can be embedded inside a PDF file in order to prove who is the author of the document. Usually a digital signature is an encrypted message digest that is meaningful only for a computer program. The PDF document specification also supports digital signatures that have a visible signature appearance.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
DECLARE 
  -- file read handle
  file_handle BFILE;
  -- input PDF BLOB
  pdf_blob BLOB;  
  -- output signed PDF BLOB
  signed_pdf_blob BLOB;
  -- PFX/p12 private key and chain storage
  pfx_blob BLOB;  
  pfx_password VARCHAR2(200);   
BEGIN
    pdf_blob := ... load PDF INTO BLOB
 
    -- load .PFX (key storage) into a BLOB
    file_handle := BFILENAME('KEYS_DIR', 'didisoft.pkcs12.p12');    
    DBMS_LOB.createtemporary(pfx_blob, TRUE);
    DBMS_LOB.OPEN(file_handle, DBMS_LOB.LOB_READONLY);
    DBMS_LOB.LoadFromFile( pfx_blob, file_handle, DBMS_LOB.GETLENGTH(file_handle) );
    DBMS_LOB.CLOSE(file_handle);
 
    pfx_password := 'cobra34';
 
    signed_pdf_blob := ORA_PDF_PROTECT.SIGN_PDF(pdf_blob, pfx_blob, pfx_password);
END;
/

Sign PDF with a visible signature

A visual digital signature is a combination of a digital signature and visual appearance in the PDF document.

The appearance of a Visual signature in a PDF document is specified with a parameter of type ORA_PDF_VISUAL_SIGNATURE

ORA_PDF_VISUAL_SIGNATURE

1
2
3
4
5
6
7
8
9
10
ORA_PDF_VISUAL_SIGNATURE  AS object (
  Signature_Text   VARCHAR2(200), -- signature text
  Rectangle_X1 INTEGER, -- signature rectangle lower left corner X coordinate
  Rectangle_Y1 INTEGER, -- signature rectangle lower left corner Y coordinate
  Rectangle_X2 INTEGER, -- signature rectangle upper right corner X coordinate
  Rectangle_Y2 INTEGER, -- signature rectangle upper right corner Y coordinate
  Page_No INTEGER, -- page where the visible signature will appear
  BG_Image BLOB, -- optional background image loaded from GIF, PNG, JPG
  Text_Color VARCHAR(20) -- optional, default is 'black'
);

An instance of ORA_PDF_VISUAL_SIGNATURE with default values can be initialized with:

1
visual_options := ORA_PDF_PROTECT.EMPTY_VISUAL_SIGNATURE;

Signature text (property Signature_Text)
The text displayed in the visual signature is specified with the Signature_Text property. Special variables can be used in this text :
${signer} – the name of the certificate owner extracted from the .pfx file used for signing.
${timestamp} – this will be substituted with the date and time of the operation
New line can be added to the signature text with the CHR(13) character.

visual_options.Signature_Text := 'Signed by ${signer}';

Signature rectangle (properties Rectangle_X1, Rectangle_Y1, Rectangle_X2, Rectangle_Y2)
The signature rectangle is the box containing the visual signature. A PDF page uses a coordinate system starting in the bottom left corner (point [1,1]) and ending at the upper right cornet point (X=612, Y=792). The image below illustrates how to place a 200 points wide and 100 points tall signature rectangle in three different positions – lower left angle, center of a page, upper right angle:

Signature page (property Page_No):

The signature page is specified with the Page_No property. If the specified page number is bigger than the number of pages in the PDF document, it will be set for the last page.

A special value is available ORA_PDF_PROTECT.SIGNATURE_ON_ALL_PAGES which if used for Page_No will make the visible signature appear on all pages of the PDF document!

visual_options.Page_No := 1;
visual_options.Page_No :=ORA_PDF_PROTECT.SIGNATURE_ON_ALL_PAGES

Background image (property Background_Image)

The background image can be loaded from a GIF, PNG or JPG image. If specified the image will be scaled to fill the signature rectangle.

Text color (property Text_Color)

The default text color in the visible signature rectangle is black. Often when a background image is specified, the text color shall also be changed in order to be more readable. A set of predefined text colors are available: black, blue, cyan, darkgray, gray, green, yellow, lightgray, magenta, orange, pink, red, white.

The color can also be specified as RGB color value like ‘#336699’ or ‘336699’

visual_options.Text_Color := 'yellow';
visual_options.Text_Color := '#336699';

Example with a visible signature

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
DECLARE 
  -- file read handle
  file_handle BFILE;
  -- input PDF BLOB
  pdf_blob BLOB;  
  -- output signed PDF BLOB
  signed_pdf_blob BLOB;
  -- PFX/p12 private key and chain storage
  pfx_blob BLOB;  
  pfx_password VARCHAR2(200); 
 
  -- visual signature appearance
  options ORA_PDF_VISUAL_SIGNATURE;  
BEGIN
    -- load PDF into a BLOB
    pdf_blob := ... load PDF INTO BLOB field
 
    -- load .PFX (key storage) into a BLOB
    file_handle := BFILENAME('KEYS_DIR', 'didisoft.pkcs12.p12');    
    DBMS_LOB.createtemporary(pfx_blob, TRUE);
    DBMS_LOB.OPEN(file_handle, DBMS_LOB.LOB_READONLY);
    DBMS_LOB.LoadFromFile( pfx_blob, file_handle, DBMS_LOB.GETLENGTH(file_handle) );
    DBMS_LOB.CLOSE(file_handle);
    pfx_password := 'cobra34';
 
    -- Visual signature options
    options := ORA_PDF_PROTECT.EMPTY_VISUAL_SIGNATURE;
    options.Signature_Text := 'Digitally signed by ${signer}' || CHR(13) || 'Date: ${timestamp}';
    options.Rectangle_X1 := 1;
    options.Rectangle_Y1 := 1;
    options.Rectangle_X2 := 150;
    options.Rectangle_Y2 := 100;
    options.Page_No := ORA_PDF_PROTECT.SIGNATURE_ON_ALL_PAGES;
    -- options.Background_Image :=  ... BLOB loaded from GIF,JPG or PNG image
    options.Text_Color := 'blue';
    signed_pdf_blob := ORA_PDF_PROTECT.SIGN_PDF_VISUAL(pdf_blob, pfx_blob, pfx_password, options);
END;
/

Sign and encrypt PDF

The SIGN_AND_ENCRYPT_PDF method of the ORA_PDF_PROTECT package combines the encrypting and signing process in one step. The set of parameters is the same as in those operations:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
DECLARE 
  -- file read handle
  file_handle BFILE;
  -- input PDF BLOB
  pdf_blob BLOB;  
  -- output signed PDF BLOB
  signed_pdf_blob BLOB;
  -- PFX/p12 private key and chain storage
  pfx_blob BLOB;  
  pfx_password VARCHAR2(200); 
 
  -- PDF permissions and password
  user_password VARCHAR2(200);
  owner_password VARCHAR2(200);
  pdf_permissions INTEGER;  
BEGIN
    DBMS_Java.set_output(10000);  
 
    pdf_blob := ...-- load PDF into a BLOB
 
    -- load .PFX (key storage) into a BLOB
    file_handle := BFILENAME('KEYS_DIR', 'didisoft.pkcs12.p12');    
    DBMS_LOB.createtemporary(pfx_blob, TRUE);
    DBMS_LOB.OPEN(file_handle, DBMS_LOB.LOB_READONLY);
    DBMS_LOB.LoadFromFile( pfx_blob, file_handle, DBMS_LOB.GETLENGTH(file_handle) );
    DBMS_LOB.CLOSE(file_handle);
    pfx_password := 'cobra34';
 
    user_password := 'test123';
    owner_password := 'my password';
    -- Restrict all permissions
    pdf_permissions := ORA_PDF_PROTECT.NOCOPY + 
                              ORA_PDF_PROTECT.NOASSEMBLY +
                              ORA_PDF_PROTECT.NOFILLIN +
                              ORA_PDF_PROTECT.NOSCREENREADERS +
                              ORA_PDF_PROTECT.NOMODIFYANNOTATIONS +
                              ORA_PDF_PROTECT.NOMODIFYCONTENTS +
                              ORA_PDF_PROTECT.NOPRINTING;
 
    signed_pdf_blob := ORA_PDF_PROTECT.SIGN_AND_ENCRYPT_PDF(pdf_blob, pfx_blob, pfx_password, user_password, owner_password, pdf_permissions);
END;
/

Sign and encrypt PDF with a visible signature

The ORA_PDF_PROTECT.SIGN_AND_ENCRYPT_PDF_VISUAL method also combines the visual signing and encrypting in a single step. The appearance of the Visual signature is customized through the ORA_PDF_VISUAL_SIGNATURE object.

Sign and encrypt PDF

The SIGN_AND_ENCRYPT_PDF method of the ORA_PDF_PROTECT package combines the encrypting and signing process in a single step. The set of parameters is the same as in those operations:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
DECLARE 
  -- file read handle
  file_handle BFILE;
  -- input PDF BLOB
  pdf_blob BLOB;  
  -- output signed PDF BLOB
  signed_pdf_blob BLOB;
  -- PFX/p12 private key and chain storage
  pfx_blob BLOB;  
  pfx_password VARCHAR2(200); 
 
  -- visual signature appearance
  options ORA_PDF_VISUAL_SIGNATURE;
 
  -- PDF permissions and password
  user_password VARCHAR2(200);
  owner_password VARCHAR2(200);
  pdf_permissions INTEGER;  
BEGIN
    pdf_blob := ... -- load PDF into a BLOB
 
    -- load .PFX (key storage) into a BLOB
    file_handle := BFILENAME('KEYS_DIR', 'didisoft.pkcs12.p12');    
    DBMS_LOB.createtemporary(pfx_blob, TRUE);
    DBMS_LOB.OPEN(file_handle, DBMS_LOB.LOB_READONLY);
    DBMS_LOB.LoadFromFile( pfx_blob, file_handle, DBMS_LOB.GETLENGTH(file_handle) );
    DBMS_LOB.CLOSE(file_handle);
    pfx_password := 'cobra34';
 
    -- Visual signature options
    options := ORA_PDF_PROTECT.EMPTY_VISUAL_SIGNATURE;
    options.Signature_Text := 'Digitally signed by ${signer}' || CHR(13) || 'Date: ${timestamp}';
    options.Rectangle_X1 := 1;
    options.Rectangle_Y1 := 1;
    options.Rectangle_X2 := 150;
    options.Rectangle_Y2 := 100;
    options.Page_No := ORA_PDF_PROTECT.SIGNATURE_ON_ALL_PAGES;
	  -- options.Background_Image :=  ... BLOB loaded with GIF,JPG or PNG image
 
    user_password := 'test123';
    owner_password := 'my password';
    -- Restrict all permissions
    pdf_permissions := ORA_PDF_PROTECT.NOCOPY + 
                              ORA_PDF_PROTECT.NOASSEMBLY +
                              ORA_PDF_PROTECT.NOFILLIN +
                              ORA_PDF_PROTECT.NOSCREENREADERS +
                              ORA_PDF_PROTECT.NOMODIFYANNOTATIONS +
                              ORA_PDF_PROTECT.NOMODIFYCONTENTS +
                              ORA_PDF_PROTECT.NOPRINTING;
 
    signed_pdf_blob := ORA_PDF_PROTECT.SIGN_AND_ENCRYPT_PDF_VISUAL(pdf_blob, pfx_blob, pfx_password, options, 
                                                                   user_password, owner_password, pdf_permissions);

Summary

This article is a starting point for using DidiSoft OraPDFProtect. Complete PL/SQL examples can be found in the \Examples folder that ships inside the product ZIP file.