gettalong / hexapdf

Versatile PDF creation and manipulation for Ruby
https://hexapdf.gettalong.org
Other
1.21k stars 69 forks source link

Opening and saving a pdf causing it to be password protected #213

Closed andi-dev closed 1 year ago

andi-dev commented 1 year ago

Hi again,

I have a pdf (which I will send you via email) with the following issue. When I open the file with hexapdf, then write it again, the written fail is password protected and can no longer be opened.

I tried to dig a bit deeper myself but I didn't get far:

Looking forward to you assessment 😄

gettalong commented 1 year ago

Thanks - will have a look at it later. From the error description I'm guessing HexaPDF is messing something up concerning the two possible passwords.

gettalong commented 1 year ago

So this bugs seems to stem from the fact that the file in question is both, linearized and encrypted. This leads the encryption routine to invalidly believe that it has to encrypt the strings in the encryption dictionary but those strings must never be encrypted, obviously.

gettalong commented 1 year ago

Correction to the previous comment: Not connected to linearization but to the fact that the PDF file has multiple revisions.

Here is a simple example script that produces the invalid output:

require 'hexapdf'
require 'stringio'

doc = HexaPDF::Document.new
doc.encrypt
io = StringIO.new(''.b)
doc.write(io)

doc = HexaPDF::Document.new(io: io)
doc.pages.add
io2 = StringIO.new(''.b)
doc.write(io2, incremental: true)

doc = HexaPDF::Document.new(io: io2)
doc.write('out.pdf')

The more concrete reason why this error happens is that the comparison between the encryption dictionary that is written and the one that is stored in doc.trailer[:Encrypt] fails due to the two being actually different. This is courtesy of HexaPDF::Writer#move_modified_objects_into_current_revision which resets all revisions, making the writer load the encryption dictionary again and thus different from the stored one.

I have a working fix for the problem but will need to test a bit more.

gettalong commented 1 year ago

I have pushed the fix to the devel branch.