def sign(self, datau, session, cert, cert_value, algomd, sig_attributes, timestamp): log.info('get certificate in format x509 to build signer attributes') x509 = Certificate.load(cert_value) sign_name = sig_attributes['position']['signature_name'] if sign_name == "": sign_name = MyConfigLoader().get_pdf_config()['position']['signatureName'] dct = { b'sigflags': 3, b'name': b'%b' % x509.subject.native['common_name'].encode(), b'signingdate': b'%b' % timestamp.encode(), b'sign_name': sign_name.encode() } # Variabile segnaposto per i bytes che conterranno il file firmato riferimenti della firma zeros = self.aligned(b'\0') log.info('start building the new pdf') try: pdfdata2 = self.makepdf(datau, dct, zeros, sig_attributes) log.info('pdf generated correctly') except PDFLinearizedError as e: raise PDFLinearizedError(e) except Exception: raise PDFCreationError('Exception on creating pdf') log.info('preparing data to be signed') startxref = len(datau) pdfbr1 = pdfdata2.find(zeros) pdfbr2 = pdfbr1 + len(zeros) br = [0, startxref + pdfbr1 - 1, startxref + pdfbr2 + 1, len(pdfdata2) - pdfbr2 - 1] brfrom = b'[0000000000 0000000000 0000000000 0000000000]' brto = b'[%010d %010d %010d %010d]' % tuple(br) pdfdata2 = pdfdata2.replace(brfrom, brto, 1) b1 = pdfdata2[:br[1] - startxref] b2 = pdfdata2[br[2] - startxref:] md = session.digestSession(Mechanism(LowLevel.CKM_SHA256)) md.update(datau) md.update(b1) md.update(b2) md = bytes(md.final()) log.info('start pdf signing') try: contents = pdf_signer.sign(None, session, cert, cert_value, algomd, True, md) contents = self.aligned(contents) pdfdata2 = pdfdata2.replace(zeros, contents, 1) log.info('pdf signed') except Exception: raise PDFSigningError('error in the sign procedure') return pdfdata2
def makepdf(self, pdfdata1, udct, zeros, sig_attributes): parser = PDFParser(BytesIO(pdfdata1)) document = PDFDocument(parser, fallback=False) log.info('get datas from pdf') prev = document.find_xref(parser) info = document.xrefs[0].trailer['Info'].objid root = document.xrefs[0].trailer['Root'].objid size = document.xrefs[0].trailer['Size'] page_objid = document.catalog['Pages'].objid page = None log.info('check sig attributes...') position = MyConfigLoader().get_pdf_config()['position'] if not sig_attributes: visibility = MyConfigLoader().get_pdf_config()['visibility'] else: visibility = sig_attributes['visibility'] log.info(f'the sign is {visibility}') if visibility == 'visible': position = sig_attributes['position'] log.info(f'position: {position}') page_pos = position['page'] if page_pos == 'n': try: pages_count = document.getobj(page_objid)['Count'] page = document.getobj(page_objid)['Kids'][pages_count - 1].objid except Exception: page = int(1) else: try: page = document.getobj(page_objid)['Kids'][int(page_pos) - 1].objid except Exception: log.error('page not found...take the first') page = document.getobj(page_objid)['Kids'][0].objid infodata = self.getdata(pdfdata1, info, prev, document).strip() rootdata = self.getdata(pdfdata1, root, prev, document).strip() pagedata = self.getdata(pdfdata1, page, prev, document).strip() no = size multiple_signs = False signatures = self.get_signature_names(document) if len(signatures) > 0: multiple_signs = True if visibility == 'visible': rect_array = self.get_rect_array(pagedata, position) stream_name = compress(STREAM_WITH_NAME % udct[b'name']) if multiple_signs: objs = self.make_multi_visible_sig_objs(document, udct, no, page, pagedata, infodata, rootdata, stream_name, rect_array, zeros) xref = self.make_multi_visible_xref() new_size = 11 else: objs = self.make_visible_sig_objs(udct, no, page, pagedata, infodata, rootdata, stream_name, rect_array, zeros) xref = self.make_visible_xref() new_size = 13 else: if multiple_signs: objs = self.make_multi_inv_sig_objs(document, udct, no, page, pagedata, infodata, rootdata, zeros, len(signatures) + 1) xref = self.make_multi_inv_xref() new_size = 5 else: objs = self.make_invisible_sig_objs(udct, no, page, pagedata, infodata, rootdata, zeros) xref = self.make_multi_inv_xref() new_size = 5 pdfdata2 = b''.join(objs) startxref = len(pdfdata1) dct = { b'page': page, b'no': no, b'startxref': startxref + len(pdfdata2), b'prev': prev, b'info': no + 0, b'root': no + 1, b'size': no + new_size, b'p0': startxref + pdfdata2.find(b'\n%d 0 obj\n' % page) + 1, b'h1': hashlib.md5(pdfdata1).hexdigest().upper().encode('ascii'), b'h2': hashlib.md5(pdfdata2).hexdigest().upper().encode('ascii'), } for i in range(new_size): dct.update(({b'n%d' % i: startxref + pdfdata2.find(b'\n%d 0 obj\n' % (no + i)) + 1, })) trailer = b'''\ trailer <</ID [<%(h1)s><%(h2)s>]/Info %(info)d 0 R/Prev %(prev)d/Root %(root)d 0 R/Size %(size)d>>\n\ startxref\n\ %(startxref)d\n\ %%%%EOF\n\ ''' xref = xref % dct trailer = trailer % dct pdfdata2 = pdfdata2 + xref + trailer return pdfdata2
from my_config_loader import MyConfigLoader from my_logger import MyLogger from os import listdir, devnull, fsdecode from PyKCS11 import PyKCS11Lib, Mechanism, LowLevel from asn1crypto.x509 import Certificate #################################################################### # CONFIGURATION # #################################################################### # driver directory DRIVER_FOLDER = MyConfigLoader().get_server_config()["driver_folder"] #################################################################### log = MyLogger().my_logger() # custom exceptions class SmartCardConnectionError(ConnectionError): """ Raised when something goes wrong with the smart card """ pass class SignatureUtils: @staticmethod def fetch_smart_card_sessions(): """ Return a `session` list for the connected smart cards """ log.info("loading drivers") pkcs11 = PyKCS11Lib() driver_loaded = False # try with default
def handle_sign(start_params): """Metodo principale. Effettua il parsing dei parametri contenuti nell'URL lanciato dalla web application, recupero dei parametri, controllo degli aggiornamenti e avvio processo di firma. :param start_params: È l'URL completo aperto nel browser :type start_params: str """ if start_params.__len__() == 0: start_params = get_sign_resume() else: start_params = start_params[0] if start_params is None: return error_response(SignStatus.ERROR.value, "No file to sign or empty array params") log.info("Parameters from protocol = %s" % start_params) tolkien_list = start_params.rsplit(";", maxsplit=1) token = tolkien_list[0].lstrip(PROTOCOL) log.info("Token: %s" % token) rev_url_encoded = tolkien_list[1] rev_url_encoded = rev_url_encoded.rstrip('/') rev_url = b64decode(rev_url_encoded).decode("utf-8").rstrip('/') + '/' log.info("Revocation Url: %s" % rev_url) # Check for upload and signed folder if not path.exists(UPLOAD_FOLDER) or not path.isdir(UPLOAD_FOLDER): makedirs(UPLOAD_FOLDER) if not path.exists(SIGNED_FOLDER) or not path.isdir(SIGNED_FOLDER): makedirs(SIGNED_FOLDER) # remove proxy if disabled enable_proxy = MyConfigLoader().get_server_config()["enable_proxy"] if enable_proxy is False: log.info("proxy setting is disabled") if "HTTP_PROXY" in environ: del environ["HTTP_PROXY"] if "HTTPS_PROXY" in environ: del environ["HTTPS_PROXY"] log.info("getting paramaters...") try: r = get(rev_url + token) if r.status_code == 200: signature_params = r.json() log.info("parameters found: %s" % signature_params) # checking for client updates update_checker_url = signature_params["update_checker_url"] status_update = updates_manager(start_params, update_checker_url) log.info(status_update) log.info("signing...") master_document_id = "" if "masterDocumentId" in signature_params: master_document_id = signature_params["masterDocumentId"] end_sign_manager_url = signature_params['params'][ 'endSignManagerUrl'] result_channel = signature_params['params']['resultChannel'] if enable_proxy is False: if "NO_PROXY" in environ: environ["NO_PROXY"] += ";*" + urlparse( end_sign_manager_url).netloc + "*" sign_result = sign(signature_params) # chiamare la endSignServletHere response_maker(end_sign_manager_url, result_channel, sign_result, master_document_id) else: log.error(r.status_code) show_warning_message( "Errore durante il reperimento dei dati per la firma. " "Riprovare o contattare il servizio di assistenza.") except ConnectionError as conn_err: log.error(conn_err) show_warning_message( "Impossibile stabilire una connessione con il server. Contattare l'assistenza." ) except Exception as err: log.error("error: %s", err) show_warning_message("Errore, contattare il servizio di assistenza.")
from my_logger import MyLogger from os import path, remove, sys, listdir, makedirs, environ from requests import post, get from revocation_checker import RevocationChecker from shutil import move from tkinter import Tk, Entry, Label, Button, Frame, messagebox, LEFT from traceback import extract_tb from urllib.parse import urlparse from update_checker import check_for_updates, run_updates, UPDATE_STATUS_STR, UpdateStatus from enum import Enum #################################################################### # CONFIGURATION # #################################################################### # url HOST = MyConfigLoader().get_server_config()["host"] PORT = MyConfigLoader().get_server_config()["port"] PROTOCOL = MyConfigLoader().get_server_config()["protocol"] # mapped directories # TEMPLATE_FOLDER = MyConfigLoader().get_server_config()["template_folder"] UPLOAD_FOLDER = MyConfigLoader().get_server_config()["uploaded_file_folder"] SIGNED_FOLDER = MyConfigLoader().get_server_config()["signed_file_folder"] LOGS_FOLDER = MyConfigLoader().get_logger_config()["log_folder"] # Allowed signature types P7M = "p7m" PDF = "pdf" ALLOWED_SIGNATURE_TYPES = {P7M, PDF} # Memorized pin user_session = {} SESSION_TIMEOUT = MyConfigLoader().get_server_config()["pin_validity_time"] # Statuses
from my_config_loader import MyConfigLoader from my_logger import MyLogger from os import path, remove, sys, listdir, fsdecode, makedirs, environ from requests import post from shutil import move from tkinter import Tk, Entry, Label, Button, Frame from traceback import extract_tb from urllib import request as urlfile from werkzeug.utils import secure_filename from zipfile import ZipFile #################################################################### # CONFIGURATION # #################################################################### # url HOST = MyConfigLoader().get_server_config()["host"] PORT = MyConfigLoader().get_server_config()["port"] # mapped directories TEMPLATE_FOLDER = MyConfigLoader().get_server_config()["template_folder"] UPLOAD_FOLDER = MyConfigLoader().get_server_config()["uploaded_file_folder"] SIGNED_FOLDER = MyConfigLoader().get_server_config()["signed_file_folder"] LOGS_FOLDER = MyConfigLoader().get_logger_config()["log_folder"] # Allowed signature types P7M = "p7m" PDF = "pdf" ALLOWED_SIGNATURE_TYPES = set([P7M, PDF]) # Memorized pin memorized_pin = {} PIN_TIMEOUT = MyConfigLoader().get_server_config()["pin_validity_time"] ####################################################################
from logging import getLogger, INFO, Formatter from logging.handlers import RotatingFileHandler from my_config_loader import MyConfigLoader from os import path, mkdir from singleton_type import SingletonType #################################################################### # CONFIGURATION # #################################################################### LOGGER_NAME = "cicerone" LOGGING_FOLDER = MyConfigLoader().get_logger_config()["log_folder"] LOGGING_FILE = MyConfigLoader().get_logger_config()["log_file_name"] LOGGING_FILE_PATH = path.join(LOGGING_FOLDER, LOGGING_FILE) FILE_SIZE = MyConfigLoader().get_logger_config()["file_byte_size"] LOG_FILE_COUNT = MyConfigLoader().get_logger_config()["log_files_count"] #################################################################### class MyLogger(object, metaclass=SingletonType): _logger = None def __init__(self): if not path.isdir(LOGGING_FOLDER): mkdir(LOGGING_FOLDER) self._logger = getLogger(LOGGER_NAME) self._logger.setLevel(INFO) handler = RotatingFileHandler( LOGGING_FILE_PATH, maxBytes=FILE_SIZE, backupCount=LOG_FILE_COUNT)