Naresh Kumar Nagwani

66 papers Journal 57Unranked 9
YearRankTypeTitle / Venue / Authors
2025 J jnl
Appl. Intell.
Deepak Suresh Asudani, Naresh Kumar Nagwani, Pradeep Singh
2025 J jnl
J. Supercomput.
Aditi Bajpai, Sonal Yadav, Naresh Kumar Nagwani
2025 J jnl
Eng. Appl. Artif. Intell.
Rahul Shrivastava, Dilip Singh Sisodia, Naresh Kumar Nagwani
2025 J jnl
Kybernetes
Rahul Shrivastava, Dilip Singh Sisodia, Naresh Kumar Nagwani
2025 J jnl
Multim. Tools Appl.
Saurabh Agrawal, Dilip Singh Sisodia, Naresh Kumar Nagwani
2025 J jnl
Inf. Sci.
Rahul Shrivastava, Dilip Singh Sisodia, Naresh Kumar Nagwani
2025 J jnl
Int. J. Adv. Intell. Paradigms
Tirath Prasad Sahu, Naresh Kumar Nagwani, Shrish Verma
2024 J jnl
Multim. Tools Appl.
Deepak Suresh Asudani, Naresh Kumar Nagwani, Pradeep Singh
2024 J jnl
Multim. Tools Appl.
Supriya Gupta, Aakanksha Sharaff, Naresh Kumar Nagwani
2024 J jnl
Multim. Tools Appl.
Supriya Gupta, Aakanksha Sharaff, Naresh Kumar Nagwani
2024 J jnl
Knowl. Inf. Syst.
Rahul Shrivastava, Dilip Singh Sisodia, Naresh Kumar Nagwani
2024 J jnl
Int. J. Comput. Sci. Eng.
Rama Ranjan Panda, Naresh Kumar Nagwani
2024 J jnl
Inf. Process. Manag.
Rahul Shrivastava, Dilip Singh Sisodia, Naresh Kumar Nagwani
2024 conf
OCIT
Rama Ranjan Panda, Naresh Kumar Nagwani
2024 J jnl
Multim. Tools Appl.
Supriya Gupta, Aakanksha Sharaff, Naresh Kumar Nagwani
2024 J jnl
Knowl. Inf. Syst.
Rama Ranjan Panda, Naresh Kumar Nagwani
2024 J jnl
Appl. Soft Comput.
Rama Ranjan Panda, Naresh Kumar Nagwani
2023 conf
ICCCNT
Ravindra Kumar Chouhan, Mithilesh Atulkar, Naresh Kumar Nagwani
2023 J jnl
Appl. Intell.
Ravindra Kumar Chouhan, Mithilesh Atulkar, Naresh Kumar Nagwani
2023 J jnl
Data Technol. Appl.
Riju Bhattacharya, Naresh Kumar Nagwani, Sarsij Tripathi
2023 J jnl
Int. J. Cloud Appl. Comput.
Kamlesh Lakhwani, Gajanand Sharma, Ramandeep Sandhu, Naresh Kumar Nagwani, Sandeep Bhargava, Varsha Arya, Ammar Almomani
2023 J jnl
Int. J. Inf. Manag. Data Insights
Naresh Kumar Nagwani, Jasjit S. Suri
2023 J jnl
Eng. Appl. Artif. Intell.
Rama Ranjan Panda, Naresh Kumar Nagwani
2023 J jnl
Data Technol. Appl.
Riju Bhattacharya, Naresh Kumar Nagwani, Sarsij Tripathi
2023 J jnl
Expert Syst. Appl.
Rahul Shrivastava, Dilip Singh Sisodia, Naresh Kumar Nagwani
2023 J jnl
J. Supercomput.
Supriya Gupta, Aakanksha Sharaff, Naresh Kumar Nagwani
2023 J jnl
Comput. Syst. Sci. Eng.
Supriya Gupta, Aakanksha Sharaff, Naresh Kumar Nagwani
2023 J jnl
Artif. Intell. Rev.
Deepak Suresh Asudani, Naresh Kumar Nagwani, Pradeep Singh
2023 conf
OCIT
Rama Ranjan Panda, Naresh Kumar Nagwani
2022 J jnl
Pattern Recognit. Lett.
Rahul Shrivastava, Dilip Singh Sisodia, Naresh Kumar Nagwani, Upendra Roy BP
2022 J jnl
J. King Saud Univ. Comput. Inf. Sci.
Rama Ranjan Panda, Naresh Kumar Nagwani
2022 J jnl
Data Technol. Appl.
Deepak Suresh Asudani, Naresh Kumar Nagwani, Pradeep Singh
2022 J jnl
Expert Syst. Appl.
Saurabh Agrawal, Dilip Singh Sisodia, Naresh Kumar Nagwani
2022 J jnl
Softw. Impacts
Rama Ranjan Panda, Naresh Kumar Nagwani
2022 J jnl
Neural Comput. Appl.
Saurabh Agrawal, Dilip Singh Sisodia, Naresh Kumar Nagwani
2022 J jnl
Knowl. Inf. Syst.
Rama Ranjan Panda, Naresh Kumar Nagwani
2022 J jnl
Data Technol. Appl.
Rahul Shrivastava, Dilip Singh Sisodia, Naresh Kumar Nagwani
2021 J jnl
Int. J. Multim. Data Eng. Manag.
Riju Bhattacharya, Naresh Kumar Nagwani, Sarsij Tripathi
2021 J jnl
Medical Biol. Eng. Comput.
Saurabh Agrawal, Dilip Singh Sisodia, Naresh Kumar Nagwani
2021 J jnl
Int. J. Comput. Sci. Eng.
Rama Ranjan Panda, Naresh Kumar Nagwani
2020 conf
ICCCNT
Abhishek Dutta, Abhisek Nayak, Aditya, Rama Ranjan Panda, Naresh Kumar Nagwani
2020 J jnl
Int. J. Medical Eng. Informatics
Mridu Sahu, Shrish Verma, Naresh Kumar Nagwani, Sneha Shukla
2020 J jnl
Int. J. Web Based Learn. Teach. Technol.
Aakanksha Sharaff, Naresh Kumar Nagwani
2019 J jnl
J. Inf. Sci.
Abhishek K. Singh, Naresh Kumar Nagwani, Sudhakar Pandey
2019 conf
CSCloud/EdgeCom
Tirath Prasad Sahu, Reswanth Sai Thummalapudi, Naresh Kumar Nagwani
2019 J jnl
Int. J. Inf. Secur. Priv.
Abhishek K. Singh, Naresh Kumar Nagwani, Sudhakar Pandey
2018 conf
ICCBN
Samrudhi Mohdiwale, Tirath Prasad Sahu, Rahul Kumar Chaurasia, Naresh Kumar Nagwani, Shrish Verma
2018 J jnl
Data Technol. Appl.
Abhishek K. Singh, Naresh Kumar Nagwani, Sudhakar Pandey
2017 J jnl
Int. Arab J. Inf. Technol.
Naresh Kumar Nagwani
2017 J jnl
Int. J. Appl. Evol. Comput.
Aakanksha Sharaff, Naresh Kumar Nagwani
2017 J jnl
J. Inf. Sci.
Naresh Kumar Nagwani, Aakanksha Sharaff
2017 conf
MISNC
Abhishek K. Singh, Naresh Kumar Nagwani, Sudhakar Pandey
2016 J jnl
J. Inf. Sci.
Aakanksha Sharaff, Naresh Kumar Nagwani
2016 J jnl
IEEE Access
Abhishek K. Singh, Debasish Sena, Naresh Kumar Nagwani, Sudhakar Pandey
2016 J jnl
Int. J. Softw. Eng. Knowl. Eng.
Naresh Kumar Nagwani, Shrish Verma
2016 J jnl
IEEE Access
Tirath Prasad Sahu, Naresh Kumar Nagwani, Shrish Verma
2016 J jnl
IEEE Access
Tirath Prasad Sahu, Naresh Kumar Nagwani, Shrish Verma
2016 conf
COMPUTE
Tirath Prasad Sahu, Naresh Kumar Nagwani, Shrish Verma
2015 J jnl
IEEE Trans. Knowl. Data Eng.
Naresh Kumar Nagwani
2015 J jnl
J. Big Data
Naresh Kumar Nagwani
2014 J jnl
Int. J. Softw. Eng. Knowl. Eng.
Naresh Kumar Nagwani, Shrish Verma
2014 J jnl
CoRR
Sanjay Chakraborty, Naresh Kumar Nagwani
2014 J jnl
CoRR
Sanjay Chakraborty, Naresh Kumar Nagwani, Lopamudra Dey
2014 J jnl
CoRR
Sanjay Chakraborty, Naresh Kumar Nagwani
2014 J jnl
CoRR
Sanjay Chakraborty, Naresh Kumar Nagwani, Lopamudra Dey
2011 conf
HPAGC
Neeraj Kumar Sharma, Naresh Kumar Nagwani
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'
        }