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]
|
## [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
|
## [20200104] - 2019-01-04
|
||||||
|
|
||||||
|
|
|
@ -1,34 +1,21 @@
|
||||||
|
import hashlib as md5
|
||||||
|
import logging
|
||||||
import re
|
import re
|
||||||
import struct
|
import struct
|
||||||
import logging
|
|
||||||
import hashlib as md5
|
|
||||||
try:
|
try:
|
||||||
from Crypto.Cipher import ARC4
|
from Crypto.Cipher import ARC4, AES
|
||||||
from Crypto.Cipher import AES
|
|
||||||
from Crypto.Hash import SHA256
|
from Crypto.Hash import SHA256
|
||||||
except ImportError:
|
except ImportError:
|
||||||
AES = SHA256 = None
|
AES = SHA256 = None
|
||||||
from . import arcfour as ARC4
|
from . import arcfour as ARC4
|
||||||
from .psparser import PSEOF
|
from .psparser import PSEOF, literal_name, LIT, KWD
|
||||||
from .psparser import literal_name
|
|
||||||
from .psparser import LIT
|
|
||||||
from .psparser import KWD
|
|
||||||
from . import settings
|
from . import settings
|
||||||
from .pdftypes import PDFException
|
from .pdftypes import PDFException, uint_value, PDFTypeError, PDFStream, \
|
||||||
from .pdftypes import PDFTypeError
|
PDFObjectNotFound, decipher_all, int_value, str_value, list_value, \
|
||||||
from .pdftypes import PDFStream
|
dict_value, stream_value
|
||||||
from .pdftypes import PDFObjectNotFound
|
from .pdfparser import PDFSyntaxError, PDFStreamParser
|
||||||
from .pdftypes import decipher_all
|
from .utils import choplist, nunpack, decode_text
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
@ -307,7 +294,7 @@ class PDFStandardSecurityHandler:
|
||||||
def init_params(self):
|
def init_params(self):
|
||||||
self.v = int_value(self.param.get('V', 0))
|
self.v = int_value(self.param.get('V', 0))
|
||||||
self.r = int_value(self.param['R'])
|
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.o = str_value(self.param['O'])
|
||||||
self.u = str_value(self.param['U'])
|
self.u = str_value(self.param['U'])
|
||||||
self.length = int_value(self.param.get('Length', 40))
|
self.length = int_value(self.param.get('Length', 40))
|
||||||
|
@ -348,7 +335,8 @@ class PDFStandardSecurityHandler:
|
||||||
password = (password + self.PASSWORD_PADDING)[:32] # 1
|
password = (password + self.PASSWORD_PADDING)[:32] # 1
|
||||||
hash = md5.md5(password) # 2
|
hash = md5.md5(password) # 2
|
||||||
hash.update(self.o) # 3
|
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
|
hash.update(self.docid[0]) # 5
|
||||||
if self.r >= 4:
|
if self.r >= 4:
|
||||||
if not self.encrypt_metadata:
|
if not self.encrypt_metadata:
|
||||||
|
|
|
@ -139,6 +139,15 @@ def num_value(x):
|
||||||
return 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):
|
def str_value(x):
|
||||||
x = resolve1(x)
|
x = resolve1(x)
|
||||||
if not isinstance(x, bytes):
|
if not isinstance(x, bytes):
|
||||||
|
|
|
@ -124,7 +124,7 @@ def apply_matrix_norm(m, v):
|
||||||
# Utility functions
|
# Utility functions
|
||||||
|
|
||||||
def isnumber(x):
|
def isnumber(x):
|
||||||
return isinstance(x, ((int,), float))
|
return isinstance(x, (int, float))
|
||||||
|
|
||||||
|
|
||||||
def uniq(objs):
|
def uniq(objs):
|
||||||
|
|
Binary file not shown.
|
@ -35,7 +35,8 @@ class TestDumpPDF():
|
||||||
|
|
||||||
def test_nonfree_175(self):
|
def test_nonfree_175(self):
|
||||||
"""Regression test for:
|
"""Regression test for:
|
||||||
https://github.com/pdfminer/pdfminer.six/issues/65"""
|
https://github.com/pdfminer/pdfminer.six/issues/65
|
||||||
|
"""
|
||||||
run('nonfree/175.pdf')
|
run('nonfree/175.pdf')
|
||||||
|
|
||||||
def test_nonfree_dmca(self):
|
def test_nonfree_dmca(self):
|
||||||
|
@ -63,6 +64,13 @@ class TestDumpPDF():
|
||||||
"""Regression test for # https://github.com/euske/pdfminer/issues/96"""
|
"""Regression test for # https://github.com/euske/pdfminer/issues/96"""
|
||||||
run('scancode/patchelf.pdf')
|
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:
|
class TestDumpImages:
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue