C. Patrick Yue

115 papers A* 2A 2C 4Journal 46Unranked 59
YearRankTypeTitle / Venue / Authors
2026 J jnl
IEEE J. Solid State Circuits
Chongyun Zhang, Li Wang, Fuzhan Chen, Quan Pan, Xianbo Li, C. Patrick Yue
2026 J jnl
CoRR
Wenhui Ou, Zhuoyu Wu, Yipu Zhang, Zheng Wang, C. Patrick Yue
2025 J jnl
IEEE Solid State Circuits Lett.
Chongyun Zhang, Li Wang, Fuzhan Chen, C. Patrick Yue
2025 conf
ISSCC
Fuzhan Chen, C. Patrick Yue, Quan Pan
2025 J jnl
IEEE Trans. Very Large Scale Integr. Syst.
Weichen Zhao, Weichen Tao, Yongheng Liu, Jingyuan Zhang, Zhongjun Zhang, Xu Yan, C. Patrick Yue, Fujiang Lin
2025 J jnl
IEEE Solid State Circuits Lett.
Shaokang Zhao, Li Wang, C. Patrick Yue
2025 J jnl
IEEE J. Solid State Circuits
Fuzhan Chen, Chongyun Zhang, Li Wang, Quan Pan, C. Patrick Yue
2025 J jnl
IEEE J. Solid State Circuits
Li Wang, Zilu Liu, Ruitao Ma, C. Patrick Yue
2025 conf
NewCAS
Shaokang Zhao, Li Wang, C. Patrick Yue
2025 C conf
ISCAS
Wenhui Ou, Zhuoyu Wu, Yike Li, Alexandra Geciova, Zheng Wang, C. Patrick Yue
2024 conf
CICC
Li Wang, Zilu Liu, Ruitao Ma, C. Patrick Yue
2024 C conf
TENCON
Juncheng Deng, Luyao Yuan, Zeyu Zhou, JinFeng Xie, Ahmed Wahba, Ping Ma, Yizhe Hu, Fujiang Lin, C. Patrick Yue, Liheng Lou
2024 conf
VLSI Technology and Circuits
Chongyun Zhang, Li Wang, Zilu Liu, Fuzhan Chen, Quan Pan, Xianbo Li, C. Patrick Yue
2024 conf
CICC
Fuzhan Chen, C. Patrick Yue, Quan Pan
2024 J jnl
IEEE J. Solid State Circuits
Li Wang, Zhao Zhang, Can Wang, Rehan Azmat, Weimin Shi, C. Patrick Yue
2024 J jnl
IEEE Access
Derek Abbott, Sonia Aissa, Anuradha Annaswamy, Nirwan Ansari, Jun Cai, Kun-Shan Chen, Yixin Chen, J.-C. Chiao, Ayman El-Baz, Shaikh Fattah, Hoay Gooi, Maya B. Gokhale, Chih-Lin I, Giuseppe Iannaccone, Yumi Iwashita, Bruce Jacob, Abbas Jamalipour, Bahram Javidi, Weihua Jiang, Okyay Kaynak, Hulya Kirkici, Germano Lambert-Torres, Shengtao Li, Michal Mrozowski, Michele Nappi, Dalma Novak, Hugo Proença, Yi Qian, Zhihua Qu, Susanto Rahardja, Mehrdad Saif, Ali Serpengüzel, Peter H. Siegel, Ashitey Trebi-Ollennu, Daniela Tuninetti, Ge Wang, Keith A. Wear, Andreas Weisshaar, C. Patrick Yue, Enrico Zio
2024 J jnl
CoRR
Zhengdong Li, Frederick Ziyang Hong, C. Patrick Yue
2024 J jnl
IEEE Trans. Circuits Syst. Video Technol.
Ziyang Hong, C. Patrick Yue
2023 conf
ESSCIRC
Fuzhan Chen, Chongyun Zhang, Li Wang, Quan Pan, C. Patrick Yue
2023 conf
VLSI Technology and Circuits
Li Wang, Zilu Liu, C. Patrick Yue
2023 J jnl
IEEE J. Emerg. Sel. Topics Circuits Syst.
Junmin Jiang, Xu Zhang, Xun Liu, Zhaojun Liu, Liusheng Sun, Shing Hin Yuen, Wing Cheung Chong, Wing-Hung Ki, C. Patrick Yue, Kei May Lau
2023 J jnl
IEEE Trans. Neural Networks Learn. Syst.
Chengchao Bai, Jiawei Zhang, Jifeng Guo, C. Patrick Yue
2023 conf
ICCV (Workshops)
Ziyang Hong, C. Patrick Yue
2023 J jnl
CoRR
Ziyang Hong, C. Patrick Yue
2023 conf
ASICON
Zilu Liu, Li Wang, Hamed Fallah, C. Patrick Yue
2023 J jnl
IEEE J. Solid State Circuits
Xianbo Li, Hengbo Wang, Jianping Zhu, C. Patrick Yue
2023 conf
CDC
Hoi Chuen Cheng, Ling Shi, C. Patrick Yue
2022 conf
MWSCAS
Chongyun Zhang, Fuzhan Chen, C. Patrick Yue
2022 J jnl
IEEE Trans. Instrum. Meas.
Babar Hussain, Yiru Wang, Runzhou Chen, C. Patrick Yue
2022 J jnl
ACM Trans. Embed. Comput. Syst.
Ziyang Hong, C. Patrick Yue
2022 J jnl
IEEE Internet Things J.
Babar Hussain, Yiru Wang, Runzhou Chen, Hoi Chuen Cheng, C. Patrick Yue
2022 J jnl
Robotics
Yiru Wang, Babar Hussain, C. Patrick Yue
2021 J jnl
IEEE J. Solid State Circuits
Zhao Zhang, Guang Zhu, C. Patrick Yue
2021 J jnl
IEEE Open J. Circuits Syst.
Can Wang, Li Wang, Zhao Zhang, Milad Kalantari Mahmoudabadi, Weimin Shi, C. Patrick Yue
2021 conf
VLSI Circuits
Li Wang, Zhao Zhang, C. Patrick Yue
2021 J jnl
IEEE J. Solid State Circuits
Milad Kalantari, Li Wang, Hossein Shirinabadi, Ali Fotowat-Ahmady, C. Patrick Yue
2021 conf
ASICON
Weimin Shi, Fuzhan Chen, Xinyi Liu, Chongyun Zhang, Zilu Liu, Tianxin Min, Bo Xu, Li Wang, Jian Kang, C. Patrick Yue
2021 J jnl
IEEE Trans. Circuits Syst. II Express Briefs
Weimin Shi, Wen Shi, Jun Peng, Linping Feng, Yong Gao, Songbai He, C. Patrick Yue
2021 conf
ASICON
Fuzhan Chen, Chongyun Zhang, Tianxin Min, Bo Xu, Quan Pan, C. Patrick Yue
2021 conf
ASICON
Tianxin Min, Jian Kang, Bo Xu, Weimin Shi, C. Patrick Yue
2021 J jnl
CoRR
Ziyang Hong, C. Patrick Yue
2021 conf
OFC
Yiru Wang, Weipeng Guan, Babar Hussain, C. Patrick Yue
2021 conf
ASICON
Zilu Liu, Rehan Azmat, Xinyi Liu, Li Wang, C. Patrick Yue
2021 C conf
PCS
Yiru Wang, C. Patrick Yue
2021 J jnl
IEEE Trans. Circuits Syst. I Regul. Pap.
Rehan Azmat, Li Wang, Khawaja Qasim Maqbool, Can Wang, C. Patrick Yue
2021 conf
GCCE
Bo Xu, Babar Hussain, Xinyi Liu, Tianxin Min, Hoi Chuen Cheng, C. Patrick Yue
2021 J jnl
CoRR
Weipeng Guan, Babar Hussain, C. Patrick Yue
2020 conf
ISSCC
Milad Kalantari, Hossein Shirinabadi, Ali Fotowat-Ahmadi, C. Patrick Yue
2020 J jnl
IEEE J. Solid State Circuits
Zhao Zhang, Guang Zhu, C. Patrick Yue
2020 J jnl
IEEE Trans. Circuits Syst. I Regul. Pap.
Xiangyu Meng, Milad Kalantari, Baoyong Chi, Wenhua Chen, Zhijian Chen, Xiaoling Lin, C. Patrick Yue
2020 J jnl
IEEE J. Solid State Circuits
Zhao Zhang, Guang Zhu, Can Wang, Li Wang, C. Patrick Yue
2020 J jnl
IEEE Trans. Circuits Syst. II Express Briefs
Quan Pan, Yipeng Wang, C. Patrick Yue
2020 J jnl
IEEE Trans. Very Large Scale Integr. Syst.
Quan Pan, Li Wang, Xiongshi Luo, C. Patrick Yue
2020 conf
MLICOM
Jian Kang, Xuanzheng Wang, Li Wang, Can Wang, C. Patrick Yue
2020 conf
MLICOM
Bo Xu, Li Wang, Jian Kang, Cong Qiu, C. Patrick Yue
2020 conf
MLICOM
Yiru Wang, Bo Xu, Jian Kang, Cong Qiu, C. Patrick Yue
2019 conf
VLSI Circuits
Zhao Zhang, Guang Zhu, C. Patrick Yue
2019 conf
ISSCC
Zhao Zhang, Guang Zhu, C. Patrick Yue
2019 conf
A-SSCC
Xiangyu Meng, Zhenpeng Zheng, Jiaqi Zhang, C. Patrick Yue
2019 conf
A-SSCC
Zhao Zhang, Guang Zhu, Can Wang, Li Wang, C. Patrick Yue
2019 conf
VLSI Circuits
Can Wang, Guang Zhu, Zhao Zhang, C. Patrick Yue
2019 conf
GCCE
Babar Hussain, Cong Qiu, C. Patrick Yue
2019 conf
GCCE
Bo Xu, Zhaojun Liu, C. Patrick Yue
2019 conf
GCCE
Cong Qiu, Babar Hussain, C. Patrick Yue
2019 conf
GCCE
Jian Kang, Li Wang, C. Patrick Yue
2019 conf
GCCE
Babar Hussain, Cong Qiu, C. Patrick Yue
2018 conf
VLSI Circuits
Xiangyu Meng, Can Wang, Milad Kalantari, C. Patrick Yue
2018 J jnl
IEEE Trans. Circuits Syst. I Regul. Pap.
Haikun Jia, Clarissa C. Prawoto, Baoyong Chi, Zhihua Wang, C. Patrick Yue
2018 J jnl
IEEE Trans. Circuits Syst. II Express Briefs
Khawaja Qasim Maqbool, Duona Luo, Xingyun Luo, Huichun Yu, C. Patrick Yue
2017 J jnl
IEEE Trans. Circuits Syst. I Regul. Pap.
Yipeng Wang, Duona Luo, Quan Pan, Liwen Jing, Zhixin Li, C. Patrick Yue
2017 conf
A-SSCC
Guang Zhu, Quan Pan, John Zhuang, Charlie Zhi, C. Patrick Yue
2017 C conf
ISCAS
Khawaja Qasim Maqbool, Duona Luo, Guang Zhu, Xingyun Luo, Huichun Yu, C. Patrick Yue
2017 conf
A-SSCC
Junmin Jiang, Liusheng Sun, Xu Zhang, Shing Hin Yuen, Xianbo Li, Wing-Hung Ki, C. Patrick Yue, Kei May Lau
2016 conf
A-SSCC
Haikun Jia, Clarissa C. Prawoto, Baoyong Chi, Zhihua Wang, C. Patrick Yue
2016 ed.
VLCS@MobiCom
Xia Zhou, C. Patrick Yue
2015 conf
ISSCC
Yan Lu, Junmin Jiang, Wing-Hung Ki, C. Patrick Yue, Sai-Weng Sin, Seng-Pan U, Rui Paulo Martins
2015 conf
ESSCIRC
Yipeng Wang, Duona Luo, Quan Pan, Liwen Jing, Zhixin Li, C. Patrick Yue
2015 J jnl
IEEE Trans. Circuits Syst. I Regul. Pap.
Yan Lu, Yipeng Wang, Quan Pan, Wing-Hung Ki, C. Patrick Yue
2015 conf
VLSIC
Babar Hussain, Fengyu Che, Feng Zhang, Tak-Sang Yim, Lin Cheng, Wing-Hung Ki, C. Patrick Yue, Liang Wu
2015 conf
VLSIC
Liang Wu, Xianbo Li, Wing Cheung Chong, Zhaojun Liu, Fengyu Che, Babar Hussain, Kei May Lau, C. Patrick Yue
2014 conf
ISSCC
Yan Lu, Wing-Hung Ki, C. Patrick Yue
2014 J jnl
IEEE Trans. Circuits Syst. I Regul. Pap.
Li Sun, Quan Pan, Keh-Chung Wang, C. Patrick Yue
2014 conf
ESSCIRC
Quan Pan, Yipeng Wang, Zhengxiong Hou, Li Sun, Liang Wu, Wing-Hung Ki, Patrick Chiang, C. Patrick Yue
2014 conf
VLSIC
Quan Pan, Zhengxiong Hou, Yipeng Wang, Yan Lu, Wing-Hung Ki, Keh-Chung Wang, C. Patrick Yue
2014 J jnl
IEEE J. Solid State Circuits
X. Shawn Wang, Xin Wang, Fei Lu, Chen Zhang, Zongyu Dong, Li Wang, Rui Ma, Zitao Shi, Albert Z. Wang, Mau-Chung Frank Chang, Dawn Wang, Alvin J. Joseph, C. Patrick Yue
2014 A conf
IROS
Ming Liu, Kejie Qiu, Fengyu Che, Shaohua Li, Babar Hussain, Liang Wu, C. Patrick Yue
2013 conf
ISSCC
Yan Lu, Xing Li, Wing-Hung Ki, Chi-Ying Tsui, C. Patrick Yue
2013 conf
ASICON
Zhengxiong Hou, Yipeng Wang, Quan Pan, C. Patrick Yue
2013 conf
ASICON
Quan Pan, Zhengxiong Hou, Yipeng Wang, C. Patrick Yue
2013 conf
CICC
X. Shawn Wang, Xin Wang, Fei Lu, Li Wang, Rui Ma, Zongyu Dong, Li Sun, Albert Z. Wang, C. Patrick Yue, Dawn Wang, Alvin J. Joseph
2013 J jnl
IEEE Trans. Circuits Syst. II Express Briefs
Yan Lu, Gang Yuan, Lawrence Der, Wing-Hung Ki, C. Patrick Yue
2012 conf
CICC
Jiao Cheng, Lingli Xia, Chao Ma, Yong Lian, Xiaoyuan Xu, C. Patrick Yue, Zhiliang Hong, Patrick Yin Chiang
2012 conf
MWSCAS
Yan Lu, Wing-Hung Ki, C. Patrick Yue
2012 conf
VLSI-DAT
Ping K. Ko, C. Patrick Yue
2012 conf
VLSI-DAT
Michel Brillouët, Shyh-Jye Jou, C. Patrick Yue
2012 conf
VLSI-DAT
Rongxiang Wu, Salahuddin Raju, Mansun Chan, Johnny K. O. Sin, C. Patrick Yue
2009 conf
CICC
Dong Hun Shin, Ji-Eun Jang, Frank O'Mahony, C. Patrick Yue
2009 conf
ISSCC
Munkyo Seo, Basanth Jagannathan, Corrado Carta, John J. Pekarik, Luis Chen, C. Patrick Yue, Mark J. W. Rodwell
2008 conf
CICC
Piljae Park, C. Patrick Yue
2007 conf
CICC
Jaejin Park, J. F. Liu, L. Richard Carley, C. Patrick Yue
2007 A conf
DATE
Dongwoo Hong, Shadi Saberi, Kwang-Ting Cheng, C. Patrick Yue
2005 conf
ISCAS (2)
Jaejin Park, Ruifeng Sun, L. Rick Carley, C. Patrick Yue
2005 conf
ISCAS (2)
Ruifeng Sun, Jaejin Park, Frank O'Mahony, C. Patrick Yue
2004 J jnl
IEEE J. Solid State Circuits
Niranjan A. Talwalkar, C. Patrick Yue, Haitao Gan, S. Simon Wong
2003 J jnl
IEEE J. Solid State Circuits
Frank O'Mahony, C. Patrick Yue, Mark A. Horowitz, S. Simon Wong
2003 A* conf
DAC
Frank O'Mahony, C. Patrick Yue, Mark Horowitz, S. Simon Wong
2003 J jnl
IEEE J. Solid State Circuits
Richard Chang, Niranjan Talwalkar, C. Patrick Yue, S. Simon Wong
2003 conf
ISQED
S. Simon Wong, C. Patrick Yue, Richard Chang, So-Young Kim, Bendik Kleveland, Frank O'Mahony
2002 J jnl
IEEE J. Solid State Circuits
Masoud Zargari, David K. Su, C. Patrick Yue, Shahriar Rabii, David Weber, Brian J. Kaczynski, Srenik S. Mehta, Kalwant Singh, Sunetra Mendis, Bruce A. Wooley
1999 A* conf
DAC
C. Patrick Yue, S. Simon Wong
1999 ch.
The VLSI Handbook
Thomas H. Lee, Maria del Mar Hershenson, Sunderarajan S. Mohan, Kirad Samavati, C. Patrick Yue
1998 J jnl
IEEE J. Solid State Circuits
Derek K. Shaeffer, Arvin Shahani, Sunderarajan S. Mohan, Hirad Samavati, Hamid R. Rategh, Maria del Mar Hershenson, Min Xu, C. Patrick Yue, Daniel J. Eddleman, Thomas H. Lee
1998 J jnl
IEEE J. Solid State Circuits
Arvin Shahani, Derek K. Shaeffer, Sunderarajan S. Mohan, Hirad Samavati, Hamid R. Rategh, Maria del Mar Hershenson, Min Xu, C. Patrick Yue, Daniel J. Eddleman, Mark A. Horowitz, Thomas H. Lee
1998 J jnl
IEEE J. Solid State Circuits
C. Patrick Yue, S. Simon Wong
1993 J jnl
IEEE Trans. Comput. Aided Des. Integr. Circuits Syst.
C. Patrick Yue, Victor Martin Agostinelli Jr., Gregory Munson Yeric, A. F. Tasch Jr.
redb/extractors/hashes.py
← Index redb/extractors/hashes.py python
from dataclasses import asdict
from typing import Any
from datetime import datetime, timezone

