Pack the /P (ermissions) entry from the /Encrypt dictionionary in the file trailer, as unsigned long (#352)
Fixes #186 * Tread the permissions (the /P entry) as unsigned long, fix #186 * handle negative values for p * Extract function for resolving an twos-complement * Add test for issue #352 * Add line to CHANGELOG.md * Only ints can be converted to a uint using two's-complement method * Standardize import style; multiple imports from same module on one line Co-authored-by: Pieter Marsman <pietermarsman@gmail.com>pull/360/head
parent
e4790fdbc2
commit
0b1741b9bf
|
@ -5,7 +5,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|||
|
||||
## [Unreleased]
|
||||
|
||||
Nothing here
|
||||
### Fixed
|
||||
- Interpret two's complement integer as unsigned integer ([#352](https://github.com/pdfminer/pdfminer.six/pull/352))
|
||||
|
||||
## [20200104] - 2019-01-04
|
||||
|
||||
|
|
|
@ -1,34 +1,21 @@
|
|||
import hashlib as md5
|
||||
import logging
|
||||
import re
|
||||
import struct
|
||||
import logging
|
||||
import hashlib as md5
|
||||
|
||||
try:
|
||||
from Crypto.Cipher import ARC4
|
||||
from Crypto.Cipher import AES
|
||||
from Crypto.Cipher import ARC4, AES
|
||||
from Crypto.Hash import SHA256
|
||||
except ImportError:
|
||||
AES = SHA256 = None
|
||||
from . import arcfour as ARC4
|
||||
from .psparser import PSEOF
|
||||
from .psparser import literal_name
|
||||
from .psparser import LIT
|
||||
from .psparser import KWD
|
||||
from .psparser import PSEOF, literal_name, LIT, KWD
|
||||
from . import settings
|
||||
from .pdftypes import PDFException
|
||||
from .pdftypes import PDFTypeError
|
||||
from .pdftypes import PDFStream
|
||||
from .pdftypes import PDFObjectNotFound
|
||||
from .pdftypes import decipher_all
|
||||
from .pdftypes import int_value
|
||||
from .pdftypes import str_value
|
||||
from .pdftypes import list_value
|
||||
from .pdftypes import dict_value
|
||||
from .pdftypes import stream_value
|
||||
from .pdfparser import PDFSyntaxError
|
||||
from .pdfparser import PDFStreamParser
|
||||
from .utils import choplist
|
||||
from .utils import nunpack
|
||||
from .utils import decode_text
|
||||
from .pdftypes import PDFException, uint_value, PDFTypeError, PDFStream, \
|
||||
PDFObjectNotFound, decipher_all, int_value, str_value, list_value, \
|
||||
dict_value, stream_value
|
||||
from .pdfparser import PDFSyntaxError, PDFStreamParser
|
||||
from .utils import choplist, nunpack, decode_text
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
@ -307,7 +294,7 @@ class PDFStandardSecurityHandler:
|
|||
def init_params(self):
|
||||
self.v = int_value(self.param.get('V', 0))
|
||||
self.r = int_value(self.param['R'])
|
||||
self.p = int_value(self.param['P'])
|
||||
self.p = uint_value(self.param['P'], 32)
|
||||
self.o = str_value(self.param['O'])
|
||||
self.u = str_value(self.param['U'])
|
||||
self.length = int_value(self.param.get('Length', 40))
|
||||
|
@ -348,7 +335,8 @@ class PDFStandardSecurityHandler:
|
|||
password = (password + self.PASSWORD_PADDING)[:32] # 1
|
||||
hash = md5.md5(password) # 2
|
||||
hash.update(self.o) # 3
|
||||
hash.update(struct.pack('<l', self.p)) # 4
|
||||
# See https://github.com/pdfminer/pdfminer.six/issues/186
|
||||
hash.update(struct.pack('<L', self.p)) # 4
|
||||
hash.update(self.docid[0]) # 5
|
||||
if self.r >= 4:
|
||||
if not self.encrypt_metadata:
|
||||
|
|
|
@ -139,6 +139,15 @@ def num_value(x):
|
|||
return x
|
||||
|
||||
|
||||
def uint_value(x, n_bits):
|
||||
"""Resolve number and interpret it as a two's-complement unsigned number"""
|
||||
x = int_value(x)
|
||||
if x > 0:
|
||||
return x
|
||||
else:
|
||||
return x + 2**n_bits
|
||||
|
||||
|
||||
def str_value(x):
|
||||
x = resolve1(x)
|
||||
if not isinstance(x, bytes):
|
||||
|
|
|
@ -124,7 +124,7 @@ def apply_matrix_norm(m, v):
|
|||
# Utility functions
|
||||
|
||||
def isnumber(x):
|
||||
return isinstance(x, ((int,), float))
|
||||
return isinstance(x, (int, float))
|
||||
|
||||
|
||||
def uniq(objs):
|
||||
|
|
Binary file not shown.
|
@ -35,7 +35,8 @@ class TestDumpPDF():
|
|||
|
||||
def test_nonfree_175(self):
|
||||
"""Regression test for:
|
||||
https://github.com/pdfminer/pdfminer.six/issues/65"""
|
||||
https://github.com/pdfminer/pdfminer.six/issues/65
|
||||
"""
|
||||
run('nonfree/175.pdf')
|
||||
|
||||
def test_nonfree_dmca(self):
|
||||
|
@ -63,6 +64,13 @@ class TestDumpPDF():
|
|||
"""Regression test for # https://github.com/euske/pdfminer/issues/96"""
|
||||
run('scancode/patchelf.pdf')
|
||||
|
||||
def test_contrib_hash_two_complement(self):
|
||||
"""Check that unsigned integer is added correctly to encryption hash.
|
||||
|
||||
See https://github.com/pdfminer/pdfminer.six/issues/186
|
||||
"""
|
||||
run('contrib/issue-00352-hash-twos-complement.pdf')
|
||||
|
||||
|
||||
class TestDumpImages:
|
||||
|
||||
|
|
Loading…
Reference in New Issue