Ramakrishna Mukkamala

51 papers B 1C 1Journal 35Unranked 13
YearRankTypeTitle / Venue / Authors
2026 J jnl
CoRR
Henry Crandall, Tyler Schuessler, Filip Belík, Albert Fabregas, Barry M. Stults, Alexandra Boyadzhiev, Huanan Zhang, Jim S. Wu, Aylin R. Rodan, Stephen P. Juraschek, Ramakrishna Mukkamala, Alfred K. Cheung, Stavros G. Drakos, Christel Hohenegger, Braxton Osting, Benjamin Sanchez
2026 J jnl
IEEE Trans. Biomed. Eng.
Sina Masoumi Shahrbabak, Azin Mousavi, Ramakrishna Mukkamala, Jin-Oh Hahn
2024 J jnl
IEEE Trans. Biomed. Eng.
Azin Mousavi, Omer T. Inan, Ramakrishna Mukkamala, Jin-Oh Hahn
2024 J jnl
IEEE J. Biomed. Health Informatics
Wenjin Wang, Caifeng Shan, Steffen Leonhardt, Ramakrishna Mukkamala, Ewa Nowara
2024 J jnl
IEEE Trans. Biomed. Eng.
Cederick Landry, Mark Freithaler, Vishaal Dhamotharan, Hadi Daher, Sanjeev G. Shroff, Ramakrishna Mukkamala
2024 J jnl
Comput. Biol. Medicine
Sina Masoumi Shahrbabak, Sooho Kim, Byeng Dong Youn, Hao-Min Cheng, Chen-Huan Chen, Ramakrishna Mukkamala, Jin-Oh Hahn
2024 J jnl
npj Digit. Medicine
Donghyeon Kim, Divyesh Narayanan, Shih-Hsien Sung, Hao-Min Cheng, Chen-Huan Chen, Chang-Sei Kim, Ramakrishna Mukkamala, Jin-Oh Hahn
2023 J jnl
IEEE Trans. Biomed. Eng.
Vishaal Dhamotharan, Anand Chandrasekhar, Hao-Min Cheng, Chen-Huan Chen, Shih-Hsien Sung, Cederick Landry, Jin-Oh Hahn, Aman Mahajan, Sanjeev G. Shroff, Ramakrishna Mukkamala
2023 J jnl
IEEE Trans. Biomed. Eng.
Mark Freithaler, Anand Chandrasekhar, Vishaal Dhamotharan, Cederick Landry, Sanjeev G. Shroff, Ramakrishna Mukkamala
2023 J jnl
Biomed. Signal Process. Control.
Yang Yao, Md Mobashir Hasan Shandhi, Jin-Oh Hahn, Omer T. Inan, Ramakrishna Mukkamala, Lin Xu
2022 J jnl
npj Digit. Medicine
Mohammad Yavarimanesh, Hao-Min Cheng, Chen-Huan Chen, Shih-Hsien Sung, Aman Mahajan, Rabih A. Chaer, Sanjeev G. Shroff, Jin-Oh Hahn, Ramakrishna Mukkamala
2022 J jnl
IEEE Trans. Biomed. Eng.
Mohammad Yavarimanesh, Robert C. Block, Keerthana Natarajan, Lalit K. Mestha, Omer T. Inan, Jin-Oh Hahn, Ramakrishna Mukkamala
2022 J jnl
IEEE Trans. Biomed. Eng.
Keerthana Natarajan, Robert C. Block, Mohammad Yavarimanesh, Anand Chandrasekhar, Lalit K. Mestha, Omer T. Inan, Jin-Oh Hahn, Ramakrishna Mukkamala
2022 J jnl
IEEE Trans. Biomed. Eng.
Sungtae Shin, Azin Mousavi, Sophia Lyle, Elisabeth Jang, Peyman Yousefian, Ramakrishna Mukkamala, Dae-Geun Jang, Ui-Kun Kwon, Youn Ho Kim, Jin-Oh Hahn
2022 J jnl
Comput. Biol. Medicine
Shuo Du, Yang Yao, Guozhe Sun, Ramakrishna Mukkamala, Lisheng Xu
2021 J jnl
IEEE Trans. Biomed. Eng.
Sungtae Shin, Peyman Yousefian, Azin Mousavi, Chang-Sei Kim, Ramakrishna Mukkamala, Dae-Geun Jang, Byung-Hoon Ko, Jongwook Lee, Ui-Kun Kwon, Youn Ho Kim, Jin-Oh Hahn
2021 J jnl
Sensors
Marco Di Rienzo, Ramakrishna Mukkamala
2020 J jnl
IEEE J. Biomed. Health Informatics
Yang Yao, Zahra Ghasemi, Md Mobashir Hasan Shandhi, Hazar Ashouri, Lisheng Xu, Ramakrishna Mukkamala, Omer T. Inan, Jin-Oh Hahn
2020 J jnl
IEEE Trans. Biomed. Eng.
Anand Chandrasekhar, Mohammad Yavarimanesh, Keerthana Natarajan, Jin-Oh Hahn, Ramakrishna Mukkamala
2020 J jnl
IEEE Access
Peyman Yousefian, Sungtae Shin, Azin Mousavi, Ali Tivay, Chang-Sei Kim, Ramakrishna Mukkamala, Dae-Geun Jang, Byung Hoon Ko, Jongwook Lee, Ui-Kun Kwon, Youn Ho Kim, Jin-Oh Hahn
2019 J jnl
Sensors
Yang Yao, Sungtae Shin, Azin Mousavi, Chang-Sei Kim, Lisheng Xu, Ramakrishna Mukkamala, Jin-Oh Hahn
2018 C conf
FIE
Marisel Villafane-Delgado, Ramakrishna Mukkamala
2018 J jnl
IEEE Trans. Biomed. Eng.
Chang-Sei Kim, Andrew M. Carek, Omer T. Inan, Ramakrishna Mukkamala, Jin-Oh Hahn
2018 J jnl
IEEE J. Biomed. Health Informatics
Jongchan Lee, Zahra Ghasemi, Chang-Sei Kim, Hao-Min Cheng, Chen-Huan Chen, Shih-Hsien Sung, Ramakrishna Mukkamala, Jin-Oh Hahn
2018 J jnl
IEEE Trans. Biomed. Eng.
Ramakrishna Mukkamala, Jin-Oh Hahn
2017 J jnl
IEEE Trans. Biomed. Eng.
Mingwu Gao, Hao-Min Cheng, Shih-Hsien Sung, Chen-Huan Chen, Nicholas Bari Olivier, Ramakrishna Mukkamala
2016 B conf
CHASE
Albert Lee, Zahra Ghasemi, Chang-Sei Kim, Jin-Oh Hahn, Ramakrishna Mukkamala, Hao-Min Cheng, Chen-Huan Chen, Shih-Hsien Sung
2015 J jnl
IEEE Trans. Biomed. Eng.
Chang-Sei Kim, Andrew M. Carek, Ramakrishna Mukkamala, Omer T. Inan, Jin-Oh Hahn
2015 J jnl
IEEE Trans. Biomed. Eng.
Ramakrishna Mukkamala, Jin-Oh Hahn, Omer T. Inan, Lalit K. Mestha, Chang-Sei Kim, Hakan Toreyin, Survi Kyal
2014 conf
EMBC
Mingwu Gao, Mohsen Moslehpour, Nicholas Bari Olivier, Ramakrishna Mukkamala
2014 J jnl
IEEE Trans. Biomed. Eng.
Mingwu Gao, Guanqun Zhang, Nicholas Bari Olivier, Ramakrishna Mukkamala
2014 conf
EMBC
Jiankun Liu, Hao-Min Cheng, Chen-Huan Chen, Shih-Hsien Sung, Jin-Oh Hahn, Ramakrishna Mukkamala
2013 conf
EMBC
Ramakrishna Mukkamala, Mingwu Gao
2013 conf
EMBC
Jiankun Liu, Jin-Oh Hahn, Ramakrishna Mukkamala
2012 conf
EMBC
Guanqun Zhang, Kathy L. Ryan, Caroline A. Rickards, Victor A. Convertino, Ramakrishna Mukkamala
2012 conf
EMBC
Jiankun Liu, Jin-Oh Hahn, Ramakrishna Mukkamala
2012 conf
EMBC
Mingwu Gao, Ramakrishna Mukkamala
2011 conf
EMBC
Mohsen Moslehpour, Guanqun Zhang, Ramakrishna Mukkamala
2011 conf
EMBC
Guanqun Zhang, Da Xu, Nicholas Bari Olivier, Ramakrishna Mukkamala
2011 conf
EMBC
Guanqun Zhang, Mingwu Gao, Ramakrishna Mukkamala
2010 J jnl
IEEE Trans. Biomed. Eng.
Gokul Swamy, Nicholas Bari Olivier, Ramakrishna Mukkamala
2009 J jnl
IEEE Trans. Biomed. Eng.
Da Xu, Nicholas Bari Olivier, Ramakrishna Mukkamala
2008 J jnl
IEEE Trans. Biomed. Eng.
Gokul Swamy, Ramakrishna Mukkamala
2006 J jnl
IEEE Trans. Biomed. Eng.
Xinshu Xiao, Ramakrishna Mukkamala, Richard J. Cohen
2006 conf
EMBC
Gokul Swamy, Qi Ling, Tongtong Li, Ramakrishna Mukkamala
2006 conf
EMBC
Zhenwei Lu, Ramakrishna Mukkamala
2006 conf
EMBC
Ramakrishna Mukkamala, Jacob Kuiper, Javier A. Sala-Mercado, Robert L. Hammond, Jong-Kyung Kim, Larry W. Stephenson, Donal S. O'Leary
2006 J jnl
IEEE Trans. Biomed. Eng.
Ramakrishna Mukkamala, Andrew T. Reisner, Horacio M. Hojman, Roger G. Mark, Richard J. Cohen
2005 J jnl
IEEE Trans. Biomed. Eng.
Xinshu Xiao, Ying Li, Ramakrishna Mukkamala
2003 J jnl
IEEE Trans. Biomed. Eng.
Antonis A. Armoundas, Andrew B. Feldman, Ramakrishna Mukkamala, Bin He, Thomas J. Mullen, Paul A. Belk, Yueh Z. Lee, Richard J. Cohen
2000
Ramakrishna Mukkamala
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'
        }