예제 #1
0
class KnotHash(object):
    def __init__(self):
        self.circular_list = CircularList([i for i in range(256)])
        self.pos = 0
        self.skip = 0

    def create_hash(self, s):
        '''Creates a knot hash from a string of input'''

        # create lengths from ASCII conversions
        knot_lengths = [ord(c) for c in s]
        # append standard end lengths
        knot_lengths += [17, 31, 73, 47, 23]

        # perform ties of each lenght 64 times
        for i in range(64):
            for l in knot_lengths:
                self.tie(l)

        # reduce hash to dense hash
        dense_hash = self.__reduce()

        # create and return final string of hex values
        final_string = []
        for n in dense_hash:
            h = hex(n)
            final_string.append(h.replace('0x', '').zfill(2))

        return ''.join(final_string)

    def reset(self):
        '''Resets position and skip to 0'''
        self.circular_list = CircularList([i for i in range(256)])
        self.pos = 0
        self.skip = 0

    def tie(self, length):
        '''Reverse portion of array for user-passed length, increases positiona
        and skip tracker variables'''

        # identify end of list
        end = self.pos + length

        # creat sub-array and reverse
        sub = self.circular_list.index(self.pos, end)
        reverse = sub[::-1]

        # replace all values
        self.circular_list.replace(self.pos, reverse)

        # move position
        self.pos = end + self.skip
        if self.pos > len(self.circular_list.array):
            self.pos %= len(self.circular_list.array)

        # increase skip size
        self.skip += 1

    def __reduce(self):
        '''Reduces a hash to a dense hash'''

        # create empty list to populate with dense hash
        dense_hash = []

        # iterate through array in groups of 16
        pos = 0
        while pos < len(self.circular_list.array):
            num = xor(self.circular_list.index(pos, pos + 16))
            dense_hash.append(num)
            pos += 16

        return dense_hash