Carlo Mereghetti

98 papers A 1B 5C 10Misc 1Journal 50Unranked 28
YearRankTypeTitle / Venue / Authors
2026 J jnl
Inf. Comput.
Martin Kutrib, Andreas Malcher, Carlo Mereghetti, Beatrice Palano, Priscilla Raucci, Matthias Wendlandt
2026 J jnl
Theor. Comput. Sci.
Martin Kutrib, Andreas Malcher, Carlo Mereghetti, Beatrice Palano, Priscilla Raucci, Matthias Wendlandt
2025 J jnl
Theor. Comput. Sci.
Caterina Feletti, Lucia Mambretti, Carlo Mereghetti, Beatrice Palano
2025 J jnl
Int. J. Found. Comput. Sci.
Carlo Mereghetti, Beatrice Palano, Priscilla Raucci
2025 conf
DCFS
Martin Kutrib, Andreas Malcher, Carlo Mereghetti, Beatrice Palano
2024 conf
SAND
Caterina Feletti, Lucia Mambretti, Carlo Mereghetti, Beatrice Palano
2024 J jnl
CoRR
Caterina Feletti, Lucia Mambretti, Carlo Mereghetti, Beatrice Palano
2024 C conf
DLT
Martin Kutrib, Andreas Malcher, Carlo Mereghetti, Beatrice Palano, Priscilla Raucci, Matthias Wendlandt
2024 C conf
CIAA
Martin Kutrib, Andreas Malcher, Carlo Mereghetti, Beatrice Palano, Priscilla Raucci, Matthias Wendlandt
2023 J jnl
J. Autom. Lang. Comb.
Martin Kutrib, Andreas Malcher, Carlo Mereghetti, Beatrice Palano
2023 J jnl
Theor. Comput. Sci.
Martin Kutrib, Andreas Malcher, Carlo Mereghetti, Beatrice Palano
2023 conf
NCMA
Carlo Mereghetti, Beatrice Palano, Priscilla Raucci
2023 B conf
OPODIS
Caterina Feletti, Carlo Mereghetti, Beatrice Palano
2022 J jnl
CoRR
Martin Kutrib, Andreas Malcher, Carlo Mereghetti, Beatrice Palano
2022 J jnl
Fundam. Informaticae
Martin Kutrib, Andreas Malcher, Carlo Mereghetti, Beatrice Palano
2022 J jnl
Inf. Comput.
Martin Kutrib, Andreas Malcher, Carlo Mereghetti, Beatrice Palano
2022 conf
ICTCS
Caterina Feletti, Carlo Mereghetti, Beatrice Palano, Priscilla Raucci
2021 J jnl
SIGACT News
Carlo Mereghetti, Beatrice Palano
2021 conf
ICTCS
Martin Kutrib, Andreas Malcher, Carlo Mereghetti, Beatrice Palano
2021 B conf
SOFSEM
Martin Kutrib, Andreas Malcher, Carlo Mereghetti, Beatrice Palano
2021 J jnl
Acta Informatica
Sebastian Jakobi, Katja Meckel, Carlo Mereghetti, Beatrice Palano
2020 C conf
CiE
Martin Kutrib, Andreas Malcher, Carlo Mereghetti, Beatrice Palano
2020 conf
DCFS
Martin Kutrib, Andreas Malcher, Carlo Mereghetti, Beatrice Palano
2020 J jnl
CoRR
Carlo Mereghetti, Beatrice Palano, Simone Cialdi, Valeria Vento, Matteo G. A. Paris, Stefano Olivares
2019 conf
DCFS
Martin Kutrib, Andreas Malcher, Carlo Mereghetti, Beatrice Palano
2019 conf
ICTCS
Martin Kutrib, Andreas Malcher, Carlo Mereghetti, Beatrice Palano
2018 C conf
SSS
Caterina Feletti, Carlo Mereghetti, Beatrice Palano
2017 J jnl
J. Comput. Syst. Sci.
Zuzana Bednárová, Viliam Geffert, Carlo Mereghetti, Beatrice Palano
2017 J jnl
Theor. Comput. Sci.
Maria Paola Bianchi, Carlo Mereghetti, Beatrice Palano
2015 J jnl
Theor. Comput. Sci.
Martin Kutrib, Andreas Malcher, Carlo Mereghetti, Beatrice Palano, Matthias Wendlandt
2015 J jnl
Int. J. Found. Comput. Sci.
Maria Paola Bianchi, Carlo Mereghetti, Beatrice Palano
2014 conf
Computing with New Resources
Maria Paola Bianchi, Carlo Mereghetti, Beatrice Palano
2014 C conf
CIAA
Maria Paola Bianchi, Carlo Mereghetti, Beatrice Palano
2014 J jnl
Inf. Comput.
Zuzana Bednárová, Viliam Geffert, Carlo Mereghetti, Beatrice Palano
2014 J jnl
Theor. Comput. Sci.
Maria Paola Bianchi, Carlo Mereghetti, Beatrice Palano
2013 conf
DCFS
Viliam Geffert, Andreas Malcher, Katja Meckel, Carlo Mereghetti, Beatrice Palano
2013 Misc conf
CSR
Viliam Geffert, Zuzana Bednárová, Carlo Mereghetti, Beatrice Palano
2013 C conf
CIAA
Martin Kutrib, Andreas Malcher, Carlo Mereghetti, Beatrice Palano, Matthias Wendlandt
2013 conf
DCFS
Sebastian Jakobi, Katja Meckel, Carlo Mereghetti, Beatrice Palano
2013 conf
UCNC
Maria Paola Bianchi, Carlo Mereghetti, Beatrice Palano
2012 conf
DCFS
Andreas Malcher, Katja Meckel, Carlo Mereghetti, Beatrice Palano
2012 J jnl
J. Autom. Lang. Comb.
Andreas Malcher, Katja Meckel, Carlo Mereghetti, Beatrice Palano
2012 J jnl
Theor. Comput. Sci.
Andreas Malcher, Carlo Mereghetti, Beatrice Palano
2012 J jnl
Acta Informatica
Christian Choffrut, Andreas Malcher, Carlo Mereghetti, Beatrice Palano
2012 J jnl
J. Autom. Lang. Comb.
Maria Paola Bianchi, Markus Holzer, Sebastian Jakobi, Carlo Mereghetti, Beatrice Palano, Giovanni Pighizzini
2012 conf
DCFS
Zuzana Bednárová, Viliam Geffert, Carlo Mereghetti, Beatrice Palano
2012 J jnl
RAIRO Theor. Informatics Appl.
Rudolf Freund, Markus Holzer, Carlo Mereghetti, Friedrich Otto, Beatrice Palano
2012 J jnl
Theor. Comput. Sci.
Zuzana Bednárová, Viliam Geffert, Carlo Mereghetti, Beatrice Palano
2011 conf
DCFS
Andreas Malcher, Carlo Mereghetti, Beatrice Palano
2011 J jnl
Fundam. Informaticae
Maria Paola Bianchi, Carlo Mereghetti, Beatrice Palano, Giovanni Pighizzini
2011 conf
DCFS
Zuzana Bednárová, Viliam Geffert, Carlo Mereghetti, Beatrice Palano
2011 ed.
NCMA
Rudolf Freund, Markus Holzer, Carlo Mereghetti, Friedrich Otto, Beatrice Palano
2010 J jnl
Inf. Comput.
Viliam Geffert, Carlo Mereghetti, Beatrice Palano
2010 C conf
LATA
Christian Choffrut, Andreas Malcher, Carlo Mereghetti, Beatrice Palano
2010 J jnl
Fundam. Informaticae
Viliam Geffert, Giovanni Pighizzini, Carlo Mereghetti
2010 conf
NCMA
Maria Paola Bianchi, Carlo Mereghetti, Beatrice Palano, Giovanni Pighizzini
2010 ch.
Scientific Applications of Language Methods
Carlo Mereghetti, Beatrice Palano
2010 J jnl
Int. J. Found. Comput. Sci.
Andreas Malcher, Carlo Mereghetti, Beatrice Palano
2010 J jnl
Nat. Comput.
Alberto Bertoni, Carlo Mereghetti, Beatrice Palano
2009 conf
ICTCS
Andreas Malcher, Carlo Mereghetti, Beatrice Palano
2009 conf
NCMA
Viliam Geffert, Carlo Mereghetti, Giovanni Pighizzini
2008 C conf
Developments in Language Theory
Viliam Geffert, Carlo Mereghetti, Beatrice Palano
2008 conf
Automata
Andreas Malcher, Carlo Mereghetti, Beatrice Palano
2008 conf
AFL
Andreas Malcher, Carlo Mereghetti, Beatrice Palano
2008 J jnl
Int. J. Found. Comput. Sci.
Carlo Mereghetti
2007 J jnl
Inf. Comput.
Viliam Geffert, Carlo Mereghetti, Giovanni Pighizzini
2007 J jnl
Theor. Comput. Sci.
Carlo Mereghetti, Beatrice Palano
2007 conf
DCFS
Carlo Mereghetti
2006 conf
DCFS
Carlo Mereghetti, Beatrice Palano
2006 J jnl
RAIRO Theor. Informatics Appl.
Carlo Mereghetti, Beatrice Palano
2006 J jnl
Theor. Comput. Sci.
Alberto Bertoni, Carlo Mereghetti, Beatrice Palano
2006 J jnl
J. Discrete Algorithms
Carlo Mereghetti, Beatrice Palano
2005 ed.
DCFS
Carlo Mereghetti, Beatrice Palano, Giovanni Pighizzini, Detlef Wotschke
2005 C conf
Developments in Language Theory
Viliam Geffert, Carlo Mereghetti, Giovanni Pighizzini
2005 J jnl
Theor. Comput. Sci.
Alberto Bertoni, Carlo Mereghetti, Beatrice Palano
2005 conf
DCFS
Alberto Bertoni, Carlo Mereghetti, Beatrice Palano
2003 J jnl
Theor. Comput. Sci.
Viliam Geffert, Carlo Mereghetti, Giovanni Pighizzini
2003 J jnl
Int. J. Found. Comput. Sci.
Alberto Bertoni, Carlo Mereghetti, Beatrice Palano
2003 conf
ICTCS
Alberto Bertoni, Carlo Mereghetti, Beatrice Palano
2003 C conf
Developments in Language Theory
Alberto Bertoni, Carlo Mereghetti, Beatrice Palano
2003 conf
Grammars and Automata for String Processing
Carlo Mereghetti, Giovanni Pighizzini
2002 J jnl
RAIRO Theor. Informatics Appl.
Carlo Mereghetti, Beatrice Palano
2002 J jnl
J. Autom. Lang. Comb.
Carlo Mereghetti, Beatrice Palano
2001 B conf
MFCS
Viliam Geffert, Carlo Mereghetti, Giovanni Pighizzini
2001 J jnl
RAIRO Theor. Informatics Appl.
Carlo Mereghetti, Beatrice Palano, Giovanni Pighizzini
2001 conf
DCFS
Carlo Mereghetti, Beatrice Palano, Giovanni Pighizzini
2001 J jnl
SIAM J. Comput.
Carlo Mereghetti, Giovanni Pighizzini
2001 J jnl
Discret. Math.
Ottavio M. D'Antona, Carlo Mereghetti, Fabio Zamparini
2001 conf
ICTCS
Carlo Mereghetti, Beatrice Palano
2000 J jnl
RAIRO Theor. Informatics Appl.
Carlo Mereghetti, Beatrice Palano
2000 J jnl
J. Autom. Lang. Comb.
Carlo Mereghetti, Giovanni Pighizzini
1998 A conf
STACS
Carlo Mereghetti, Giovanni Pighizzini
1998 J jnl
SIAM J. Comput.
Viliam Geffert, Carlo Mereghetti, Giovanni Pighizzini
1995 J jnl
Inf. Process. Lett.
Carlo Mereghetti, Giovanni Pighizzini
1995 B conf
MFCS
Alberto Bertoni, Carlo Mereghetti, Giovanni Pighizzini
1994 J jnl
Inf. Process. Lett.
Alberto Bertoni, Carlo Mereghetti, Giovanni Pighizzini
1994 J jnl
Inf. Process. Lett.
Alberto Bertoni, Carlo Mereghetti, Giovanni Pighizzini
1994 B conf
MFCS
Alberto Bertoni, Carlo Mereghetti, Giovanni Pighizzini
redb/extractors/pe_extractors/pe_signature.py
← Index redb/extractors/pe_extractors/pe_signature.py python
import inspect
import yara_x
from datetime import datetime, timezone
from signify.authenticode import SignedPEFile
from typing import Any, Dict, List, Tuple

