From 90e361380a3e5bea380ef29be817509613e08e3e Mon Sep 17 00:00:00 2001 From: Benjamin Dornel Date: Sun, 8 Oct 2023 22:14:34 +0800 Subject: [PATCH 1/3] refactor(john): use pyhanko library to manage encryption metadata --- monopoly/helpers/pdf2john.py | 377 ++++++----------------------------- poetry.lock | 325 +++++++++++++++++++++++++++++- pyproject.toml | 1 + 3 files changed, 382 insertions(+), 321 deletions(-) diff --git a/monopoly/helpers/pdf2john.py b/monopoly/helpers/pdf2john.py index e5936a49..20851f25 100644 --- a/monopoly/helpers/pdf2john.py +++ b/monopoly/helpers/pdf2john.py @@ -1,355 +1,92 @@ -# pylint: skip-file -# flake8: noqa #!/usr/bin/env python -# Copyright (c) 2013 Shane Quigley, < shane at softwareontheside.info > - -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: - -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. - -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - +import logging import os -import re import sys -from xml.dom import minidom -PY3 = sys.version_info[0] == 3 +from pyhanko.pdf_utils.crypt import SecurityHandlerVersion +from pyhanko.pdf_utils.reader import PdfFileReader + +logger = logging.getLogger(__name__) class PdfHashExtractor: def __init__(self, file_name): self.file_name = file_name - f = open(file_name, "rb") - self.encrypted = f.read() - f.close() - self.process = True - psr = re.compile(b"PDF-\d\.\d") - try: - self.pdf_spec = psr.findall(self.encrypted)[0] - except IndexError: - sys.stderr.write("%s is not a PDF file!\n" % file_name) - self.process = False + + with open(file_name, "rb") as doc: + pdf = PdfFileReader(doc, strict=False) + self.document_id = pdf.document_id + self.encryption_params = pdf._get_encryption_params() + self.trailer = pdf.trailer + self.pdf_spec = pdf._header_version + self.security_handler = pdf.security_handler def parse(self): - if not self.process: - return + algorithm = self.encryption_params["/V"] + revision = self.encryption_params["/R"] + length = self.encryption_params["/Length"] + permissions = self.encryption_params["/P"] - try: - trailer = self.get_trailer() - except RuntimeError: - e = sys.exc_info()[1] - sys.stderr.write("%s : %s\n" % (self.file_name, str(e))) - return - # print >> sys.stderr, trailer - object_id = self.get_object_id(b"Encrypt", trailer) - # print >> sys.stderr, object_id - if len(object_id) == 0: - raise RuntimeError("Could not find object id") - encryption_dictionary = self.get_encryption_dictionary(object_id) - # print >> sys.stderr, encryption_dictionary - dr = re.compile(b"\d+") - vr = re.compile(b"\/V \d") - rr = re.compile(b"\/R \d") - try: - v = dr.findall(vr.findall(encryption_dictionary)[0])[0] - except IndexError: - raise RuntimeError("Could not find /V") - r = dr.findall(rr.findall(encryption_dictionary)[0])[0] - lr = re.compile(b"\/Length \d+") - longest = 0 - # According to the docs: - # Length : (Optional; PDF 1.4; only if V is 2 or 3). Default value: 40 - length = b"40" - for le in lr.findall(encryption_dictionary): - if int(dr.findall(le)[0]) > longest: - longest = int(dr.findall(le)[0]) - length = dr.findall(le)[0] - pr = re.compile(b"\/P -?\d+") - try: - p = pr.findall(encryption_dictionary)[0] - except IndexError: - # print >> sys.stderr, "** dict:", encryption_dictionary - raise RuntimeError("Could not find /P") - pr = re.compile(b"-?\d+") - p = pr.findall(p)[0] - meta = "1" if self.is_meta_data_encrypted(encryption_dictionary) else "0" - idr = re.compile(b"\/ID\s*\[\s*<\w+>\s*<\w+>\s*\]") - try: - i_d = idr.findall(trailer)[0] # id key word - except IndexError: - # some pdf files use () instead of <> - idr = re.compile(b"\/ID\s*\[\s*\(\w+\)\s*\(\w+\)\s*\]") - try: - i_d = idr.findall(trailer)[0] # id key word - except IndexError: - # print >> sys.stderr, "** idr:", idr - # print >> sys.stderr, "** trailer:", trailer - raise RuntimeError("Could not find /ID tag") + document_id = self.document_id[0].hex() + passwords = self.get_passwords() - idr = re.compile(b"<\w+>") - try: - i_d = idr.findall(trailer)[0] - except IndexError: - idr = re.compile(b"\(\w+\)") - i_d = idr.findall(trailer)[0] - i_d = i_d.replace(b"<", b"") - i_d = i_d.replace(b">", b"") - i_d = i_d.lower() - passwords = self.get_passwords_for_JtR(encryption_dictionary) output = ( - "$pdf$" - + v.decode("ascii") - + "*" - + r.decode("ascii") + "$pdf$" + str(algorithm) + "*" + str(revision) + "*" + str(length) + "*" + ) + + output += ( + str(permissions) + "*" - + length.decode("ascii") + + str(int(self.security_handler.encrypt_metadata)) + "*" ) - output += p.decode("ascii") + "*" + meta + "*" - output += str(int(len(i_d) / 2)) + "*" + i_d.decode("ascii") + "*" + passwords + output += str(int(len(document_id) / 2)) + "*" + document_id + "*" + passwords + logger.info("Hash: %s", output) + return output - def get_passwords_for_JtR(self, encryption_dictionary): + def get_passwords(self): output = "" - letters = [b"U", b"O"] - if b"1.7" in self.pdf_spec: - letters = [b"U", b"O", b"UE", b"OE"] - for let in letters: - pr_str = b"\/" + let + b"\s*\([^)]+\)" - pr = re.compile(pr_str) - pas = pr.findall(encryption_dictionary) - if len(pas) > 0: - pas = pr.findall(encryption_dictionary)[0] - # because regexs in python suck <=== LOL - while pas[-2] == b"\\": - pr_str += b"[^)]+\)" - pr = re.compile(pr_str) - # print >> sys.stderr, "pr_str:", pr_str - # print >> sys.stderr, encryption_dictionary - try: - pas = pr.findall(encryption_dictionary)[0] - except IndexError: - break - output += self.get_password_from_byte_string(pas) + "*" - else: - pr = re.compile(let + b"\s*<\w+>") - pas = pr.findall(encryption_dictionary) - if not pas: - continue - pas = pas[0] - pr = re.compile(b"<\w+>") - pas = pr.findall(pas)[0] - pas = pas.replace(b"<", b"") - pas = pas.replace(b">", b"") - if PY3: - output += ( - str(int(len(pas) / 2)) + "*" + str(pas.lower(), "ascii") + "*" - ) - else: - output += str(int(len(pas) / 2)) + "*" + pas.lower() + "*" - return output[:-1] - - def is_meta_data_encrypted(self, encryption_dictionary): - mr = re.compile(b"\/EncryptMetadata\s\w+") - if len(mr.findall(encryption_dictionary)) > 0: - wr = re.compile(b"\w+") - is_encrypted = wr.findall(mr.findall(encryption_dictionary)[0])[-1] - if is_encrypted == b"false": - return False - else: - return True - else: - return True + encryption_keys = ["/U", "/O"] - def parse_meta_data(self, trailer): - root_object_id = self.get_object_id(b"Root", trailer) - root_object = self.get_pdf_object(root_object_id) - object_id = self.get_object_id(b"Metadata", root_object) - xmp_metadata_object = self.get_pdf_object(object_id) - return self.get_xmp_values(xmp_metadata_object) + # Support for PDF-1.7 + if self.pdf_spec == (1, 7): + encryption_keys.extend(["/UE", "/OE"]) - def get_xmp_values(self, xmp_metadata_object): - xmp_metadata_object = xmp_metadata_object.partition(b"stream")[2] - xmp_metadata_object = xmp_metadata_object.partition(b"endstream")[0] - try: - xml_metadata = minidom.parseString(xmp_metadata_object) - except: - return "" - values = [] - values.append(self.get_dc_value("title", xml_metadata)) - values.append(self.get_dc_value("creator", xml_metadata)) - values.append(self.get_dc_value("description", xml_metadata)) - values.append(self.get_dc_value("subject", xml_metadata)) - created_year = xml_metadata.getElementsByTagName("xmp:CreateDate") - if len(created_year) > 0: - created_year = created_year[0].firstChild.data[0:4] - values.append(str(created_year)) - return " ".join(values).replace(":", "") + for key in encryption_keys: + data = self.encryption_params.get(key, b"") - def get_dc_value(self, value, xml_metadata): - output = xml_metadata.getElementsByTagName("dc:" + value) - if len(output) > 0: - output = output[0] - output = output.getElementsByTagName("rdf:li")[0] - if output.firstChild: - output = output.firstChild.data - return output - return "" + if key in ("/O", "/U"): + logger.info( + "Security handler version: %s", self.security_handler.version + ) + if self.security_handler.version == SecurityHandlerVersion.AES256: + data = data[:40] - def get_encryption_dictionary(self, object_id): - encryption_dictionary = self.get_pdf_object(object_id) - for o in encryption_dictionary.split(b"endobj"): - if object_id + b" obj" in o: - encryption_dictionary = o - return encryption_dictionary + # Legacy support for older PDF specifications + if ( + self.security_handler.version + <= SecurityHandlerVersion.RC4_OR_AES128 + ): + data = data[:32] - def get_object_id(self, name, trailer): - oir = re.compile(b"\/" + name + b"\s\d+\s\d\sR") - try: - object_id = oir.findall(trailer)[0] - except IndexError: - # print >> sys.stderr, " ** get_object_id: name \"", name, "\", trailer ", trailer - return "" - oir = re.compile(b"\d+ \d") - object_id = oir.findall(object_id)[0] - return object_id + output += str(int(len(data))) + "*" + data.hex() + "*" - def get_pdf_object(self, object_id): - output = ( - object_id - + b" obj" - + self.encrypted.partition(b"\r" + object_id + b" obj")[2] - ) - if output == object_id + b" obj": - output = ( - object_id - + b" obj" - + self.encrypted.partition(b"\n" + object_id + b" obj")[2] - ) - output = output.partition(b"endobj")[0] + b"endobj" - # print >> sys.stderr, output return output - def get_trailer(self): - trailer = self.get_data_between(b"trailer", b">>", b"/ID") - if trailer == b"": - trailer = self.get_data_between(b"DecodeParms", b"stream", b"") - if trailer == "": - raise RuntimeError("Can't find trailer") - if trailer != "" and trailer.find(b"Encrypt") == -1: - # print >> sys.stderr, trailer - raise RuntimeError("File not encrypted") - return trailer - - def get_data_between(self, s1, s2, tag): - output = b"" - inside_first = False - lines = re.split(b"\n|\r", self.encrypted) - for line in lines: - inside_first = inside_first or line.find(s1) != -1 - if inside_first: - output += line - if line.find(s2) != -1: - if tag == b"" or output.find(tag) != -1: - break - else: - output = b"" - inside_first = False - return output - - def get_hex_byte(self, o_or_u, i): - if PY3: - return hex(o_or_u[i]).replace("0x", "") - else: - return hex(ord(o_or_u[i])).replace("0x", "") - - def get_password_from_byte_string(self, o_or_u): - pas = "" - escape_seq = False - escapes = 0 - excluded_indexes = [0, 1, 2] - # For UE & OE in 1.7 spec - if not PY3: - if o_or_u[2] != "(": - excluded_indexes.append(3) - else: - if o_or_u[2] != 40: - excluded_indexes.append(3) - for i in range(len(o_or_u)): - if i not in excluded_indexes: - if len(self.get_hex_byte(o_or_u, i)) == 1 and o_or_u[i] != "\\"[0]: - pas += "0" # need to be 2 digit hex numbers - is_back_slash = True - if not PY3: - is_back_slash = o_or_u[i] != "\\"[0] - else: - is_back_slash = o_or_u[i] != 92 - if is_back_slash or escape_seq: - if escape_seq: - if not PY3: - esc = "\\" + o_or_u[i] - else: - esc = "\\" + chr(o_or_u[i]) - esc = self.unescape(esc) - if len(hex(ord(esc[0])).replace("0x", "")) == 1: - pas += "0" - pas += hex(ord(esc[0])).replace("0x", "") - escape_seq = False - else: - pas += self.get_hex_byte(o_or_u, i) - else: - escape_seq = True - escapes += 1 - output = len(o_or_u) - (len(excluded_indexes) + 1) - escapes - return str(output) + "*" + pas[:-2] - - def unescape(self, esc): - escape_seq_map = { - "\\n": "\n", - "\\s": "\s", - "\\e": "\e", - "\\r": "\r", - "\\t": "\t", - "\\v": "\v", - "\\f": "\f", - "\\b": "\b", - "\\a": "\a", - "\\)": ")", - "\\(": "(", - "\\\\": "\\", - "\\0": "\0", - } - - return escape_seq_map[esc] - if __name__ == "__main__": if len(sys.argv) < 2: - sys.stderr.write("Usage: %s \n" % os.path.basename(sys.argv[0])) + logger.error(f"Usage: {os.path.basename(sys.argv[0])} ") sys.exit(-1) + for j in range(1, len(sys.argv)): - if not PY3: - filename = sys.argv[j].decode("UTF-8") - else: - filename = sys.argv[j] - # sys.stderr.write("Analyzing %s\n" % sys.argv[j].decode('UTF-8')) - unlocker = PdfHashExtractor(filename) + filename = sys.argv[j] + logger.info(f"Analyzing {filename}") + extractor = PdfHashExtractor(filename) + try: - unlocker.parse() - except RuntimeError: - e = sys.exc_info()[1] - sys.stderr.write("%s : %s\n" % (filename, str(e))) + extractor.parse() + except RuntimeError as e: + logger.error(f"{filename} : {str(e)}") diff --git a/poetry.lock b/poetry.lock index c0922500..6b2fd336 100644 --- a/poetry.lock +++ b/poetry.lock @@ -11,6 +11,17 @@ files = [ {file = "annotated_types-0.5.0.tar.gz", hash = "sha256:47cdc3490d9ac1506ce92c7aaa76c579dc3509ff11e098fc867e5130ab7be802"}, ] +[[package]] +name = "asn1crypto" +version = "1.5.1" +description = "Fast ASN.1 parser and serializer with definitions for private keys, public keys, certificates, CRL, OCSP, CMS, PKCS#3, PKCS#7, PKCS#8, PKCS#12, PKCS#5, X.509 and TSP" +optional = false +python-versions = "*" +files = [ + {file = "asn1crypto-1.5.1-py2.py3-none-any.whl", hash = "sha256:db4e40728b728508912cbb3d44f19ce188f218e9eba635821bb4b68564f8fd67"}, + {file = "asn1crypto-1.5.1.tar.gz", hash = "sha256:13ae38502be632115abf8a24cbe5f4da52e3b5231990aff31123c805306ccb9c"}, +] + [[package]] name = "astroid" version = "2.15.6" @@ -92,6 +103,70 @@ files = [ {file = "certifi-2023.7.22.tar.gz", hash = "sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082"}, ] +[[package]] +name = "cffi" +version = "1.16.0" +description = "Foreign Function Interface for Python calling C code." +optional = false +python-versions = ">=3.8" +files = [ + {file = "cffi-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6b3d6606d369fc1da4fd8c357d026317fbb9c9b75d36dc16e90e84c26854b088"}, + {file = "cffi-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ac0f5edd2360eea2f1daa9e26a41db02dd4b0451b48f7c318e217ee092a213e9"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7e61e3e4fa664a8588aa25c883eab612a188c725755afff6289454d6362b9673"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a72e8961a86d19bdb45851d8f1f08b041ea37d2bd8d4fd19903bc3083d80c896"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b50bf3f55561dac5438f8e70bfcdfd74543fd60df5fa5f62d94e5867deca684"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7651c50c8c5ef7bdb41108b7b8c5a83013bfaa8a935590c5d74627c047a583c7"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4108df7fe9b707191e55f33efbcb2d81928e10cea45527879a4749cbe472614"}, + {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:32c68ef735dbe5857c810328cb2481e24722a59a2003018885514d4c09af9743"}, + {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:673739cb539f8cdaa07d92d02efa93c9ccf87e345b9a0b556e3ecc666718468d"}, + {file = "cffi-1.16.0-cp310-cp310-win32.whl", hash = "sha256:9f90389693731ff1f659e55c7d1640e2ec43ff725cc61b04b2f9c6d8d017df6a"}, + {file = "cffi-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:e6024675e67af929088fda399b2094574609396b1decb609c55fa58b028a32a1"}, + {file = "cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404"}, + {file = "cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee07e47c12890ef248766a6e55bd38ebfb2bb8edd4142d56db91b21ea68b7627"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e70f54f1796669ef691ca07d046cd81a29cb4deb1e5f942003f401c0c4a2695d"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5bf44d66cdf9e893637896c7faa22298baebcd18d1ddb6d2626a6e39793a1d56"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e"}, + {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c6a164aa47843fb1b01e941d385aab7215563bb8816d80ff3a363a9f8448a8dc"}, + {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e09f3ff613345df5e8c3667da1d918f9149bd623cd9070c983c013792a9a62eb"}, + {file = "cffi-1.16.0-cp311-cp311-win32.whl", hash = "sha256:2c56b361916f390cd758a57f2e16233eb4f64bcbeee88a4881ea90fca14dc6ab"}, + {file = "cffi-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba"}, + {file = "cffi-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956"}, + {file = "cffi-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:68e7c44931cc171c54ccb702482e9fc723192e88d25a0e133edd7aff8fcd1f6e"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abd808f9c129ba2beda4cfc53bde801e5bcf9d6e0f22f095e45327c038bfe68e"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88e2b3c14bdb32e440be531ade29d3c50a1a59cd4e51b1dd8b0865c54ea5d2e2"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b7be2d771cdba2942e13215c4e340bfd76398e9227ad10402a8767ab1865d2e6"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e715596e683d2ce000574bae5d07bd522c781a822866c20495e52520564f0969"}, + {file = "cffi-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2d92b25dbf6cae33f65005baf472d2c245c050b1ce709cc4588cdcdd5495b520"}, + {file = "cffi-1.16.0-cp312-cp312-win32.whl", hash = "sha256:b2ca4e77f9f47c55c194982e10f058db063937845bb2b7a86c84a6cfe0aefa8b"}, + {file = "cffi-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:68678abf380b42ce21a5f2abde8efee05c114c2fdb2e9eef2efdb0257fba1235"}, + {file = "cffi-1.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a09582f178759ee8128d9270cd1344154fd473bb77d94ce0aeb2a93ebf0feaf0"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e760191dd42581e023a68b758769e2da259b5d52e3103c6060ddc02c9edb8d7b"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:80876338e19c951fdfed6198e70bc88f1c9758b94578d5a7c4c91a87af3cf31c"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a6a14b17d7e17fa0d207ac08642c8820f84f25ce17a442fd15e27ea18d67c59b"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6602bc8dc6f3a9e02b6c22c4fc1e47aa50f8f8e6d3f78a5e16ac33ef5fefa324"}, + {file = "cffi-1.16.0-cp38-cp38-win32.whl", hash = "sha256:131fd094d1065b19540c3d72594260f118b231090295d8c34e19a7bbcf2e860a"}, + {file = "cffi-1.16.0-cp38-cp38-win_amd64.whl", hash = "sha256:31d13b0f99e0836b7ff893d37af07366ebc90b678b6664c955b54561fc36ef36"}, + {file = "cffi-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:582215a0e9adbe0e379761260553ba11c58943e4bbe9c36430c4ca6ac74b15ed"}, + {file = "cffi-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b29ebffcf550f9da55bec9e02ad430c992a87e5f512cd63388abb76f1036d8d2"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dc9b18bf40cc75f66f40a7379f6a9513244fe33c0e8aa72e2d56b0196a7ef872"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cb4a35b3642fc5c005a6755a5d17c6c8b6bcb6981baf81cea8bfbc8903e8ba8"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b86851a328eedc692acf81fb05444bdf1891747c25af7529e39ddafaf68a4f3f"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c0f31130ebc2d37cdd8e44605fb5fa7ad59049298b3f745c74fa74c62fbfcfc4"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f8e709127c6c77446a8c0a8c8bf3c8ee706a06cd44b1e827c3e6a2ee6b8c098"}, + {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:748dcd1e3d3d7cd5443ef03ce8685043294ad6bd7c02a38d1bd367cfd968e000"}, + {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8895613bcc094d4a1b2dbe179d88d7fb4a15cee43c052e8885783fac397d91fe"}, + {file = "cffi-1.16.0-cp39-cp39-win32.whl", hash = "sha256:ed86a35631f7bfbb28e108dd96773b9d5a6ce4811cf6ea468bb6a359b256b1e4"}, + {file = "cffi-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:3686dffb02459559c74dd3d81748269ffb0eb027c39a6fc99502de37d501faa8"}, + {file = "cffi-1.16.0.tar.gz", hash = "sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0"}, +] + +[package.dependencies] +pycparser = "*" + [[package]] name = "charset-normalizer" version = "3.2.0" @@ -201,6 +276,51 @@ files = [ {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] +[[package]] +name = "cryptography" +version = "41.0.4" +description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." +optional = false +python-versions = ">=3.7" +files = [ + {file = "cryptography-41.0.4-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:80907d3faa55dc5434a16579952ac6da800935cd98d14dbd62f6f042c7f5e839"}, + {file = "cryptography-41.0.4-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:35c00f637cd0b9d5b6c6bd11b6c3359194a8eba9c46d4e875a3660e3b400005f"}, + {file = "cryptography-41.0.4-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cecfefa17042941f94ab54f769c8ce0fe14beff2694e9ac684176a2535bf9714"}, + {file = "cryptography-41.0.4-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e40211b4923ba5a6dc9769eab704bdb3fbb58d56c5b336d30996c24fcf12aadb"}, + {file = "cryptography-41.0.4-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:23a25c09dfd0d9f28da2352503b23e086f8e78096b9fd585d1d14eca01613e13"}, + {file = "cryptography-41.0.4-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:2ed09183922d66c4ec5fdaa59b4d14e105c084dd0febd27452de8f6f74704143"}, + {file = "cryptography-41.0.4-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:5a0f09cefded00e648a127048119f77bc2b2ec61e736660b5789e638f43cc397"}, + {file = "cryptography-41.0.4-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:9eeb77214afae972a00dee47382d2591abe77bdae166bda672fb1e24702a3860"}, + {file = "cryptography-41.0.4-cp37-abi3-win32.whl", hash = "sha256:3b224890962a2d7b57cf5eeb16ccaafba6083f7b811829f00476309bce2fe0fd"}, + {file = "cryptography-41.0.4-cp37-abi3-win_amd64.whl", hash = "sha256:c880eba5175f4307129784eca96f4e70b88e57aa3f680aeba3bab0e980b0f37d"}, + {file = "cryptography-41.0.4-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:004b6ccc95943f6a9ad3142cfabcc769d7ee38a3f60fb0dddbfb431f818c3a67"}, + {file = "cryptography-41.0.4-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:86defa8d248c3fa029da68ce61fe735432b047e32179883bdb1e79ed9bb8195e"}, + {file = "cryptography-41.0.4-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:37480760ae08065437e6573d14be973112c9e6dcaf5f11d00147ee74f37a3829"}, + {file = "cryptography-41.0.4-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:b5f4dfe950ff0479f1f00eda09c18798d4f49b98f4e2006d644b3301682ebdca"}, + {file = "cryptography-41.0.4-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:7e53db173370dea832190870e975a1e09c86a879b613948f09eb49324218c14d"}, + {file = "cryptography-41.0.4-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:5b72205a360f3b6176485a333256b9bcd48700fc755fef51c8e7e67c4b63e3ac"}, + {file = "cryptography-41.0.4-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:93530900d14c37a46ce3d6c9e6fd35dbe5f5601bf6b3a5c325c7bffc030344d9"}, + {file = "cryptography-41.0.4-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:efc8ad4e6fc4f1752ebfb58aefece8b4e3c4cae940b0994d43649bdfce8d0d4f"}, + {file = "cryptography-41.0.4-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:c3391bd8e6de35f6f1140e50aaeb3e2b3d6a9012536ca23ab0d9c35ec18c8a91"}, + {file = "cryptography-41.0.4-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:0d9409894f495d465fe6fda92cb70e8323e9648af912d5b9141d616df40a87b8"}, + {file = "cryptography-41.0.4-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:8ac4f9ead4bbd0bc8ab2d318f97d85147167a488be0e08814a37eb2f439d5cf6"}, + {file = "cryptography-41.0.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:047c4603aeb4bbd8db2756e38f5b8bd7e94318c047cfe4efeb5d715e08b49311"}, + {file = "cryptography-41.0.4.tar.gz", hash = "sha256:7febc3094125fc126a7f6fb1f420d0da639f3f32cb15c8ff0dc3997c4549f51a"}, +] + +[package.dependencies] +cffi = ">=1.12" + +[package.extras] +docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=1.1.1)"] +docstest = ["pyenchant (>=1.6.11)", "sphinxcontrib-spelling (>=4.0.1)", "twine (>=1.12.0)"] +nox = ["nox"] +pep8test = ["black", "check-sdist", "mypy", "ruff"] +sdist = ["build"] +ssh = ["bcrypt (>=3.1.5)"] +test = ["pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"] +test-randomorder = ["pytest-randomly"] + [[package]] name = "dill" version = "0.3.7" @@ -803,6 +923,20 @@ rsa = ["cryptography (>=3.0.0)"] signals = ["blinker (>=1.4.0)"] signedtoken = ["cryptography (>=3.0.0)", "pyjwt (>=2.0.0,<3)"] +[[package]] +name = "oscrypto" +version = "1.3.0" +description = "TLS (SSL) sockets, key generation, encryption, decryption, signing, verification and KDFs using the OS crypto libraries. Does not require a compiler, and relies on the OS for patching. Works on Windows, OS X and Linux/BSD." +optional = false +python-versions = "*" +files = [ + {file = "oscrypto-1.3.0-py2.py3-none-any.whl", hash = "sha256:2b2f1d2d42ec152ca90ccb5682f3e051fb55986e1b170ebde472b133713e7085"}, + {file = "oscrypto-1.3.0.tar.gz", hash = "sha256:6f5fef59cb5b3708321db7cca56aed8ad7e662853351e7991fcf60ec606d47a4"}, +] + +[package.dependencies] +asn1crypto = ">=1.5.1" + [[package]] name = "packaging" version = "23.1" @@ -1083,6 +1217,17 @@ files = [ {file = "pycodestyle-2.11.0.tar.gz", hash = "sha256:259bcc17857d8a8b3b4a2327324b79e5f020a13c16074670f9c8c8f872ea76d0"}, ] +[[package]] +name = "pycparser" +version = "2.21" +description = "C parser in Python" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"}, + {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, +] + [[package]] name = "pydantic" version = "2.4.2" @@ -1246,6 +1391,63 @@ files = [ {file = "pyflakes-3.1.0.tar.gz", hash = "sha256:a0aae034c444db0071aa077972ba4768d40c830d9539fd45bf4cd3f8f6992efc"}, ] +[[package]] +name = "pyhanko" +version = "0.20.1" +description = "Tools for stamping and signing PDF files" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pyHanko-0.20.1-py3-none-any.whl", hash = "sha256:463068cbea01792037cacbad11141cc9070c80b63cf738f488167bb6700d36fa"}, + {file = "pyHanko-0.20.1.tar.gz", hash = "sha256:93de44061c0907c9121cf35f20294930f31f22cf71334907ddde8e8fefbafcbc"}, +] + +[package.dependencies] +asn1crypto = ">=1.5.1" +click = ">=7.1.2" +cryptography = ">=3.3.1" +pyhanko-certvalidator = "==0.24.*" +pyyaml = ">=5.3.1" +qrcode = ">=6.1" +requests = ">=2.24.0" +tzlocal = ">=4.3" + +[package.extras] +async-http = ["aiohttp (>=3.8.0,<3.9.0)"] +docs = ["sphinx", "sphinx-rtd-theme"] +extra-pubkey-algs = ["oscrypto (>=1.2.1)"] +image-support = ["Pillow (>=7.2.0)", "python-barcode (==0.15.1)"] +live-test = ["certomancer-csc-dummy (==0.2.2)", "certomancer[pkcs12,web-api] (>=0.11.0,<0.12.0)", "pyHanko[async-http,extra-pubkey-algs,testing-basic,xmp]", "pytest-aiohttp (>=1.0.4,<1.1.0)", "pytest-cov (>=4.0,<4.2)"] +mypy = ["pyHanko[async-http,extra-pubkey-algs,image-support,opentype,pkcs11,xmp]", "types-PyYAML", "types-python-dateutil", "types-requests", "types-tzlocal"] +opentype = ["fonttools (>=4.33.3)", "uharfbuzz (>=0.25.0,<0.38.0)"] +pkcs11 = ["python-pkcs11 (>=0.7.0,<0.8.0)"] +testing = ["certomancer-csc-dummy (==0.2.2)", "pyHanko[async-http,extra-pubkey-algs,image-support,opentype,pkcs11,testing-basic,xmp]", "pytest-aiohttp (>=1.0.4,<1.1.0)"] +testing-basic = ["backports.zoneinfo[tzdata]", "certomancer (==0.11.*)", "freezegun (>=1.1.0)", "pytest (>=6.1.1)", "pytest-asyncio (==0.21.1)", "pytest-cov (>=4.0,<4.2)", "requests-mock (>=1.8.0)"] +xmp = ["defusedxml (>=0.7.1,<0.8.0)"] + +[[package]] +name = "pyhanko-certvalidator" +version = "0.24.1" +description = "Validates X.509 certificates and paths; forked from wbond/certvalidator" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pyhanko-certvalidator-0.24.1.tar.gz", hash = "sha256:4c6de2c2372751df8d449451583a84da6b01cd2e3156b0a3da2b06613cbbf25d"}, + {file = "pyhanko_certvalidator-0.24.1-py3-none-any.whl", hash = "sha256:46d093df4768319a8c54ce3edb5c4df42f06de010907ff01630e75378561b5ca"}, +] + +[package.dependencies] +asn1crypto = ">=1.5.1" +cryptography = ">=3.3.1" +oscrypto = ">=1.1.0" +requests = ">=2.24.0" +uritools = ">=3.0.1" + +[package.extras] +async-http = ["aiohttp (>=3.8.0,<3.9.0)"] +mypy = ["pyhanko-certvalidator[testing]", "types-requests"] +testing = ["aiohttp (>=3.8.0,<3.9.0)", "freezegun (>=1.1.0)", "pyhanko-certvalidator[async-http]", "pytest (>=6.1.1)", "pytest-aiohttp (>=1.0.4,<1.1.0)", "pytest-cov (>=4.0,<4.2)"] + [[package]] name = "pylint" version = "2.17.5" @@ -1365,6 +1567,17 @@ files = [ [package.extras] diagrams = ["jinja2", "railroad-diagrams"] +[[package]] +name = "pypng" +version = "0.20220715.0" +description = "Pure Python library for saving and loading PNG images" +optional = false +python-versions = "*" +files = [ + {file = "pypng-0.20220715.0-py3-none-any.whl", hash = "sha256:4a43e969b8f5aaafb2a415536c1a8ec7e341cd6a3f957fd5b5f32a4cfeed902c"}, + {file = "pypng-0.20220715.0.tar.gz", hash = "sha256:739c433ba96f078315de54c0db975aee537cbc3e1d0ae4ed9aab0ca1e427e2c1"}, +] + [[package]] name = "pysnooper" version = "1.2.0" @@ -1473,6 +1686,88 @@ files = [ {file = "pytz-2023.3.post1.tar.gz", hash = "sha256:7b4fddbeb94a1eba4b557da24f19fdf9db575192544270a9101d8509f9f43d7b"}, ] +[[package]] +name = "pyyaml" +version = "6.0.1" +description = "YAML parser and emitter for Python" +optional = false +python-versions = ">=3.6" +files = [ + {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"}, + {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, + {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, + {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, + {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, + {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, + {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, + {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, + {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, + {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, + {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, + {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"}, + {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"}, + {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, + {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, + {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, + {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, + {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, + {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, + {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, + {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, +] + +[[package]] +name = "qrcode" +version = "7.4.2" +description = "QR Code image generator" +optional = false +python-versions = ">=3.7" +files = [ + {file = "qrcode-7.4.2-py3-none-any.whl", hash = "sha256:581dca7a029bcb2deef5d01068e39093e80ef00b4a61098a2182eac59d01643a"}, + {file = "qrcode-7.4.2.tar.gz", hash = "sha256:9dd969454827e127dbd93696b20747239e6d540e082937c90f14ac95b30f5845"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} +pypng = "*" +typing-extensions = "*" + +[package.extras] +all = ["pillow (>=9.1.0)", "pytest", "pytest-cov", "tox", "zest.releaser[recommended]"] +dev = ["pytest", "pytest-cov", "tox"] +maintainer = ["zest.releaser[recommended]"] +pil = ["pillow (>=9.1.0)"] +test = ["coverage", "pytest"] + [[package]] name = "requests" version = "2.31.0" @@ -1598,6 +1893,23 @@ files = [ {file = "tzdata-2023.3.tar.gz", hash = "sha256:11ef1e08e54acb0d4f95bdb1be05da659673de4acbd21bf9c69e94cc5e907a3a"}, ] +[[package]] +name = "tzlocal" +version = "5.1" +description = "tzinfo object for the local timezone" +optional = false +python-versions = ">=3.7" +files = [ + {file = "tzlocal-5.1-py3-none-any.whl", hash = "sha256:2938498395d5f6a898ab8009555cb37a4d360913ad375d4747ef16826b03ef23"}, + {file = "tzlocal-5.1.tar.gz", hash = "sha256:a5ccb2365b295ed964e0a98ad076fe10c495591e75505d34f154d60a7f1ed722"}, +] + +[package.dependencies] +tzdata = {version = "*", markers = "platform_system == \"Windows\""} + +[package.extras] +devenv = ["black", "check-manifest", "flake8", "pyroma", "pytest (>=4.3)", "pytest-cov", "pytest-mock (>=3.3)", "zest.releaser"] + [[package]] name = "uritemplate" version = "4.1.1" @@ -1609,6 +1921,17 @@ files = [ {file = "uritemplate-4.1.1.tar.gz", hash = "sha256:4346edfc5c3b79f694bccd6d6099a322bbeb628dbf2cd86eea55a456ce5124f0"}, ] +[[package]] +name = "uritools" +version = "4.0.2" +description = "URI parsing, classification and composition" +optional = false +python-versions = ">=3.7" +files = [ + {file = "uritools-4.0.2-py3-none-any.whl", hash = "sha256:607b15eae1e7b69a120f463a7d98f91a56671e1ab92aae13f8e1f25c017fe60e"}, + {file = "uritools-4.0.2.tar.gz", hash = "sha256:04df2b787d0eb76200e8319382a03562fbfe4741fd66c15506b08d3b8211d573"}, +] + [[package]] name = "urllib3" version = "1.26.16" @@ -1712,4 +2035,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = "^3.11" -content-hash = "a1295bd964f51bad3e9924734320e8ba339a40408fac9a441a7b58e3f0e0383e" +content-hash = "a52057d148ef738152598d0b599948d4886d15a4a2f67d48ba1c681913428aa1" diff --git a/pyproject.toml b/pyproject.toml index b1358c77..b68fd696 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,6 +16,7 @@ google-cloud-secret-manager = "^2.16.3" pydantic-settings = "^2.0.3" pymupdf = "^1.23.3" pydantic = "^2.4.2" +pyhanko = "^0.20.1" [tool.poetry.group.dev.dependencies] From 64815424497b893071d9be3b29d3c8aecf1a6fd6 Mon Sep 17 00:00:00 2001 From: Benjamin Dornel Date: Wed, 11 Oct 2023 00:03:16 +0800 Subject: [PATCH 2/3] refactor(john): allow script to print to terminal when called --- monopoly/helpers/pdf2john.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/monopoly/helpers/pdf2john.py b/monopoly/helpers/pdf2john.py index 20851f25..b237378b 100644 --- a/monopoly/helpers/pdf2john.py +++ b/monopoly/helpers/pdf2john.py @@ -87,6 +87,7 @@ def get_passwords(self): extractor = PdfHashExtractor(filename) try: - extractor.parse() + result = extractor.parse() + print(result) except RuntimeError as e: logger.error(f"{filename} : {str(e)}") From d2bdad5eab2b75c7da447a66c15edb5a73e5c536 Mon Sep 17 00:00:00 2001 From: Benjamin Dornel Date: Wed, 11 Oct 2023 00:04:47 +0800 Subject: [PATCH 3/3] refactor(john): rename pdf2john to pdf_hash_extractor --- monopoly/helpers/{pdf2john.py => pdf_hash_extractor.py} | 0 monopoly/pdf.py | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename monopoly/helpers/{pdf2john.py => pdf_hash_extractor.py} (100%) diff --git a/monopoly/helpers/pdf2john.py b/monopoly/helpers/pdf_hash_extractor.py similarity index 100% rename from monopoly/helpers/pdf2john.py rename to monopoly/helpers/pdf_hash_extractor.py diff --git a/monopoly/pdf.py b/monopoly/pdf.py index 24147c20..308fd40a 100644 --- a/monopoly/pdf.py +++ b/monopoly/pdf.py @@ -7,7 +7,7 @@ from PIL import Image from monopoly.config import PdfConfig -from monopoly.helpers.pdf2john import PdfHashExtractor +from monopoly.helpers.pdf_hash_extractor import PdfHashExtractor logger = logging.getLogger(__name__)