import hashlib
import inspect
from struct import pack

from magika import Magika
from signify.fingerprinter import AuthenticodeFingerprinter
import ppdeep
import tlsh

import pefile
from elftools.elf.elffile import ELFFile
from elftools.common.exceptions import ELFError

from redb.extractors.enum import Tag
from redb.models.dataclasses import Hashes
from redb.extractors.extractor import Extractor


class HashExtractor(Extractor):

    def __init__(
        self,
        filepath,
        log,
        exporters=None,
        index_prefix=None,
        elastic_index=None,
        known_benign=False,
        known_malicious=False,
        macho=None,
    ):
        super().__init__(
            filepath, log, exporters, index_prefix, elastic_index, known_benign, known_malicious
        )
        self.hashes = None
        self.elastic_index = self.index_prefix + "-hashes"
        self.filetype = Magika().identify_bytes(self.binary).output.label
        self.pe = None
        self.elf = None
        self.macho = macho
        if self.filetype == "pebin":  # else None
            try:
                self.pe = pefile.PE(self.filepath)
            except Exception as e:
                self.log.error(f"Failed to initialize PE file object: {e}")
                self.pe = None
        elif self.filetype == "elf":
            # ELF file will be created when needed in _extract_elf_hashes
            pass

    def _extract_hashes(self):
        self.log.debug(inspect.currentframe().f_code.co_name)
        
        # Initialize hash values with None
        md5 = None
        sha1 = None
        sha256 = None
        ssdeep_hash = None
        tlsh_hash = None
        
        # Calculate basic hashes with error handling
        try:
            md5 = hashlib.md5(self.binary).hexdigest()
        except Exception as e:
            self.log.error(f"Failed to calculate MD5 hash: {e}")
            
        try:
            sha1 = hashlib.sha1(self.binary).hexdigest()
        except Exception as e:
            self.log.error(f"Failed to calculate SHA1 hash: {e}")
            
        try:
            sha256 = hashlib.sha256(self.binary).hexdigest()
        except Exception as e:
            self.log.error(f"Failed to calculate SHA256 hash: {e}")
            
        try:
            ssdeep_hash = ppdeep.hash_from_file(self.filepath)
        except Exception as e:
            self.log.error(f"Failed to calculate ssdeep hash: {e}")
            
        try:
            tlsh_hash = tlsh.hash(self.binary)
        except Exception as e:
            self.log.error(f"Failed to calculate TLSH hash: {e}")
        
        # Create Hashes object with available values
        self.hashes = Hashes(
            md5 or "",
            sha1 or "",
            sha256 or "",
            ssdeep_hash or "",
            tlsh_hash or "",
        )

        if self.filetype == "pebin" and self.pe is not None:
            self.log.debug("Computing PEBIN related hash values")
            
            # Authentihash
            try:
                with open(self.filepath, 'rb') as f:
                    fingerprinter = AuthenticodeFingerprinter(f)
                    fingerprinter.add_authenticode_hashers(hashlib.sha256)
                    self.hashes.authentihash = fingerprinter.hash()['sha256'].hex()
            except Exception as e:
                self.log.error(f"Failed to calculate Authentihash: {e}")
                self.hashes.authentihash = None
                
            # Imphash
            try:
                self.hashes.imphash = self.pe.get_imphash()
            except Exception as e:
                self.log.error(f"Failed to calculate Imphash: {e}")
                self.hashes.imphash = None
                
            # Rich header hashes
            try:
                if self.pe.parse_rich_header():
                    self.log.debug("Computing RichHeader related hash values")
                    
                    richhash = self._compute_richhash()
                    if richhash:
                        self.hashes.richhash = richhash
                        
                    richpe_hash = self._compute_richpe_hash()
                    if richpe_hash:
                        self.hashes.richpe_hash = richpe_hash
                        
                    richpv_result = self._compute_richpv_hash()
                    if richpv_result:
                        self.hashes.richpv_hash, self.hashes.richpv_hash_sorted = richpv_result
            except Exception as e:
                self.log.error(f"Failed to calculate Rich header hashes: {e}")
        elif self.filetype == "pebin" and self.pe is None:
            self.log.warning("PE file type detected but PE object initialization failed - skipping PE-specific hashes")

        elif self.filetype == "elf":
            self.log.debug("Computing ELF related hash values")
            self._extract_elf_hashes()
        elif self.filetype == "macho":
            self.log.debug("Computing Mach-O related hash values")
            self._extract_macho_hashes()
        elif self.filetype == "apk":
            self.log.debug("Computing APK related hash values")
            self._extract_apk_hashes()
        else:
            pass
        self.log.debug(f"Hashes dump: {asdict(self.hashes)}")
        return self.hashes

    def _compute_richhash(self):
        self.log.debug(inspect.currentframe().f_code.co_name)
        try:
            rich_header = self.pe.parse_rich_header()
            if not rich_header:
                return ""
            data = rich_header["clear_data"]
            return hashlib.md5(data).hexdigest().lower()
        except:
            return ""

    def _compute_richpe_hash(self):
        """
        Computes the RichPE hash given a file path or PE object.

        RichPE hash is includes RichHeader CompID and count, as well as
        fields from IMAGE_FILE_HEADER and IMAGE_OPTIONAL_HEADER

        Parameters:
        input: it can be either a file path or a PE object

        Returns:
        richpe_hash: md5 hash of the RichPE value
        None: if no Rich Header present
        """
        try:
            # Attempt to parse Rich header
            self.log.debug(inspect.currentframe().f_code.co_name)
            rich_header = self.pe.parse_rich_header()
            if rich_header is None:
                return None

            # Get list of @Comp.IDs and counts from Rich header
            # Elements in rich_fields at even indices are @Comp.IDs
            # Elements in rich_fields at odd indices are counts
            rich_fields = rich_header.get("values", None)
            if not rich_fields or len(rich_fields) % 2 != 0:
                return None

            md5 = hashlib.md5()

            # Update hash using @Comp.IDs and masked counts from Rich header
            while len(rich_fields):
                compid = rich_fields.pop(0)
                count = rich_fields.pop(0)
                mask = 2 ** (count.bit_length() // 2 + 1) - 1
                count |= mask
                md5.update(pack("<L", compid))
                md5.update(pack("<L", count))

            # Update hash using metadata from the PE header
            md5.update(pack("<L", self.pe.FILE_HEADER.Machine))
            md5.update(pack("<L", self.pe.FILE_HEADER.Characteristics))
            md5.update(pack("<L", self.pe.OPTIONAL_HEADER.Subsystem))
            md5.update(pack("<B", self.pe.OPTIONAL_HEADER.MajorLinkerVersion))
            md5.update(pack("<B", self.pe.OPTIONAL_HEADER.MinorLinkerVersion))
            md5.update(pack("<L", self.pe.OPTIONAL_HEADER.MajorOperatingSystemVersion))
            md5.update(pack("<L", self.pe.OPTIONAL_HEADER.MinorOperatingSystemVersion))
            md5.update(pack("<L", self.pe.OPTIONAL_HEADER.MajorImageVersion))
            md5.update(pack("<L", self.pe.OPTIONAL_HEADER.MinorImageVersion))
            md5.update(pack("<L", self.pe.OPTIONAL_HEADER.MajorSubsystemVersion))
            md5.update(pack("<L", self.pe.OPTIONAL_HEADER.MinorSubsystemVersion))

            return md5.hexdigest()
        except Exception as e:
            self.log.error(f"Failed to compute RichPE hash: {e}")
            return None

    def _compute_richpv_hash(self):
        """
        Compute the RichPV hash values, sorted and unsorted.
        RichPV excludes the most volatile Rich Header field from the MD5 input data,
        the Product Count (pC) field.

        Returns:
        richpv_hash_unsorted: md5 hash of the RichPV value unsorted
        richpv_hash_sorted: md5 hash of the RichPV value sorted
        None: if no Rich Header present
        """
        try:
            self.log.debug(inspect.currentframe().f_code.co_name)
            # Attempt to parse Rich header
            rich_header = self.pe.parse_rich_header()
            if rich_header is None:
                return None

            # Get list of @Comp.IDs and counts from Rich header
            # Elements in rich_fields at even indices are @Comp.IDs
            # Elements in rich_fields at odd indices are counts
            rich_fields = rich_header.get("values", None)
            if not rich_fields or len(rich_fields) % 2 != 0:
                return None

            md5 = hashlib.md5()
            md5_sorted = hashlib.md5()
            sorted_vector = []

            # Update hash using @Comp.IDs only
            for i in range(0, len(rich_fields), 2):
                compid = rich_fields[i]
                md5.update(pack("<L", compid))
                sorted_vector.append(compid)

            sorted_vector.sort()
            for compid in sorted_vector:
                md5_sorted.update(pack("<L", compid))

            return md5.hexdigest(), md5_sorted.hexdigest()
        except Exception as e:
            self.log.error(f"Failed to compute RichPV hash: {e}")
            return None

    def _extract_elf_hashes(self):
        """Extract ELF specific similarity hashes."""
        self.log.debug(inspect.currentframe().f_code.co_name)

        try:
            with open(self.filepath, 'rb') as f:
                elf = ELFFile(f)
                if not elf:
                    return

                # Generate all similarity hashes
                import_hash = self._generate_elf_import_hash(elf)
                export_hash = self._generate_elf_export_hash(elf)
                section_hash = self._generate_elf_section_hash(elf)
                symbol_hash = self._generate_elf_symbol_hash(elf)
                dynamic_hash = self._generate_elf_dynamic_hash(elf)

                # Only set hashes if they have meaningful values
                if import_hash:
                    self.hashes.import_hash = import_hash
                if export_hash:
                    self.hashes.export_hash = export_hash
                if section_hash:
                    self.hashes.section_hash = section_hash
                if symbol_hash:
                    self.hashes.symhash = symbol_hash
                if dynamic_hash:
                    self.hashes.dynamic_hash = dynamic_hash

        except Exception as e:
            self.log.error(f"Failed to extract ELF hashes: {e}")

    def _generate_elf_import_hash(self, elf) -> str:
        """Generate MD5 hash of sorted, deduplicated imported symbol names."""
        try:
            imported_symbols = set()

            # Get dynamic symbol table
            dynsym_section = elf.get_section_by_name('.dynsym')
            if dynsym_section and hasattr(dynsym_section, 'iter_symbols'):
                for symbol in dynsym_section.iter_symbols():
                    # Look for undefined symbols (imports)
                    if (symbol.entry.get('st_shndx', 0) == 'SHN_UNDEF' and
                        symbol.name and
                        symbol.entry.get('st_info', {}).get('bind') in ['STB_GLOBAL', 'STB_WEAK']):
                        imported_symbols.add(symbol.name)

            # Also check relocations for additional imports
            for section in elf.iter_sections():
                if hasattr(section, 'iter_relocations'):
                    try:
                        for relocation in section.iter_relocations():
                            if hasattr(relocation, 'symbol') and relocation.symbol and relocation.symbol.name:
                                imported_symbols.add(relocation.symbol.name)
                    except:
                        pass

            # Sort and concatenate
            sorted_imports = sorted(list(imported_symbols))

            # Return None if no imports found
            if not sorted_imports:
                return None

            imports_string = '|'.join(sorted_imports)

            # Generate MD5 hash
            return hashlib.md5(imports_string.encode('utf-8')).hexdigest()

        except Exception as e:
            self.log.error(f"Error generating ELF import hash: {e}")
            return None

    def _generate_elf_export_hash(self, elf) -> str:
        """Generate MD5 hash of sorted, deduplicated exported symbol names."""
        try:
            exported_symbols = set()

            # Check both static and dynamic symbol tables
            symbol_sections = ['.symtab', '.dynsym']

            for section_name in symbol_sections:
                section = elf.get_section_by_name(section_name)
                if not section or not hasattr(section, 'iter_symbols'):
                    continue

                for symbol in section.iter_symbols():
                    # Check if symbol is exported (defined and globally visible)
                    if (symbol.name and
                        symbol.entry.get('st_shndx', 0) != 'SHN_UNDEF' and
                        symbol.entry.get('st_info', {}).get('bind') in ['STB_GLOBAL', 'STB_WEAK'] and
                        symbol.entry.get('st_info', {}).get('type') in ['STT_FUNC', 'STT_OBJECT']):
                        exported_symbols.add(symbol.name)

            # Sort and concatenate
            sorted_exports = sorted(list(exported_symbols))

            # Return None if no exports found
            if not sorted_exports:
                return None

            exports_string = '|'.join(sorted_exports)

            # Generate MD5 hash
            return hashlib.md5(exports_string.encode('utf-8')).hexdigest()

        except Exception as e:
            self.log.error(f"Error generating ELF export hash: {e}")
            return None

    def _generate_elf_section_hash(self, elf) -> str:
        """Generate MD5 hash of section layout (names, types, flags sequence)."""
        try:
            section_info = []

            for section in elf.iter_sections():
                header = section.header
                section_name = section.name or "<unnamed>"
                section_type = header.get('sh_type', 'SHT_NULL')
                section_flags = header.get('sh_flags', 0)

                # Create a consistent representation
                section_repr = f"{section_name}:{section_type}:{section_flags}"
                section_info.append(section_repr)

            # Return None if no meaningful sections found
            if not section_info:
                return None

            # Join all section info
            sections_string = '|'.join(section_info)

            # Generate MD5 hash
            return hashlib.md5(sections_string.encode('utf-8')).hexdigest()

        except Exception as e:
            self.log.error(f"Error generating ELF section hash: {e}")
            return None

    def _generate_elf_symbol_hash(self, elf) -> str:
        """Generate MD5 hash of sorted symbol names and types."""
        try:
            symbol_info = set()

            # Check both static and dynamic symbol tables
            symbol_sections = ['.symtab', '.dynsym']

            for section_name in symbol_sections:
                section = elf.get_section_by_name(section_name)
                if not section or not hasattr(section, 'iter_symbols'):
                    continue

                for symbol in section.iter_symbols():
                    if symbol.name:
                        symbol_type = symbol.entry.get('st_info', {}).get('type', 'STT_NOTYPE')
                        symbol_bind = symbol.entry.get('st_info', {}).get('bind', 'STB_LOCAL')

                        # Create a consistent representation
                        symbol_repr = f"{symbol.name}:{symbol_type}:{symbol_bind}"
                        symbol_info.add(symbol_repr)

            # Sort and concatenate
            sorted_symbols = sorted(list(symbol_info))

            # Return None if no symbols found
            if not sorted_symbols:
                return None

            symbols_string = '|'.join(sorted_symbols)

            # Generate MD5 hash
            return hashlib.md5(symbols_string.encode('utf-8')).hexdigest()

        except Exception as e:
            self.log.error(f"Error generating ELF symbol hash: {e}")
            return None

    def _generate_elf_dynamic_hash(self, elf) -> str:
        """Generate MD5 hash of dynamic section entries (DT_* tags)."""
        try:
            dynamic_info = []

            # Get the dynamic section
            dynamic_section = elf.get_section_by_name('.dynamic')
            if not dynamic_section:
                return None

            # Extract dynamic tags and their values
            for tag in dynamic_section.iter_tags():
                dt_tag = tag.entry.d_tag

                # Create a representation based on tag type
                if dt_tag == 'DT_NEEDED':
                    dynamic_info.append(f"DT_NEEDED:{tag.needed}")
                elif dt_tag == 'DT_SONAME':
                    dynamic_info.append(f"DT_SONAME:{tag.soname}")
                elif dt_tag == 'DT_RPATH':
                    dynamic_info.append(f"DT_RPATH:{tag.rpath}")
                elif dt_tag == 'DT_RUNPATH':
                    dynamic_info.append(f"DT_RUNPATH:{tag.runpath}")
                else:
                    # For other tags, use the tag name and value
                    dt_value = tag.entry.d_val if hasattr(tag.entry, 'd_val') else 0
                    dynamic_info.append(f"{dt_tag}:{dt_value}")

            # Sort to ensure consistent ordering
            dynamic_info.sort()
            dynamics_string = '|'.join(dynamic_info)

            # Generate MD5 hash
            return hashlib.md5(dynamics_string.encode('utf-8')).hexdigest()

        except Exception as e:
            self.log.error(f"Error generating ELF dynamic hash: {e}")
            return None

    def _extract_macho_hashes(self):
        """Extract Mach-O specific similarity hashes using machofile API.

        For FAT binaries, this extracts hashes for the current file being processed
        (either the FAT container or an individual slice). The machofile library
        handles the architecture-specific extraction when an arch parameter is provided.

        For slices: We parse the slice file directly since it's a standalone Mach-O.
        For FAT container: We use the provided macho object with combined/fat hashes.
        """
        self.log.debug(inspect.currentframe().f_code.co_name)

        try:
            # If we have a pre-parsed macho object (FAT container or single-arch with passed object)
            if self.macho:
                architectures = self.macho.get_architectures()
                is_fat = len(architectures) > 1

                if is_fat:
                    # For FAT container, get combined hashes (key may be 'fat' or 'combined')
                    all_hashes = self.macho.get_similarity_hashes()
                    if all_hashes:
                        # Try 'fat' first, then 'combined' for backwards compatibility
                        similarity_hashes = all_hashes.get('fat', all_hashes.get('combined', {}))
                    else:
                        similarity_hashes = {}
                else:
                    # Single-arch with pre-parsed object
                    similarity_hashes = self.macho.get_similarity_hashes(arch=architectures[0]) if architectures else {}
            else:
                # No pre-parsed object - parse the file (slice case)
                import machofile
                macho = machofile.UniversalMachO(self.filepath)
                macho.parse()

                architectures = macho.get_architectures()
                if architectures:
                    # For a slice, there's only one architecture
                    similarity_hashes = macho.get_similarity_hashes(arch=architectures[0]) or {}
                else:
                    similarity_hashes = {}

            # Set the hash values on the Hashes object
            if similarity_hashes:
                if similarity_hashes.get('dylib_hash'):
                    self.hashes.macho_dylib_hash = similarity_hashes['dylib_hash']
                if similarity_hashes.get('import_hash'):
                    self.hashes.macho_import_hash = similarity_hashes['import_hash']
                if similarity_hashes.get('export_hash'):
                    self.hashes.macho_export_hash = similarity_hashes['export_hash']
                if similarity_hashes.get('entitlement_hash'):
                    self.hashes.macho_entitlement_hash = similarity_hashes['entitlement_hash']
                if similarity_hashes.get('symhash'):
                    self.hashes.macho_symhash = similarity_hashes['symhash']

        except Exception as e:
            self.log.error(f"Failed to extract Mach-O hashes: {e}")

    def _extract_apk_hashes(self):
        """Extract APK specific similarity hashes (permhash)."""
        self.log.debug(inspect.currentframe().f_code.co_name)
        try:
            from permhash.functions import permhash_apk
            ph = permhash_apk(self.filepath)
            if ph:
                self.hashes.permhash = ph
        except Exception as e:
            self.log.error(f"Failed to extract APK hashes: {e}")

    def extract(self):
        try:
            self.log.debug(inspect.currentframe().f_code.co_name)
            self._extract_hashes()
            return self.hashes
        except Exception as e:
            self.log.error(f"Error extracting hashes: {e}")
            return None

    def prepare_export_data(self, exporter_type: str) -> Any:
        if exporter_type == "ElasticsearchExporter":
            return self.hashes
        elif exporter_type == "ClickHouseExporter":
            # Safely get hash values with fallbacks for None values
            sha256 = getattr(self.hashes, 'sha256', None) or ""
            md5 = getattr(self.hashes, 'md5', None) or ""
            sha1 = getattr(self.hashes, 'sha1', None) or ""
            ssdeep_hash = getattr(self.hashes, 'ssdeep_hash', None) or ""
            tlsh_hash = getattr(self.hashes, 'tlsh_hash', None) or ""
            authentihash = getattr(self.hashes, 'authentihash', None)
            imphash = getattr(self.hashes, 'imphash', None)
            impfuzzy = getattr(self.hashes, 'impfuzzy', None)
            typerefhash = getattr(self.hashes, 'typerefhash', None)
            richhash = getattr(self.hashes, 'richhash', None)
            richpe_hash = getattr(self.hashes, 'richpe_hash', None)
            richpv_hash = getattr(self.hashes, 'richpv_hash', None)
            richpv_hash_sorted = getattr(self.hashes, 'richpv_hash_sorted', None)
            # ELF hashes
            import_hash = getattr(self.hashes, 'import_hash', None)
            export_hash = getattr(self.hashes, 'export_hash', None)
            section_hash = getattr(self.hashes, 'section_hash', None)
            symbol_hash = getattr(self.hashes, 'symhash', None)
            dynamic_hash = getattr(self.hashes, 'dynamic_hash', None)
            # Mach-O hashes
            macho_dylib_hash = getattr(self.hashes, 'macho_dylib_hash', None)
            macho_import_hash = getattr(self.hashes, 'macho_import_hash', None)
            macho_export_hash = getattr(self.hashes, 'macho_export_hash', None)
            macho_entitlement_hash = getattr(self.hashes, 'macho_entitlement_hash', None)
            macho_symhash = getattr(self.hashes, 'macho_symhash', None)
            # APK hashes
            permhash = getattr(self.hashes, 'permhash', None)

            data = [[
                sha256,
                md5,
                sha1,
                ssdeep_hash,
                tlsh_hash,
                authentihash,
                imphash,
                impfuzzy,
                typerefhash,
                richhash,
                richpe_hash,
                richpv_hash,
                richpv_hash_sorted,
                import_hash,
                export_hash,
                section_hash,
                symbol_hash,
                dynamic_hash,
                macho_dylib_hash,
                macho_import_hash,
                macho_export_hash,
                macho_entitlement_hash,
                macho_symhash,
                permhash,
                datetime.now(timezone.utc)
            ]]

            column_names = [
                'sha256', 'md5', 'sha1', 'ssdeep_hash', 'tlsh_hash',
                'authentihash', 'imphash', 'impfuzzy', 'typerefhash',
                'richhash', 'richpe_hash', 'richpv_hash', 'richpv_hash_sorted',
                'import_hash', 'export_hash', 'section_hash', 'symbol_hash', 'dynamic_hash',
                'macho_dylib_hash', 'macho_import_hash', 'macho_export_hash',
                'macho_entitlement_hash', 'macho_symhash',
                'permhash',
                'analysis_date'
            ]

            column_type_names = [
                # sha256, md5, sha1
                'String', 'String', 'String',
                # ssdeep_hash, tlsh_hash
                'Nullable(String)', 'Nullable(String)',
                # authentihash, imphash, impfuzzy, typerefhash
                'Nullable(String)', 'Nullable(String)',
                'Nullable(String)', 'Nullable(String)',
                # richhash, richpe_hash, richpv_hash, richpv_hash_sorted
                'Nullable(String)', 'Nullable(String)',
                'Nullable(String)', 'Nullable(String)',
                # import_hash, export_hash, section_hash, symbol_hash, dynamic_hash
                'Nullable(FixedString(32))', 'Nullable(FixedString(32))',
                'Nullable(FixedString(32))', 'Nullable(FixedString(32))',
                'Nullable(FixedString(32))',
                # macho_dylib_hash, macho_import_hash, macho_export_hash, macho_entitlement_hash, macho_symhash
                'Nullable(FixedString(32))', 'Nullable(FixedString(32))',
                'Nullable(FixedString(32))', 'Nullable(FixedString(32))',
                'Nullable(FixedString(32))',
                # permhash (APK)
                'Nullable(FixedString(64))',
                # analysis_date
                'DateTime64(3, \'UTC\')'
            ]

            return (data, column_names, column_type_names)

    def get_clickhouse_table(self) -> str:
        return "redb_hashes"

    def tag(self):
        return Tag.HASH.value