--- pdf_base.ps.orig Thu May 9 12:59:54 1996 +++ pdf_base.ps Thu May 9 13:02:29 1996 @@ -168,6 +168,23 @@ ifelse } bind def +% PDF decryption stuff +/computeobjkey % computeobjkey +{ + exch + 10 string + dup 0 FileKey putinterval + exch + % stack: gen# string obj# + 2 copy 255 and 5 exch put + 2 copy -8 bitshift 255 and 6 exch put + 2 copy -16 bitshift 255 and 7 exch put + pop exch + 2 copy 255 and 8 exch put + 2 copy -8 bitshift 255 and 9 exch put + pop md5 0 10 getinterval +} bind def + % If we encounter an object definition while reading sequentially, % we just store it away and keep going. /objopdict mark @@ -198,7 +215,8 @@ /resolveR % resolveR { DEBUG { (Resolving: ) print 2 copy 2 array astore == } if 1 index unresolved? - { PDFfile fileposition 3 1 roll + { 2 copy + PDFfile fileposition 3 1 roll 1 index readxrefentry 3 1 roll checkgeneration % Stack: savepos objpos obj# @@ -213,6 +231,20 @@ if PDFfile resolveopdict pdfrun exch PDFfile exch setfileposition + % stack: obj# gen# object + /FileKey where + { + pop + 3 1 roll computeobjkey + exch dup dup dup 5 2 roll + % stack: object object key object object + xcheck exch type /dicttype eq and + { 2 copy /StreamKey exch put } if + % should probably decrypt dictionaries here. + pop pop + } + { exch pop exch pop } + ifelse } { pop Objects exch get } @@ -226,6 +258,7 @@ % /File - the file or string where the stream contents are stored; % /FilePosition - iff File is a file, the position in the file % where the contents start. +% /StreamKey - the key used to decrypt this stream if any % We do the real work of constructing the data stream only when the % contents are needed. @@ -291,6 +324,14 @@ % Stack: readdata? dict parms filternames 2 index /File get exch % Stack: readdata? dict parms file/string filternames + 3 index /StreamKey known + { + exch + % Stack: readdata? dict parms filternames file/string + 3 index /Length oget () /SubFileDecode filter + 3 index /StreamKey get rc4decodefilter + exch + } if dup length 0 eq { % All the PDF filters have EOD markers, but in this case % there is no specified filter. --- pdf_main.ps.orig Thu May 9 12:59:54 1996 +++ pdf_main.ps Thu May 9 13:01:17 1996 @@ -113,6 +113,57 @@ end % userdict pdfdict begin +% MD5 and RC4 stuff + +% Alleged-RC4 +% rc4setkey +% rc4 +% where 'rc4key' and 'string' are the same object, modified. +% (change the names to taste). +/rc4/rc4setkey <~H\_lh23JD%CQ^lE1G<0k! cvx exec + +% take a stream and rc4 decrypt it. +% rc4decodefilter +/rc4decodefilter { + rc4setkey exch 512 string + % stack: + { readstring pop rc4 exch pop } aload pop + 8 array astore cvx 0 () /SubFileDecode filter +} bind def + +% MD5 derived from RFC 1321, "The MD5 Message-Digest Algorithm", +% R. Rivest, MIT, RSADSI. + +% We construct the MD5 transform by a sort of inline expansion. +% this takes up quite a bit of memory (around 17k), but gives a +% factor-of-two speed increase. This also allows us to make use of +% interpreters with 64-bit wide integers. +% md5 +<~L_,_,Ops'6>C0j&A+CgPMA<@")OhlHm@N]0C_.8\EI=#LeE+4rMA!+TU?'6us= +,6m5+-I.j!0U0A1G;$:=-3M:D.GM4A7Uj'Ou"b5+BO:%d"Va$P#[YOOu"aYL]ESoL]E53Ld-5>Bp(Z +C1G57&H`dO#6bM?&I0'W#71eG&IT?_#7V(O&J#WX"U58@%KI1H"UYPH%KmIP"V(h@%L +%fmCN"qM%F +%h06V"q(b>%g`tbP"Uro04?MC04QYGL]hFJ"-NeMLKcEB04QYE04A.5P!5$bI?I0D+@B@A+@[JfM#< +DHP"Us&@3@ihGT_$_plZ/M90ngC!'o.NUj2+D[oOasE8/4BcL1@Q&$JKY`[[o@7MG_iPlYTLR+RHs#if=l$^&L.1@EKd8F6]OaF#U/m_-"=YTZTojD>#FOma/[]D&7#?*'Nc/uo +&#M/Ot%>RAU'^_m[klq"RU\JJ?!niP_9T&lH3C8L@p47(O@3Y[33"2Usl9n;%c`-WM945KK]Po9gI` +CZH-i2?]0SKXc* +OuP+2P!5$bP,4GL&h7:"Hn +"N+Dci?bMY@N]/'A6jP<"+-1jM"m,DI? +K52P"Ar8!/LZ3%ss*7Or9EBL]`G6P)#2nL&h7:"Hn"mFa]EDP')pJI?G)'1B~> cvx exec + + % ======================== File parsing ======================== % % Read the cross-reference and trailer sections. @@ -164,7 +215,7 @@ % Open a PDF file and read the trailer and cross-reference. /pdfopen % pdfopen - { 10 dict begin + { 11 dict begin cvlit /PDFfile exch def /PDFsource PDFfile def PDFfile dup dup 0 setfileposition bytesavailable setfileposition @@ -191,6 +242,21 @@ % Create and initialize some caches. /PageCount pdfpagecount def /PageNumbers PageCount dict def + % sort out encryption stuff + Trailer /Encrypt knownoget + { <28bf4e5e4e758a41 64004e56fffa0108 + 2e2e00b6d0683e80 2f0ca9fe6453697a> exch + dup /O oget exch + /P oget 4 string exch + 2 copy 255 and 0 exch put + 2 copy -8 bitshift 255 and 1 exch put + 2 copy -16 bitshift 255 and 2 exch put + 2 copy -24 bitshift 255 and 3 exch put pop + Trailer /ID oget 0 oget + 3 { concatstrings } repeat + md5 0 5 getinterval + /FileKey exch def + } if % Write the DSC header if appropriate. [ (%!PS-Adobe-1.0) #dsc [ (%%Pages: ) pdfpagecount #dsc