CAM-PDF - 128 bit pdf encryption (and password bug)

Posted on Sat Oct 18 21:52:17 2008 by joe312213
128 bit pdf encryption (and password bug)
Hi!

I'm trying to get your module to do version 2 (128bit) encryption.

I've read the relevant bits of the pdf spec and it seems all I should have done was add a 'Length' key to the dictionary (type number, value 128), set 'V' to 2 (also further down in the set_passwords sub, set
$self->{keylength} = 128
instead of 40) and bobs your uncle. unfortunately it didn't work out that way... my script runs and produces an encrypted pdf, but the keys are not accepted.

This is what I changed the set_passwords function in
CAM::PDF::Decrypt
to:
sub set_passwords { my $self = shift; my $doc = shift; my $opass = shift; my $upass = shift; my $p = shift || $self->{P} || $self->encode_permissions(1,1,1,1); require Digest::MD5; require Crypt::RC4; $doc->clean(); # Mark EVERYTHING changed # if no crypt block, create it and a trailer entry # changed V from 1 to 2 and added Length node my $cryptkeylength = 128; my $dict = CAM::PDF::Node->new('dictionary', { Filter => CAM::PDF::Node->new('label', 'Standard'), V => CAM::PDF::Node->new('number', 2), Length => CAM::PDF::Node->new('number', $cryptkeylength), R => CAM::PDF::Node->new('number', 2), P => CAM::PDF::Node->new('number', $p), O => CAM::PDF::Node->new('string', q{}), U => CAM::PDF::Node->new('string', q{}) }); my $objnode = CAM::PDF::Node->new('object', $dict); my $objnum = $self->{EncryptBlock}; if ($objnum) { $doc->replaceObject($objnum, undef, $objnode, 0); } else { $objnum = $doc->appendObject(undef, $objnode, 0); } if (!$doc->{trailer}) { die 'No trailer'; } # This may overwrite an existing ref, but that's no big deal, just a tiny bit inefficient $doc->{trailer}->{Encrypt} = CAM::PDF::Node->new('reference', $objnum); # if no ID, create it if (!$doc->{ID}) { $doc->createID(); #print 'new ID: ' . unpack('h*',$doc->{ID}) . ' (' . length($doc->{ID}) . ")\n"; } #else { print 'old ID: '.unpack('h*',$doc->{ID}) . ' (' . length($doc->{ID}) . ")\n"; } # Recompute O and U # To do so, we must set up a couple of dependent variables first: $self->{R} = 2; $self->{keylength} = $cryptkeylength; $self->{P} = $p; # set O (has to be first because U uses O) $self->{O} = $self->_compute_o($opass, $upass); # set U $self->{U} = $self->_compute_u($doc->{ID}, $upass); # save O and U in the Encrypt block $dict = $doc->getObjValue($objnum); $dict->{O}->{value} = $self->{O}; $dict->{U}->{value} = $self->{U}; # Create a brand new instance my $pkg = ref $self; $doc->{crypt} = $pkg->new($doc, $opass, $upass, 0) || die "$CAM::PDF::errstr\n"; return $doc->{crypt}; }
Also (when I changed the module back to bog-standard 40bit encryption, if I set the user password and owner password differently, the content seems to vanish from the pdf (it's the same size, and the passwords are accepted, but there's nothing on the page.) The simple 1 page pdf in question was created using pdf::api2

Any clues?

The encryption isn't much use at 40bits and neither is not being able to have seperate user and owner passwords, so I'd really like to get this fixed! I'm willing to put some time into it, but could use some help, thanks!

Joe
Direct Responses: 9120 | Write a response