home *** CD-ROM | disk | FTP | other *** search
/ jppd.dyndns.org / jppd.dyndns.org.tar / jppd.dyndns.org / QUERYPRO / Impressora_PDF / converter.exe / GPLGS / pdf_sec.ps < prev    next >
Text File  |  2004-01-30  |  10KB  |  374 lines

  1. %   Copyright (C) 1996-1998 Geoffrey Keating. 
  2. %    Copyright (C) 2001 Artifex Software, Inc.
  3. % This file may be freely distributed with or without modifications,
  4. % so long as modified versions are marked as such and copyright notices are
  5. % not removed.
  6.  
  7. % $Id: pdf_sec.ps,v 1.11.2.2 2004/01/29 12:08:47 igor Exp $
  8. % Implementation of security hooks for PDF reader.
  9.  
  10. % This file contains the procedures that have to take encryption into
  11. % account when reading a PDF file. It replaces the stub version of this
  12. % file that is shipped with GhostScript. It requires GhostScript 7.01
  13. % or later.
  14.  
  15. % Documentation for using this file is available at
  16. % http://www.ozemail.com.au/%7Egeoffk/pdfencrypt/
  17.  
  18. % Modified by Alex Cherepanov to work with GS 6.60 and higher.
  19. % New versions of GS require explicit checks for /true , /false, and /null
  20. % in .decpdfrun . This fix is backward-compatible.
  21.  
  22. % Modified by Raph Levien and Ralph Giles to use the new C
  23. % implementations of md5 and arcfour in ghostscript 7.01, and to
  24. % be compatible with PDF 1.4 128-bit encryption.
  25.  
  26. /.setlanguagelevel where { pop 2 .setlanguagelevel } if
  27. .currentglobal true .setglobal
  28. /pdfdict where { pop } { /pdfdict 100 dict def } ifelse
  29. pdfdict begin
  30.  
  31. % Older ghostscript versions do not have .pdftoken, so we use 'token' instead.
  32. /.pdftoken where { pop } { /.pdftoken /token load def } ifelse
  33.  
  34. % take a stream and arc4 decrypt it.
  35. % <stream> <key> arc4decodefilter <stream>
  36. /arc4decodefilter {
  37.   1 dict begin
  38.   /Key exch def
  39.   currentdict end /ArcfourDecode filter
  40. } bind def
  41.  
  42. % <ciphertext> <key> arc4decode <plaintext>
  43. /arc4decode {
  44.   %(key: ) print dup == (ct: ) print 1 index ==
  45.   1 index length 0 eq {
  46.     pop
  47.   } {
  48.     1 index length string 3 1 roll arc4decodefilter exch readstring pop
  49.   } ifelse
  50. } bind def
  51.  
  52. /md5 {
  53.   16 string dup /MD5Encode filter dup 4 3 roll writestring closefile
  54. } bind def
  55.  
  56. /md5_trunk {
  57.   md5 pdf_key_length 0 exch getinterval
  58. } bind def
  59.  
  60.  
  61. /pdf_padding_string
  62.    <28bf4e5e4e758a41 64004e56fffa0108
  63.     2e2e00b6d0683e80 2f0ca9fe6453697a>
  64. def
  65.  
  66. % Pad a key out to 32 bytes.
  67. /pdf_pad_key {        % <key> pdf_pad_key <padded key>
  68.   dup length 32 gt { 0 32 getinterval } if
  69.   pdf_padding_string
  70.   0 32 3 index length sub getinterval
  71.   concatstrings
  72. } bind def
  73.  
  74. /pdf_xorbytes {      % <iter-num> <key> pdf_xorbytes <xored-key>
  75.   dup length dup string
  76.   exch 1 sub 0 1 3 2 roll {
  77.     % <iter-num> <key> <new-key> <byte-num>
  78.     dup 3 index exch get 4 index xor
  79.     % <iter-num> <key> <new-key> <byte-num> <byte>
  80.     3 copy put pop pop
  81.   } for
  82.   3 1 roll pop pop
  83. } bind def
  84.  
  85. % Get length of encryption key in bytes
  86. /pdf_key_length {    % pdf_key_length <key_length>
  87.   Trailer /Encrypt oget /Length knownoget { -3 bitshift } { 5 } ifelse
  88. } bind def
  89.  
  90. % Algorithm 3.2
  91. /pdf_compute_encryption_key {  % <password> pdf_compute_encryption_key <key>
  92.   % Step 1.
  93.   pdf_pad_key
  94.  
  95.   % Step 2, 3.
  96.   Trailer /Encrypt oget dup /O oget
  97.   % <padded-key> <encrypt> <O>
  98.  
  99.   % Step 4.
  100.   exch /P oget 4 string exch
  101.   2 copy 255 and 0 exch put
  102.   2 copy -8 bitshift 255 and 1 exch put
  103.   2 copy -16 bitshift 255 and 2 exch put
  104.   2 copy -24 bitshift 255 and 3 exch put pop
  105.   % <padded-key> <O> <P>
  106.  
  107.   % Step 5.
  108.   Trailer /ID knownoget { 0 oget } {
  109.     ()
  110.     (   **** ID key in the trailer is required for encrypted files.\n) pdfformaterror
  111.   } ifelse
  112.   3 { concatstrings } repeat md5_trunk
  113.  
  114.   % Step 6.
  115.   Trailer /Encrypt oget /R oget 3 eq {
  116.      50 { md5_trunk } repeat
  117.   } if
  118.  
  119.   % Step 7 - Done in md5_trunk.
  120. } bind def
  121.  
  122. % Algorithm 3.4
  123. /pdf_gen_user_password_R2 { % <filekey> pdf_gen_user_password_R2 <U>
  124.  
  125.   % Step 2.
  126.   pdf_padding_string exch arc4decode
  127. } bind def
  128.  
  129. % Algorithm 3.5
  130. /pdf_gen_user_password_R3 { % <filekey> pdf_gen_user_password_R3 <U>
  131.  
  132.   % Step 2.
  133.   pdf_padding_string
  134.  
  135.   % Step 3.
  136.   Trailer /ID knownoget { 0 oget } {
  137.     ()
  138.     (   **** ID key in the trailer is required for encrypted files.\n) pdfformaterror
  139.   } ifelse
  140.   concatstrings md5
  141.  
  142.   % Step 4.
  143.   1 index arc4decode
  144.  
  145.   % Step 5.
  146.   1 1 19 {
  147.     2 index pdf_xorbytes arc4decode
  148.   } for
  149.   exch pop
  150.  
  151. } bind def
  152.  
  153. /pdf_gen_user_password { % <password> pdf_gen_user_password <filekey> <U>
  154.   % common Step 1 of Algorithms 3.4 and 3.5.
  155.   pdf_compute_encryption_key dup
  156.  
  157.   Trailer /Encrypt oget
  158.  
  159.   /R oget dup 2 eq {
  160.     pop pdf_gen_user_password_R2
  161.   } {
  162.     dup 3 eq {
  163.       pop pdf_gen_user_password_R3
  164.     } {
  165.       (   **** This file uses an unknown standard security handler revision: )
  166.       exch =string cvs concatstrings pdfformaterror printProducer
  167.       /pdf_check_user_password cvx /undefined signalerror
  168.     } ifelse
  169.   } ifelse
  170. } bind def
  171.  
  172. % Algorithm 3.6
  173. /pdf_check_user_password { % <password> pdf_check_user_password <filekey> true
  174.                            % <password> pdf_check_user_password false
  175.   pdf_gen_user_password
  176.  
  177.   Trailer /Encrypt oget /U oget
  178.  
  179.   0 2 index length getinterval eq {
  180.     true
  181.   } {
  182.     pop false
  183.   } ifelse
  184. } bind def
  185.  
  186. % Compute an owner key, ie the result of step 4 of Algorithm 3.3
  187. /pdf_owner_key % <password> pdf_owner_key <owner-key>
  188. {
  189.   % Step 1.
  190.   pdf_pad_key
  191.  
  192.   % Step 2.
  193.   md5_trunk
  194.  
  195.   % 3.3 Step 3.
  196.   Trailer /Encrypt oget /R oget 3 eq {
  197.     50 { md5_trunk } repeat
  198.   } if
  199.  
  200.   % Step 4 - Done in md5_trunk.
  201. } bind def
  202.  
  203. % Algorithm 3.7
  204. /pdf_check_owner_password { % <password> pdf_check_owner_password <filekey> true
  205.                             % <password> pdf_check_owner_password false
  206.   % Step 1.
  207.   pdf_owner_key
  208.  
  209.   % Step 2.
  210.   Trailer /Encrypt oget dup /O oget 2 index arc4decode
  211.   % <encryption-key> <encrypt-dict> <decrypted-O>
  212.  
  213.   % Step 3.
  214.   exch /R oget 3 eq {
  215.     1 1 19 {
  216.       2 index pdf_xorbytes arc4decode
  217.     } for
  218.   } if
  219.   exch pop
  220.   % <result-of-step-3>
  221.  
  222.   pdf_check_user_password
  223. } bind def
  224.  
  225. % Process the encryption information in the Trailer.
  226. /pdf_process_Encrypt {
  227.   Trailer /Encrypt oget
  228.   /Filter oget /Standard eq not {
  229.     (   **** This file uses an unknown security handler.\n) pdfformaterror
  230.     printProducer
  231.     /pdf_process_Encrypt cvx /undefined signalerror
  232.   } if
  233.   () pdf_check_user_password
  234.   {
  235.     /FileKey exch def
  236.   } {
  237.     /PDFPassword where {
  238.        pop PDFPassword pdf_check_user_password
  239.        {
  240.          /FileKey exch def
  241.        } {
  242.          PDFPassword pdf_check_owner_password
  243.          {
  244.            /FileKey exch def
  245.          } {
  246.            (   **** Password did not work.\n) pdfformaterror
  247.        printProducer
  248.        /pdf_process_Encrypt cvx /invalidfileaccess signalerror
  249.          } ifelse
  250.        } ifelse
  251.     } {
  252.       (   **** This file requires a password for access.\n) pdfformaterror
  253.       printProducer
  254.       /pdf_process_Encrypt cvx /invalidfileaccess signalerror
  255.     } ifelse
  256.   } ifelse
  257.  
  258. %   Trailer /Encrypt oget /P oget 4 and 0 eq #? and
  259. %    { (   ****This owner of this file has requested you do not print it.\n)
  260. %      pdfformaterror printProducer
  261. %      /pdf_process_Encrypt cvx /invalidfileaccess signalerror
  262. %    }
  263. %   if
  264. } bind def
  265.  
  266. % Calculate the key used to decrypt an object (to pass to .decpdfrun or
  267. % put into a stream dictionary).
  268. /computeobjkey    % <object#> <generation#> computeobjkey <keystring>
  269. {
  270.   exch
  271.   FileKey length 5 add string
  272.   dup 0 FileKey putinterval
  273.   exch
  274.         % stack:  gen# string obj#
  275.     2 copy 255 and FileKey length exch put
  276.     2 copy -8 bitshift 255 and FileKey length 1 add exch put
  277.     2 copy -16 bitshift 255 and FileKey length 2 add exch put
  278.   pop exch
  279.     2 copy 255 and FileKey length 3 add exch put
  280.     2 copy -8 bitshift 255 and FileKey length 4 add exch put
  281.   pop md5 0 FileKey length 5 add 2 index length .min getinterval
  282. } bind def
  283.  
  284. % As .pdfrun, but decrypt strings with key <key>.
  285. /.decpdfrun            % <file> <keystring> <opdict> .decpdfrun -
  286.  {    % Construct a procedure with the file, opdict and key bound into it.
  287.    2 index cvlit mark mark 5 2 roll
  288.     { .pdftoken not { (%%EOF) cvn cvx } if
  289.       dup xcheck
  290.        { PDFDEBUG { dup == flush } if
  291.      3 -1 roll pop
  292.      2 copy .knownget
  293.       { exch pop exch pop exec
  294.           }
  295.       { exch pop
  296.             dup /true eq
  297.               { pop //true
  298.               }
  299.               { dup /false eq
  300.                   { pop //false 
  301.                   }
  302.                   { dup /null eq
  303.                       { pop //null
  304.                       }
  305.                       { (   **** Unknown operator: ) 
  306.                     exch =string cvs concatstrings (\n) concatstrings
  307.             pdfformaterror
  308.                       }
  309.                     ifelse
  310.                   }
  311.                 ifelse
  312.               }
  313.             ifelse
  314.       }
  315.      ifelse
  316.        }
  317.        { exch pop PDFDEBUG { dup ==only ( ) print flush } if
  318.      dup type /stringtype eq
  319.       { 1 index arc4decode
  320.         PDFDEBUG { (%Decrypted: ) print dup == flush } if
  321.       }
  322.      if
  323.      exch pop
  324.        }
  325.       ifelse
  326.     }
  327.    aload pop .packtomark cvx
  328.    /loop cvx 2 packedarray cvx
  329.     { stopped /PDFsource } aload pop
  330.    PDFsource
  331.     { store { stop } if } aload pop .packtomark cvx 
  332.    /PDFsource 3 -1 roll store exec
  333.  } bind def
  334.  
  335. % Run the code to resolve an object reference.
  336. /pdf_run_resolve
  337.  { /FileKey where
  338.     { pop
  339.       2 copy computeobjkey dup 4 1 roll
  340.       PDFfile exch resolveopdict .decpdfrun
  341.       dup dup dup 5 2 roll
  342.     % stack: object object key object object
  343.       xcheck exch type /dicttype eq and
  344.        { /StreamKey exch put }
  345.        { pop pop }
  346.       ifelse
  347.     }
  348.     { PDFfile resolveopdict .pdfrun }
  349.    ifelse
  350.  } bind def
  351.  
  352. % Prefix a decryption filter to a stream if needed.
  353. % Stack: readdata? dict parms file/string filternames
  354. % (both before and after).
  355. /pdf_decrypt_stream
  356.  { 3 index /StreamKey known
  357.    {
  358.       exch 
  359.     % Stack: readdata? dict parms filternames file/string
  360.       3 index /Length oget
  361.       dup 0 eq {
  362.     % Handle Length=0 case specially to avoid SubFileDecode semantics
  363.         pop pop ()
  364.       } {
  365.         () /SubFileDecode filter
  366.       } ifelse
  367.       3 index /StreamKey get arc4decodefilter
  368.       exch
  369.    } if
  370.  } bind def
  371.  
  372. end            % pdfdict
  373. .setglobal
  374.