def parse_rich_header(self):
        """Parses the rich header
        see https://www.ntcore.com/files/richsign.htm for more information

        Structure:
        00 DanS ^ checksum, checksum, checksum, checksum
        10 Symbol RVA ^ checksum, Symbol size ^ checksum...
        ...
        XX Rich, checksum, 0, 0,...
        """

        # Rich Header constants
        #
        DANS = 0x536E6144  # 'DanS' as dword
        RICH = 0x68636952  # 'Rich' as dword

        rich_index = self.__data__.find(
            b"Rich", 0x80, self.OPTIONAL_HEADER.get_file_offset()
        )
        if rich_index == -1:
            return None

        # Read a block of data
        try:
            # The end of the structure is 8 bytes after the start of the Rich
            # string (although there is padding after this).
            rich_data = self.__data__[0x80 : rich_index + 8]
            # Make the data have length a multiple of 4, otherwise the
            # subsequent parsing will fail. It's not impossible that we retrieve
            # truncated data that is not a multiple.
            rich_data = rich_data[: 4 * (len(rich_data) // 4)]
            data = list(struct.unpack("<{0}I".format(len(rich_data) // 4), rich_data))
            if RICH not in data:
                return None
        except PEFormatError:
            return None

        # get key, raw_data and clear_data
        key = struct.pack("<L", data[data.index(RICH) + 1])
        result = {"key": key}

        raw_data = rich_data[: rich_data.find(b"Rich")]
        result["raw_data"] = raw_data

        ord_ = lambda c: ord(c) if not isinstance(c, int) else c

        clear_data = bytearray()
        for idx, val in enumerate(raw_data):
            clear_data.append(ord_(val) ^ ord_(key[idx % len(key)]))
        result["clear_data"] = bytes(clear_data)

        # PE files are stored in little-endian order, the same byte order as an x86
        # https://wiki.osdev.org/PE
        checksum = int.from_bytes(key, "little")
        # the checksum should be present 3 times after the DanS signature
        if (
            data[0] ^ checksum != DANS
            or data[1] != checksum
            or data[2] != checksum
            or data[3] != checksum
        ):
            self.__warnings.append(
                "Rich Header is not in Microsoft format, possibly malformed"
            )

        result["checksum"] = checksum
        headervalues = []
        result["values"] = headervalues

        data = data[4:]
        for i in range(len(data) // 2):
            # Stop until the Rich footer signature is found
            #
            if data[2 * i] == RICH:
                # it should be followed by the checksum
                #
                if data[2 * i + 1] != checksum:
                    self.__warnings.append("Rich Header is malformed")
                break

            # header values come by pairs
            #
            headervalues += [data[2 * i] ^ checksum, data[2 * i + 1] ^ checksum]
        return result
Parses the rich header
        see https://www.ntcore.com/files/richsign.htm for more information

        Structure:
        00 DanS ^ checksum, checksum, checksum, checksum
        10 Symbol RVA ^ checksum, Symbol size ^ checksum...
        ...
        XX Rich, checksum, 0, 0,...
        
pefile.py