from redb.extractors.enum import Tag
from redb.extractors.pe_extractor import PEExtractor
from redb.models.dataclasses import PECertificate, PESigner, PECodeSigningInfo


class PESignatureExtractor(PEExtractor):
    """
    RFC 3161 - Internet X.509 Public Key Infrastructure Time-Stamp Protocol (TSP)
    Section 2.4.2 defines the TSTInfo structure.
    https://tools.ietf.org/html/rfc3161#section-2.4.2

    Microsoft Authenticode Time Stamping Specification
    https://download.microsoft.com/download/9/c/5/9c5b2167-8017-4bae-9fde-d599bac8184a/Authenticode_PE.docx
    """

    def __init__(
        self,
        filepath,
        log,
        exporters=None,
        index_prefix=None,
        elastic_index=None,
        known_benign=False,
        known_malicious=False,
        pe=None,
    ):
        super().__init__(
            filepath,
            log,
            exporters,
            index_prefix,
            elastic_index,
            known_benign,
            known_malicious,
            pe,
        )
        self.elastic_index = self.index_prefix + "-pe_signature"
        self.log.debug(inspect.currentframe().f_code.co_name)
        self.code_signing_info = None

    def tag(self):
        return [Tag.PE_CERTIFICATE.value, Tag.PE_SIGNER.value, Tag.PE_SIGNATURE.value]

    def _extract_certificate_info(self, certificate):
        self.log.debug(inspect.currentframe().f_code.co_name)

        # YARA-X returns datetime objects directly, not Unix timestamps
        not_before = certificate["not_before"]
        not_after = certificate["not_after"]

        # Handle both datetime objects and Unix timestamps for compatibility
        if isinstance(not_before, datetime):
            valid_from = not_before.strftime("%Y-%m-%d %H:%M:%S")
        else:
            valid_from = datetime.fromtimestamp(int(not_before), timezone.utc).strftime("%Y-%m-%d %H:%M:%S")

        if isinstance(not_after, datetime):
            valid_to = not_after.strftime("%Y-%m-%d %H:%M:%S")
        else:
            valid_to = datetime.fromtimestamp(int(not_after), timezone.utc).strftime("%Y-%m-%d %H:%M:%S")

        return PECertificate(
            certificate_serial_number=certificate["serial"],
            certificate_subject=certificate["subject"],
            certificate_issuer=certificate["issuer"],
            certificate_valid_from=valid_from,
            certificate_valid_to=valid_to,
            certificate_thumbprint=certificate["thumbprint"].upper(),
            certificate_algorithm=certificate["algorithm"],
        )

    def _extract_signer_info(self, signer):
        self.log.debug(inspect.currentframe().f_code.co_name)

        # YARA-X returns datetime objects directly, not Unix timestamps
        not_before = signer["not_before"]
        not_after = signer["not_after"]

        # Handle both datetime objects and Unix timestamps for compatibility
        if isinstance(not_before, datetime):
            valid_from = not_before.strftime("%Y-%m-%d %H:%M:%S")
        else:
            valid_from = datetime.fromtimestamp(int(not_before), timezone.utc).strftime("%Y-%m-%d %H:%M:%S")

        if isinstance(not_after, datetime):
            valid_to = not_after.strftime("%Y-%m-%d %H:%M:%S")
        else:
            valid_to = datetime.fromtimestamp(int(not_after), timezone.utc).strftime("%Y-%m-%d %H:%M:%S")

        return PESigner(
            signer_serial_number=signer["serial"],
            signer_subject=signer["subject"],
            signer_issuer=signer["issuer"],
            signer_valid_from=valid_from,
            signer_valid_to=valid_to,
            signer_thumbprint=signer["thumbprint"].upper(),
            signer_algorithm=signer["algorithm"],
        )

    def _extract_signature_info(self):
        self.log.debug(inspect.currentframe().f_code.co_name)
        pe_rules = """
            import "pe"
            rule is_pe {
                condition: 
                    pe.is_pe
            }
        """
        rule = yara_x.compile(pe_rules)
        results = rule.scan(self.binary)
        yara_output = results.module_outputs

        signature_info = yara_output["pe"]["signatures"][0]
        number_of_certificates = signature_info["number_of_certificates"]
        signature_verified = signature_info["verified"]
        self.code_signing_info = PECodeSigningInfo(
            _id=self.sha256,
            signature_verified=signature_verified,
            number_of_certificates=int(number_of_certificates),
        )

        keys = signature_info.keys()
        if "certificates" in keys:
            self.log.debug("Extracting PE Signing Certificates")
            certificates = signature_info["certificates"]
            certificates_list = []
            for cert in certificates:
                cert_info = self._extract_certificate_info(cert)
                certificates_list.append(cert_info)
            self.code_signing_info.x509_certificates = certificates_list

        if "signer_info" in keys:
            self.log.debug("Extracting PE Signing Signer Info")
            signers = signature_info["signer_info"]["chain"]
            signers_list = []
            for signer in signers:
                sig = self._extract_signer_info(signer)
                signers_list.append(sig)
            self.code_signing_info.signers = signers_list

        if "countersignatures" in keys:
            self.log.debug("Extracting PE Signing Countersignatures")
            countersignatures = signature_info["countersignatures"][0]["chain"]
            countersigners_list = []
            for csigner in countersignatures:
                csig = self._extract_signer_info(csigner)
                countersigners_list.append(csig)
            self.code_signing_info.countersigners = countersigners_list

        with open(self.filepath, "rb") as f:
            self.log.debug("Extracting PE Signing spcSpOpusInfo")
            sig_pefile = SignedPEFile(f)
            try:
                spc_opusinfo = {}
                for signed_data in sig_pefile.signed_datas:
                    spc_opusinfo["ProgramName"] = signed_data.signer_info.program_name
                    spc_opusinfo["MoreInfo"] = signed_data.signer_info.more_info
                    self.code_signing_info.spcSpOpusInfo = spc_opusinfo

                    if signed_data.signer_info.countersigner is not None:
                        stime = signed_data.signer_info.countersigner.signing_time
                        self.code_signing_info.date_signed = stime.strftime(
                            "%Y-%m-%d %H:%M:%S"
                        )
            except Exception as e:
                self.log.error(
                    f"Error while extracting spcSpOpusInfo or signing date: {e}"
                )

    def extract(self):
        try:
            self.log.debug(inspect.currentframe().f_code.co_name)
            if self._is_signed():
                self._extract_signature_info()
                # self.export_to_elastic([self.code_signing_info])
                return self.code_signing_info
            return None
        except Exception as e:
            self.log.error(f"Error extracting PE Signature: {e}")
            return None

    # def prepare_export_data(self, exporter_type: str) -> Any:
    #     self.log.debug(inspect.currentframe().f_code.co_name)
    #     if exporter_type == "ElasticsearchExporter":
    #         return self.extract()
    #     elif exporter_type == "ClickHouseExporter":
    #         signing_info = self.extract()
    #         if signing_info is None:
    #             return None
                
    #         current_time = datetime.now(timezone.utc)
            
    #         # Prepare data for redb_pe_signatures table
    #         signatures_data = [[
    #             self.sha256,                                    # sha256
    #             self.md5,                                       # md5
    #             self.sha1,                                      # sha1
    #             signing_info.signature_verified,                # signature_verified
    #             datetime.strptime(signing_info.date_signed, "%Y-%m-%d %H:%M:%S") if signing_info.date_signed else None,  # date_signed
    #             signing_info.number_of_certificates,            # number_of_certificates
    #             signing_info.spcSpOpusInfo.get('ProgramName', None) if signing_info.spcSpOpusInfo else None,  # program_name
    #             signing_info.spcSpOpusInfo.get('MoreInfo', None) if signing_info.spcSpOpusInfo else None,    # more_info
    #             current_time                                    # analysis_date
    #         ]]

    #         certificates_data = []
            
    #         # Process signers
    #         if signing_info.signers:
    #             for signer in signing_info.signers:
    #                 certificates_data.append(self._prepare_certificate_data(signer, 'signer', current_time))
            
    #         # Process countersigners
    #         if signing_info.countersigners:
    #             for csigner in signing_info.countersigners:
    #                 certificates_data.append(self._prepare_certificate_data(csigner, 'countersigner', current_time))
            
    #         # Process x509 certificates
    #         if signing_info.x509_certificates:
    #             for cert in signing_info.x509_certificates:
    #                 certificates_data.append(self._prepare_certificate_data(cert, 'chain', current_time))
            
    #         return {
    #             'multi_table': True,
    #             'signatures': {
    #                 'table': 'redb_pe_signatures',
    #                 'data': signatures_data,
    #                 'column_names': [
    #                     'sha256', 'md5', 'sha1', 'signature_verified', 'date_signed',
    #                     'number_of_certificates', 'spcSpOpusInfo_program_name', 'spcSpOpusInfo_more_info', 'analysis_date'
    #                 ],
    #                 'column_type_names': [
    #                     'FixedString(64)', 'FixedString(32)', 'FixedString(40)',
    #                     'Boolean', 'DateTime64(3, \'UTC\')', 'UInt8',
    #                     'Nullable(String)', 'Nullable(String)', 'DateTime64(3, \'UTC\')'
    #                 ]
    #             },
    #             'certificates': {
    #                 'table': 'redb_pe_certificates',
    #                 'data': certificates_data,
    #                 'column_names': [
    #                     'sha256', 'md5', 'sha1', 'certificate_type', 'certificate_algorithm',
    #                     'certificate_issuer', 'certificate_subject', 'certificate_serial_number',
    #                     'certificate_thumbprint', 'certificate_valid_from', 'certificate_valid_to',
    #                     'analysis_date'
    #                 ],
    #                 'column_type_names': [
    #                     'FixedString(64)', 'FixedString(32)', 'FixedString(40)',
    #                     'Enum(\'signer\', \'countersigner\', \'chain\')', 'LowCardinality(String)',
    #                     'LowCardinality(String)', 'LowCardinality(String)', 'String',
    #                     'String', 'DateTime64(3, \'UTC\')', 'DateTime64(3, \'UTC\')',
    #                     'DateTime64(3, \'UTC\')'
    #                 ]
    #             }
    #         }

    # def _prepare_certificate_data(self, cert, cert_type: str, analysis_time: datetime) -> List:
    #     """Helper method to prepare certificate data for ClickHouse"""
    #     self.log.debug(inspect.currentframe().f_code.co_name)
    #     prefix = "certificate_" if hasattr(cert, "certificate_algorithm") else "signer_"
        
    #     # Get serial number and clean it up
    #     serial_number = getattr(cert, f"{prefix}serial_number")
    #     if serial_number:
    #         serial_number = serial_number.replace(':', '')
        
    #     return [
    #         self.sha256,                          # sha256
    #         self.md5,                             # md5
    #         self.sha1,                            # sha1
    #         cert_type,                            # certificate_type
    #         getattr(cert, f"{prefix}algorithm"),   # certificate_algorithm
    #         getattr(cert, f"{prefix}issuer"),     # certificate_issuer
    #         getattr(cert, f"{prefix}subject"),    # certificate_subject
    #         serial_number,                        # certificate_serial_number
    #         getattr(cert, f"{prefix}thumbprint"),  # certificate_thumbprint
    #         datetime.strptime(getattr(cert, f"{prefix}valid_from"), "%Y-%m-%d %H:%M:%S"),  # certificate_valid_from
    #         datetime.strptime(getattr(cert, f"{prefix}valid_to"), "%Y-%m-%d %H:%M:%S"),    # certificate_valid_to
    #         analysis_time                         # analysis_date
    #     ]
    def prepare_export_data(self, exporter_type: str) -> Any:
        self.log.debug(inspect.currentframe().f_code.co_name)
        if exporter_type == "ElasticsearchExporter":
            return self.extract()
        elif exporter_type == "ClickHouseExporter":
            signing_info = self.extract()
            if signing_info is None:
                return None
                
            current_time = datetime.now(timezone.utc)
            
            # Prepare data for redb_pe_signatures table
            signatures_data = [[
                self.sha256,                                    # sha256
                self.md5,                                       # md5
                self.sha1,                                      # sha1
                signing_info.signature_verified,                # signature_verified
                datetime.strptime(signing_info.date_signed, "%Y-%m-%d %H:%M:%S") if signing_info.date_signed else None,  # date_signed
                signing_info.number_of_certificates,            # number_of_certificates
                signing_info.spcSpOpusInfo.get('ProgramName', None) if signing_info.spcSpOpusInfo else None,  # program_name
                signing_info.spcSpOpusInfo.get('MoreInfo', None) if signing_info.spcSpOpusInfo else None,    # more_info
                current_time                                    # analysis_date
            ]]

            # Prepare data for redb_pe_certificates table
            certificates_data = []
            
            # Process signers
            if signing_info.signers:
                for signer in signing_info.signers:
                    certificates_data.append(self._prepare_certificate_data(signer, 'signer', current_time))
            
            # Process countersigners
            if signing_info.countersigners:
                for csigner in signing_info.countersigners:
                    certificates_data.append(self._prepare_certificate_data(csigner, 'countersigner', current_time))
            
            # Process x509 certificates
            if signing_info.x509_certificates:
                for cert in signing_info.x509_certificates:
                    certificates_data.append(self._prepare_certificate_data(cert, 'chain', current_time))
            
            return {
                'multi_table': True,
                'signatures': {
                    'table': 'redb_pe_signatures',
                    'data': signatures_data,
                    'column_names': [
                        'sha256', 'md5', 'sha1', 'signature_verified', 'date_signed',
                        'number_of_certificates', 'spcSpOpusInfo_program_name', 'spcSpOpusInfo_more_info', 'analysis_date'
                    ],
                    'column_type_names': [
                        'FixedString(64)', 'FixedString(32)', 'FixedString(40)',
                        'Boolean', 'DateTime64(3, \'UTC\')', 'UInt8',
                        'Nullable(String)', 'Nullable(String)', 'DateTime64(3, \'UTC\')'
                    ]
                },
                'certificates': {
                    'table': 'redb_pe_certificates',
                    'data': certificates_data,
                    'column_names': [
                        'sha256', 'md5', 'sha1', 'certificate_type', 'certificate_algorithm',
                        'certificate_issuer', 'certificate_subject', 'certificate_serial_number',
                        'certificate_thumbprint', 'certificate_valid_from', 'certificate_valid_to',
                        'analysis_date'
                    ],
                    'column_type_names': [
                        'FixedString(64)', 'FixedString(32)', 'FixedString(40)',
                        'Enum8(\'signer\' = 1, \'countersigner\' = 2, \'chain\' = 3)', 'LowCardinality(String)',
                        'LowCardinality(String)', 'LowCardinality(String)', 'String',
                        'String', 'DateTime64(3, \'UTC\')', 'DateTime64(3, \'UTC\')',
                        'DateTime64(3, \'UTC\')'
                    ]
                }
            }

    # def _prepare_certificate_data(self, cert, cert_type: str, analysis_time: datetime) -> List:
    #     """Helper method to prepare certificate data for ClickHouse"""
    #     self.log.debug(inspect.currentframe().f_code.co_name)
    #     prefix = "certificate_" if hasattr(cert, "certificate_algorithm") else "signer_"
        
    #     # Get serial number and clean it up - with strict handling
    #     serial_number = getattr(cert, f"{prefix}serial_number", "UNKNOWN")
    #     if not serial_number or not str(serial_number).strip():
    #         serial_number = "UNKNOWN"
    #     else:
    #         serial_number = serial_number.replace(':', '')
    #         if not serial_number.strip():  # Double check after cleaning
    #             serial_number = "UNKNOWN"
        
    #     return [
    #         self.sha256,                          # sha256
    #         self.md5,                             # md5
    #         self.sha1,                            # sha1
    #         cert_type,                            # certificate_type
    #         getattr(cert, f"{prefix}algorithm"),   # certificate_algorithm
    #         getattr(cert, f"{prefix}issuer"),     # certificate_issuer
    #         getattr(cert, f"{prefix}subject"),    # certificate_subject
    #         serial_number,                        # certificate_serial_number
    #         getattr(cert, f"{prefix}thumbprint"),  # certificate_thumbprint
    #         datetime.strptime(getattr(cert, f"{prefix}valid_from"), "%Y-%m-%d %H:%M:%S"),  # certificate_valid_from
    #         datetime.strptime(getattr(cert, f"{prefix}valid_to"), "%Y-%m-%d %H:%M:%S"),    # certificate_valid_to
    #         analysis_time                         # analysis_date
    #     ]

    def _prepare_certificate_data(self, cert, cert_type: str, analysis_time: datetime) -> List:
        """Helper method to prepare certificate data for ClickHouse"""
        self.log.debug(inspect.currentframe().f_code.co_name)
        prefix = "certificate_" if hasattr(cert, "certificate_algorithm") else "signer_"
        
        def clean_string(value, field_name):
            if value is None or (isinstance(value, str) and not value.strip()):
                self.log.warning(f"Empty or None value found for {field_name}")
                return "UNKNOWN"
            return str(value).strip()
        
        try:
            serial_number = getattr(cert, f"{prefix}serial_number", "UNKNOWN")
            serial_number = clean_string(serial_number, "serial_number")
            if serial_number != "UNKNOWN":
                serial_number = serial_number.replace(':', '')
        
            return [
                clean_string(self.sha256, "sha256"),
                clean_string(self.md5, "md5"),
                clean_string(self.sha1, "sha1"),
                cert_type,
                clean_string(getattr(cert, f"{prefix}algorithm"), "algorithm"),
                clean_string(getattr(cert, f"{prefix}issuer"), "issuer"),
                clean_string(getattr(cert, f"{prefix}subject"), "subject"),
                serial_number,
                clean_string(getattr(cert, f"{prefix}thumbprint"), "thumbprint"),
                datetime.strptime(getattr(cert, f"{prefix}valid_from"), "%Y-%m-%d %H:%M:%S"),
                datetime.strptime(getattr(cert, f"{prefix}valid_to"), "%Y-%m-%d %H:%M:%S"),
                analysis_time
            ]
        except Exception as e:
            self.log.error(f"Error preparing certificate data: {str(e)}")
            self.log.error(f"Certificate data that caused error: {cert}")
            raise

    def get_clickhouse_table(self) -> str:
        """Required by PEExtractor abstract base class"""
        return "redb_pe_signatures"  # Return the primary table

    def get_clickhouse_tables(self) -> Dict[str, str]:
        """Additional method for multi-table support"""
        return {
            'signatures': 'redb_pe_signatures',
            'certificates': 'redb_pe_certificates'
        }