Exemple #1
0
    def match(self, key, data):
        """
        Check whether the bytes are likely (within collision probability) to be
        a member of the set represented by the filter.

        Args:
            key (ByteArray): The siphash key.
            data (ByteArray): The data to find.

        Returns:
            bool: Whether the data is likely to be in the set.
        """
        # An empty filter or empty data can't possibly match anything.
        if len(self.filterData) == 0 or len(data) == 0:
            return False
        if len(key) != 16:
            raise DecredError(f"key length {len(key)} != 16 not allowed")

        # Hash the search term with the same parameters as the filter.
        term = (siphash24(data.bytes(),
                          key=key.bytes(),
                          encoder=SiphashEncoder).littleEndian().int())
        term = (term * self.modulusNM) >> 64

        # Go through the search filter and look for the desired value.
        bitStream = BitReader(self.filterData)
        lastValue = 0
        readInt = self.readFullUint64
        while lastValue <= term:
            # Read the difference between previous and new value from
            # bitstream.
            try:
                value = readInt(bitStream)
            except EncodingError:  # out of bytes
                return False

            # Add the previous value to it.
            value += lastValue
            if value == term:
                return True

            lastValue = value

        return False
Exemple #2
0
def test_shortened_key(inp, key, expected):
    with pytest.raises(ValueError):
        siphash24(inp, key)
Exemple #3
0
def test_siphash24(inp, key, expected):
    rs = siphash24(inp, key)
    assert rs == hexlify(expected)
Exemple #4
0
    def matchAny(self, key, data):
        """
        Check whether any of the supplied data values are likely (within
        collision probability) to be a member of the set represented by the
        filter faster than calling match() for each value individually.

        Args:
            key (ByteArray): The siphash key.
            data list(ByteArray): The data to find.

        Returns:
            bool: Whether any member of the data is likely to be in the set.
        """
        # An empty filter or empty data can't possibly match anything.
        if len(self.filterData) == 0 or len(data) == 0:
            return False

        # Create an uncompressed filter of the search values.
        values = []
        mod = self.modulusNM
        keyB = key.bytes()
        for d in data:
            if len(d) == 0:
                continue
            v = (siphash24(d.bytes(), key=keyB,
                           encoder=SiphashEncoder).littleEndian().int())
            values.append((v * mod) >> 64)

        if len(values) == 0:
            return False

        values.sort()

        # Zip down the filters, comparing values until we either run out of
        # values to compare in one of the filters or we reach a matching value.
        bitStream = BitReader(self.filterData)
        searchSize = len(data)
        searchIdx = 0
        filterVal = 0

        readInt = self.readFullUint64
        for i in range(self.n):
            # Read the next item to compare from the filter.
            try:
                delta = readInt(bitStream)
            except EncodingError:  # out of bytes
                return False

            filterVal += delta

            again = False
            # Iterate through the values to search until either a match is found
            # or the search value exceeds the current filter value.
            while searchIdx < searchSize:
                searchVal = values[searchIdx]
                if searchVal == filterVal:
                    return True

                # Move to the next filter item once the current search value
                # exceeds it.
                if searchVal > filterVal:
                    again = True
                    break

                searchIdx += 1

            if again:
                continue
            # Exit early when there are no more values to search for.
            break

        return False
Exemple #5
0
def test_shortened_key(inp, key, expected):
    with pytest.raises(ValueError):
        siphash24(inp, key)
    with pytest.raises(ValueError):
        siphashx24(inp, key)
Exemple #6
0
def test_siphash24(inp, key, expected):
    rs = siphash24(inp, key)
    assert rs == hexlify(expected)