Пример #1
0
 def test_stress(self):
     """
     Stress test BitStream by writings lots of numbers of different bit 
     sizes and reading them back.
     """
     # num_writes = 10000
     num_writes = 1000
     min_bit_length = 1
     max_bit_length = 8192
     
     # Generate the numbers
     nums = []
     total_bit_length = 0
     for i in range(0, num_writes):
         bit_length = random.randint(min_bit_length, max_bit_length)
         total_bit_length += bit_length
         val = random.randint(0, 2**bit_length - 1)
         nums.append({"bit_length" : bit_length, "value" : val})
         
     # Write them to a BitStream object
     bitstream = BitStream()
     for num in nums:
         bitstream.put_num(num["value"], num["bit_length"])
         
     # Check the BitStream length and current position
     self.assertEquals(bitstream.get_length(),total_bit_length)
     self.assertEquals(bitstream.get_current_pos(),total_bit_length)
     
     # Read all numbers back
     bitstream.seek(0)
     for num in nums:
         self.assertEquals(bitstream.get_num(num["bit_length"]),num["value"])
Пример #2
0
    def test_hex_basic(self):
        """
        This method tests put_hex's and get_hex's basic functionality.
        """
        bitstream = BitStream()

        # Generate a random string of hex digits, ie: ('0'-'9'|'a'-'f'|'A'-'F')*
        valid_hex_digits = "0123456789abcdefABCDEF"
        num_digits = 50
        digits = ""
        for i in range(0, num_digits):
            digits += random.choice(valid_hex_digits)

        # Put those digits in the BitStream...
        bitstream.put_hex(digits)

        # ...and get them back
        bitstream.seek(0)
        read_digits = bitstream.get_hex(len(digits) *
                                        4)  # 1 hex digit == 4 bits

        # Check that the hexadecimal digits were recovered correctly
        # Note that case information may be lost. Comparison must be case
        # insensitive (ie. 'a9Bc' and 'A9bC' are equal)
        self.assertEqual(read_digits.lower(), digits.lower())
Пример #3
0
    def test_put_bitstream_copy_self(self):
        """
        Test using the put_bitstream_copy method with the same BitStream object 
        as origin and destination.
        """
        bitstream = BitStream()

        # Generate a random string of bits, ie: ('0' | '1')*
        num_bits = 50
        bits = ""
        for i in range(0, num_bits):
            bits += random.choice(
                ('0', '1'))  # inefficient, but ok for a test.

        # Put those bits in the BitStream...
        bitstream.put_bit_dump_string(bits)

        # ... copy the bitstream into itself at any point:
        bitstream.seek(random.randint(0, 50))
        bitstream.put_bitstream_copy(bitstream)

        # Check that the bitstream was unchanged by the previous operation:
        # (overwriting data with the same data is the same as doing nothing,
        # except that the current position is changed to the end of the stream)
        self.assertEquals(bitstream.get_length(), num_bits)
        self.assertEquals(bitstream.get_current_pos(), num_bits)
        bitstream.seek(0)
        read_bits = bitstream.get_bit_dump_string(bitstream.get_length())
        self.assertEqual(read_bits, bits)
Пример #4
0
    def test_stress(self):
        """
        Stress test BitStream by writings lots of numbers of different bit 
        sizes and reading them back.
        """
        # num_writes = 10000
        num_writes = 1000
        min_bit_length = 1
        max_bit_length = 8192

        # Generate the numbers
        nums = []
        total_bit_length = 0
        for i in range(0, num_writes):
            bit_length = random.randint(min_bit_length, max_bit_length)
            total_bit_length += bit_length
            val = random.randint(0, 2**bit_length - 1)
            nums.append({"bit_length": bit_length, "value": val})

        # Write them to a BitStream object
        bitstream = BitStream()
        for num in nums:
            bitstream.put_num(num["value"], num["bit_length"])

        # Check the BitStream length and current position
        self.assertEquals(bitstream.get_length(), total_bit_length)
        self.assertEquals(bitstream.get_current_pos(), total_bit_length)

        # Read all numbers back
        bitstream.seek(0)
        for num in nums:
            self.assertEquals(bitstream.get_num(num["bit_length"]),
                              num["value"])
Пример #5
0
    def test_string_ascii(self):
        """
        Test basic put_string and get_string behavior, using ASCII strings.
        """
        bitstream = BitStream()
        string1 = "Test string "  # 12 chars/bytes
        string2 = "using only ASCII characters (0-126):\n\t"  # 38 chars/bytes
        string3 = "Hello World!"  # 12 chars/bytes

        # Store our message in 3 writes
        bitstream.put_string(string1)
        bitstream.put_string(string2)
        bitstream.put_string(string3)

        # Sanity check:
        self.assertEquals(bitstream.get_length(), (12 + 38 + 12) * 8)
        self.assertEquals(bitstream.get_current_pos(), (12 + 38 + 12) * 8)

        # Retrieve our message in 2 reads
        bitstream.seek(0)
        self.assertEquals(
            bitstream.get_string(29 * 8),  # read 29 bytes
            "Test string using only ASCII ")
        self.assertEquals(
            bitstream.get_string(33 * 8),  # read 33 bytes
            "characters (0-126):\n\tHello World!")
Пример #6
0
 def test_put_bitstream_copy_self(self):
     """
     Test using the put_bitstream_copy method with the same BitStream object 
     as origin and destination.
     """
     bitstream = BitStream()
     
     # Generate a random string of bits, ie: ('0' | '1')*
     num_bits = 50        
     bits = ""
     for i in range(0,num_bits):
         bits += random.choice(('0','1')) # inefficient, but ok for a test.
         
     # Put those bits in the BitStream...
     bitstream.put_bit_dump_string(bits)
     
     # ... copy the bitstream into itself at any point:
     bitstream.seek(random.randint(0,50))
     bitstream.put_bitstream_copy(bitstream)
     
     # Check that the bitstream was unchanged by the previous operation:
     # (overwriting data with the same data is the same as doing nothing,
     # except that the current position is changed to the end of the stream)
     self.assertEquals(bitstream.get_length(),num_bits)
     self.assertEquals(bitstream.get_current_pos(),num_bits)
     bitstream.seek(0)
     read_bits = bitstream.get_bit_dump_string(bitstream.get_length())
     self.assertEqual(read_bits, bits)
Пример #7
0
 def test_get_hex_invalid_length(self):
     """
     Test that trying to read a number of bits that is not a multiple of 4 
     as hex data raises an exception.
     """
     bitstream = BitStream()
     bitstream.put_hex("DfF7CE69fF5478A") # 15 digits, 60 bits
     bitstream.seek(0)
     self.assertRaises(ValueError, 
                       bitstream.get_hex, 47) # read 11.75 hex digits?
Пример #8
0
 def test_get_base64_invalid_length(self):
     """
     Test that trying to read a number of bits that is not a multiple of 8 
     as base64 data raises an exception.
     """
     bitstream = BitStream()
     bitstream.put_base64("Zm9vYmE=") # 40 bits
     bitstream.seek(0)
     self.assertRaises(ValueError, 
                       bitstream.get_base64, 26) # read 3.25 bytes?
Пример #9
0
 def test_string_character_zero(self):
     """
     Test that we are handling character zero ('\\0') correctly.
     """
     bitstream = BitStream()
     bitstream.put_string("Evil \0String.") # 13 chars/bytes
     self.assertEquals(bitstream.get_length(),13*8)
     bitstream.seek(0)
     self.assertEquals(bitstream.get_string(bitstream.get_length()),    
                       "Evil \0String.")
Пример #10
0
 def test_get_hex_invalid_length(self):
     """
     Test that trying to read a number of bits that is not a multiple of 4 
     as hex data raises an exception.
     """
     bitstream = BitStream()
     bitstream.put_hex("DfF7CE69fF5478A")  # 15 digits, 60 bits
     bitstream.seek(0)
     self.assertRaises(ValueError, bitstream.get_hex,
                       47)  # read 11.75 hex digits?
Пример #11
0
 def test_get_base64_invalid_length(self):
     """
     Test that trying to read a number of bits that is not a multiple of 8 
     as base64 data raises an exception.
     """
     bitstream = BitStream()
     bitstream.put_base64("Zm9vYmE=")  # 40 bits
     bitstream.seek(0)
     self.assertRaises(ValueError, bitstream.get_base64,
                       26)  # read 3.25 bytes?
Пример #12
0
 def test_string_character_zero(self):
     """
     Test that we are handling character zero ('\\0') correctly.
     """
     bitstream = BitStream()
     bitstream.put_string("Evil \0String.")  # 13 chars/bytes
     self.assertEquals(bitstream.get_length(), 13 * 8)
     bitstream.seek(0)
     self.assertEquals(bitstream.get_string(bitstream.get_length()),
                       "Evil \0String.")
Пример #13
0
 def test_base64_basic(self):
     """
     This method tests put_base64's and get_base64's basic functionality.
     """
     bitstream = BitStream()
     
     # We use the Base64 Test Vectors defined in RFC4648.
     # http://www.ietf.org/rfc/rfc4648.txt
     test_vectors = [("",""),
                     ("f","Zg=="),
                     ("fo","Zm8="),
                     ("foo","Zm9v"),
                     ("foob","Zm9vYg=="),
                     ("fooba","Zm9vYmE="),
                     ("foobar","Zm9vYmFy")]
     
     # STEP 1:
     # For each test vector, we write its value to the bitstream as a string 
     # then read it as base64 data.
     for (str_val, base64_val) in test_vectors:
         vector_bit_length = len(str_val)*8
         bitstream.put_string(str_val)
         bitstream.seek(0)
         self.assertEquals(bitstream.get_base64(vector_bit_length),
                           base64_val)
         bitstream.seek(0)
         
     # NOTE that we are overwriting multiple times our bitstream, this is 
     # also a feature of BitStream we are testing in this test case.
     
     # STEP 2:
     # For each test vector, we write its value to the bitstream as base64  
     # data, then read it as string *and* base64 data.
     for (str_val, base64_val) in test_vectors:
         vector_bit_length = len(str_val)*8
         bitstream.put_base64(base64_val)
         bitstream.seek(0)
         self.assertEquals(bitstream.get_string(vector_bit_length),
                           str_val)
         bitstream.seek(0)
         self.assertEquals(bitstream.get_base64(vector_bit_length),
                           base64_val)
         bitstream.seek(0)
     
     # STEP 3:
     # For each test vector, we write its value to a NEW bitstream as base64  
     # data, and make sure the length of the stream is the expected one.
     for (str_val, base64_val) in test_vectors:
         vector_bit_length = len(str_val)*8
         new_bs = BitStream()
         new_bs.put_base64(base64_val)
         self.assertEquals(new_bs.get_length(), vector_bit_length)
         self.assertEquals(new_bs.get_current_pos(), vector_bit_length)
Пример #14
0
 def test_string_unicode(self):
     """
     Test basic put_string and get_string support for python unicode objects.
     """
     bitstream = BitStream()
     unicode_string = u"ÄäÜüßЯБГДЖЙŁĄŻĘĆŃŚŹてすとアイウエオカキクケコサシスセソタチツテ"
     bitstream.put_string(unicode_string)
     bitstream.seek(0)
     # Note: the string is read back as a "normal" UTF-8 string, unicode
     #       type information is not stored in the bitstream.
     self.assertEquals(bitstream.get_string(bitstream.get_length()),
                       "ÄäÜüßЯБГДЖЙŁĄŻĘĆŃŚŹてすとアイウエオカキクケコサシスセソタチツテ")
Пример #15
0
 def test_string_unicode(self):
     """
     Test basic put_string and get_string support for python unicode objects.
     """
     bitstream = BitStream()
     unicode_string = u"ÄäÜüßЯБГДЖЙŁĄŻĘĆŃŚŹてすとアイウエオカキクケコサシスセソタチツテ"
     bitstream.put_string(unicode_string)
     bitstream.seek(0)
     # Note: the string is read back as a "normal" UTF-8 string, unicode
     #       type information is not stored in the bitstream.
     self.assertEquals(bitstream.get_string(bitstream.get_length()),    
                       "ÄäÜüßЯБГДЖЙŁĄŻĘĆŃŚŹてすとアイウエオカキクケコサシスセソタチツテ")
Пример #16
0
 def test_get_bit_dump_string_zero_bits(self):
     """
     Test that reading zero bits from the stream as a bit dump string 
     results in getting the empty string: \"\".
     """
     bitstream = BitStream()
     self.assertEquals(bitstream.get_bit_dump_string(0), "")
     
     # Store some bits in the stream.
     bitstream.put_bit_dump_string("0001110101") # 10 bits
     
     bitstream.seek(0)
     self.assertEquals(bitstream.get_bit_dump_string(0), "")
Пример #17
0
 def test_get_string_zero_bits(self):
     """
     Test that reading zero bits from the stream as a string results in  
     getting the empty string: \"\".
     """
     bitstream = BitStream()
     self.assertEquals(bitstream.get_string(0), "")
     
     # Store a string in the stream.
     bitstream.put_string("Hello World!")
     
     bitstream.seek(0)
     self.assertEquals(bitstream.get_string(0), "")
Пример #18
0
 def test_get_hex_zero_bits(self):
     """
     Test that reading zero bits from the stream as hex data results in 
     getting the empty string: \"\".
     """
     bitstream = BitStream()
     self.assertEquals(bitstream.get_hex(0), "")
     
     # Store some hex data in the stream.
     bitstream.put_hex("DfF7CE69fF5478A") # 15 digits, 60 bits
     
     bitstream.seek(0)
     self.assertEquals(bitstream.get_hex(0), "")
Пример #19
0
    def test_get_hex_zero_bits(self):
        """
        Test that reading zero bits from the stream as hex data results in 
        getting the empty string: \"\".
        """
        bitstream = BitStream()
        self.assertEquals(bitstream.get_hex(0), "")

        # Store some hex data in the stream.
        bitstream.put_hex("DfF7CE69fF5478A")  # 15 digits, 60 bits

        bitstream.seek(0)
        self.assertEquals(bitstream.get_hex(0), "")
Пример #20
0
    def test_get_string_zero_bits(self):
        """
        Test that reading zero bits from the stream as a string results in  
        getting the empty string: \"\".
        """
        bitstream = BitStream()
        self.assertEquals(bitstream.get_string(0), "")

        # Store a string in the stream.
        bitstream.put_string("Hello World!")

        bitstream.seek(0)
        self.assertEquals(bitstream.get_string(0), "")
Пример #21
0
 def test_get_base64_zero_bits(self):
     """
     Test that reading zero bits from the stream as base64 data results in 
     getting the empty string: \"\".
     """
     bitstream = BitStream()
     self.assertEquals(bitstream.get_base64(0), "")
     
     # Store some base64 data in the stream.
     bitstream.put_base64("Zm9vYmE=") # 40 bits
     
     bitstream.seek(0)
     self.assertEquals(bitstream.get_base64(0), "")
Пример #22
0
    def test_get_bit_dump_string_zero_bits(self):
        """
        Test that reading zero bits from the stream as a bit dump string 
        results in getting the empty string: \"\".
        """
        bitstream = BitStream()
        self.assertEquals(bitstream.get_bit_dump_string(0), "")

        # Store some bits in the stream.
        bitstream.put_bit_dump_string("0001110101")  # 10 bits

        bitstream.seek(0)
        self.assertEquals(bitstream.get_bit_dump_string(0), "")
Пример #23
0
    def test_get_base64_zero_bits(self):
        """
        Test that reading zero bits from the stream as base64 data results in 
        getting the empty string: \"\".
        """
        bitstream = BitStream()
        self.assertEquals(bitstream.get_base64(0), "")

        # Store some base64 data in the stream.
        bitstream.put_base64("Zm9vYmE=")  # 40 bits

        bitstream.seek(0)
        self.assertEquals(bitstream.get_base64(0), "")
Пример #24
0
    def test_get_string_non_bytable_size(self):
        """
        Test that calling get_string with a bit_length that is not a multiple 
        of 8 raises an exception.
        That is, we cannot read partial bytes as string data.
        """
        bitstream = BitStream()
        bitstream.put_string("Hello World!")
        bitstream.seek(0)

        self.assertRaises(ValueError, bitstream.get_string, 18)

        # Current position should not have been changed
        self.assertEquals(bitstream.get_current_pos(), 0)
Пример #25
0
 def test_get_string_non_bytable_size(self):
     """
     Test that calling get_string with a bit_length that is not a multiple 
     of 8 raises an exception.
     That is, we cannot read partial bytes as string data.
     """
     bitstream = BitStream()
     bitstream.put_string("Hello World!")
     bitstream.seek(0)
     
     self.assertRaises(ValueError, bitstream.get_string, 18)
     
     # Current position should not have been changed
     self.assertEquals(bitstream.get_current_pos(),0)
Пример #26
0
 def test_get_num_zero_bits(self):
     """
     Test that reading zero bits from the stream as a number results in 
     getting the number 0.
     """
     bitstream = BitStream()
     self.assertEquals(bitstream.get_num(0), 0)
     
     # Store a 64-bit integer in the stream.
     num = int('00000000000000110101011001010011'
               '00101100001000101000100110101111', 2)
     bitstream.put_num(num, 64)
     
     bitstream.seek(0)
     self.assertEquals(bitstream.get_num(0), 0)
Пример #27
0
    def test_base64_basic(self):
        """
        This method tests put_base64's and get_base64's basic functionality.
        """
        bitstream = BitStream()

        # We use the Base64 Test Vectors defined in RFC4648.
        # http://www.ietf.org/rfc/rfc4648.txt
        test_vectors = [("", ""), ("f", "Zg=="), ("fo", "Zm8="),
                        ("foo", "Zm9v"), ("foob", "Zm9vYg=="),
                        ("fooba", "Zm9vYmE="), ("foobar", "Zm9vYmFy")]

        # STEP 1:
        # For each test vector, we write its value to the bitstream as a string
        # then read it as base64 data.
        for (str_val, base64_val) in test_vectors:
            vector_bit_length = len(str_val) * 8
            bitstream.put_string(str_val)
            bitstream.seek(0)
            self.assertEquals(bitstream.get_base64(vector_bit_length),
                              base64_val)
            bitstream.seek(0)

        # NOTE that we are overwriting multiple times our bitstream, this is
        # also a feature of BitStream we are testing in this test case.

        # STEP 2:
        # For each test vector, we write its value to the bitstream as base64
        # data, then read it as string *and* base64 data.
        for (str_val, base64_val) in test_vectors:
            vector_bit_length = len(str_val) * 8
            bitstream.put_base64(base64_val)
            bitstream.seek(0)
            self.assertEquals(bitstream.get_string(vector_bit_length), str_val)
            bitstream.seek(0)
            self.assertEquals(bitstream.get_base64(vector_bit_length),
                              base64_val)
            bitstream.seek(0)

        # STEP 3:
        # For each test vector, we write its value to a NEW bitstream as base64
        # data, and make sure the length of the stream is the expected one.
        for (str_val, base64_val) in test_vectors:
            vector_bit_length = len(str_val) * 8
            new_bs = BitStream()
            new_bs.put_base64(base64_val)
            self.assertEquals(new_bs.get_length(), vector_bit_length)
            self.assertEquals(new_bs.get_current_pos(), vector_bit_length)
Пример #28
0
    def test_get_num_zero_bits(self):
        """
        Test that reading zero bits from the stream as a number results in 
        getting the number 0.
        """
        bitstream = BitStream()
        self.assertEquals(bitstream.get_num(0), 0)

        # Store a 64-bit integer in the stream.
        num = int(
            '00000000000000110101011001010011'
            '00101100001000101000100110101111', 2)
        bitstream.put_num(num, 64)

        bitstream.seek(0)
        self.assertEquals(bitstream.get_num(0), 0)
Пример #29
0
    def test_get_string_utf8_read_partial_characters(self):
        """
        Test that it is possible to read "partial" utf-8 characters from the 
        bitstream and that concatenation restores the full character/glyph.
        """
        bitstream = BitStream()
        string = "てすとアイウエオカキクケコサシスセソタチツテ"  # 22 chars, 66 bytes
        bitstream.put_string(string)
        bitstream.seek(0)

        # First read 32 bytes
        readString = bitstream.get_string(32 * 8)
        self.assertEquals(readString, "てすとアイウエオカキ\xef\xbd")
        # Now read the rest
        readString += bitstream.get_string(34 * 8)
        self.assertEquals(readString, "てすとアイウエオカキクケコサシスセソタチツテ")
Пример #30
0
 def test_get_string_utf8_read_partial_characters(self):
     """
     Test that it is possible to read "partial" utf-8 characters from the 
     bitstream and that concatenation restores the full character/glyph.
     """
     bitstream = BitStream()
     string = "てすとアイウエオカキクケコサシスセソタチツテ" # 22 chars, 66 bytes
     bitstream.put_string(string)
     bitstream.seek(0)
     
     # First read 32 bytes
     readString = bitstream.get_string(32*8)
     self.assertEquals(readString,"てすとアイウエオカキ\xef\xbd") 
     # Now read the rest
     readString += bitstream.get_string(34*8)
     self.assertEquals(readString,"てすとアイウエオカキクケコサシスセソタチツテ") 
Пример #31
0
 def test_get_byte_beyond_eos(self):
     """
     Test that trying to read beyond the end of the stream raises an 
     exception when calling get_byte(...).
     """
     bitstream = BitStream()
     
     self.assertRaises(NotEnoughBitsInStreamError, bitstream.get_byte)
     # Current position should not have been changed
     self.assertEquals(bitstream.get_current_pos(),0)
     
     bitstream.put_byte(14)
     bitstream.seek(1)
     # Read a single bit beyond EOS
     self.assertRaises(NotEnoughBitsInStreamError, bitstream.get_byte)
     # Current position should not have been changed
     self.assertEquals(bitstream.get_current_pos(),1)
Пример #32
0
    def test_get_byte_beyond_eos(self):
        """
        Test that trying to read beyond the end of the stream raises an 
        exception when calling get_byte(...).
        """
        bitstream = BitStream()

        self.assertRaises(NotEnoughBitsInStreamError, bitstream.get_byte)
        # Current position should not have been changed
        self.assertEquals(bitstream.get_current_pos(), 0)

        bitstream.put_byte(14)
        bitstream.seek(1)
        # Read a single bit beyond EOS
        self.assertRaises(NotEnoughBitsInStreamError, bitstream.get_byte)
        # Current position should not have been changed
        self.assertEquals(bitstream.get_current_pos(), 1)
Пример #33
0
    def test_get_base64_beyond_eos(self):
        """
        Test that trying to read beyond the end of the stream raises an 
        exception when calling get_base64(...).
        """
        bitstream = BitStream()

        self.assertRaises(NotEnoughBitsInStreamError, bitstream.get_base64, 8)
        # Current position should not have been changed
        self.assertEquals(bitstream.get_current_pos(), 0)

        bitstream.put_base64("Zm9vYmE=")  # 40 bits
        bitstream.seek(0)
        # Read beyond EOS
        self.assertRaises(NotEnoughBitsInStreamError, bitstream.get_base64, 48)
        # Current position should not have been changed
        self.assertEquals(bitstream.get_current_pos(), 0)
Пример #34
0
    def test_get_hex_beyond_eos(self):
        """
        Test that trying to read beyond the end of the stream raises an 
        exception when calling get_hex(...).
        """
        bitstream = BitStream()

        self.assertRaises(NotEnoughBitsInStreamError, bitstream.get_hex, 1)
        # Current position should not have been changed
        self.assertEquals(bitstream.get_current_pos(), 0)

        bitstream.put_hex("DfF7CE69fF5478A")  # 15 digits, 60 bits
        bitstream.seek(0)
        # Read beyond EOS
        self.assertRaises(NotEnoughBitsInStreamError, bitstream.get_hex, 61)
        # Current position should not have been changed
        self.assertEquals(bitstream.get_current_pos(), 0)
Пример #35
0
    def test_get_string_beyond_eos(self):
        """
        Test that trying to read beyond the end of the stream raises an 
        exception when calling get_string(...).
        """
        bitstream = BitStream()

        self.assertRaises(NotEnoughBitsInStreamError, bitstream.get_string, 1)
        # Current position should not have been changed
        self.assertEquals(bitstream.get_current_pos(), 0)

        bitstream.put_string("Hello World!")  # 12 chars/bytes
        bitstream.seek(0)
        # Read beyond EOS
        self.assertRaises(NotEnoughBitsInStreamError, bitstream.get_string,
                          13 * 8)
        # Current position should not have been changed
        self.assertEquals(bitstream.get_current_pos(), 0)
Пример #36
0
 def test_get_string_beyond_eos(self):
     """
     Test that trying to read beyond the end of the stream raises an 
     exception when calling get_string(...).
     """
     bitstream = BitStream()
     
     self.assertRaises(NotEnoughBitsInStreamError, bitstream.get_string, 1)
     # Current position should not have been changed
     self.assertEquals(bitstream.get_current_pos(),0)
     
     bitstream.put_string("Hello World!")    # 12 chars/bytes
     bitstream.seek(0)
     # Read beyond EOS
     self.assertRaises(NotEnoughBitsInStreamError, bitstream.get_string, 
                       13*8)
     # Current position should not have been changed
     self.assertEquals(bitstream.get_current_pos(),0)
Пример #37
0
 def test_get_hex_beyond_eos(self):
     """
     Test that trying to read beyond the end of the stream raises an 
     exception when calling get_hex(...).
     """
     bitstream = BitStream()
     
     self.assertRaises(NotEnoughBitsInStreamError, 
                       bitstream.get_hex, 1)
     # Current position should not have been changed
     self.assertEquals(bitstream.get_current_pos(),0)
     
     bitstream.put_hex("DfF7CE69fF5478A") # 15 digits, 60 bits
     bitstream.seek(0)
     # Read beyond EOS
     self.assertRaises(NotEnoughBitsInStreamError, 
                       bitstream.get_hex, 61)
     # Current position should not have been changed
     self.assertEquals(bitstream.get_current_pos(),0)
Пример #38
0
 def test_get_base64_beyond_eos(self):
     """
     Test that trying to read beyond the end of the stream raises an 
     exception when calling get_base64(...).
     """
     bitstream = BitStream()
     
     self.assertRaises(NotEnoughBitsInStreamError, 
                       bitstream.get_base64, 8)
     # Current position should not have been changed
     self.assertEquals(bitstream.get_current_pos(),0)
     
     bitstream.put_base64("Zm9vYmE=") # 40 bits
     bitstream.seek(0)
     # Read beyond EOS
     self.assertRaises(NotEnoughBitsInStreamError, 
                       bitstream.get_base64, 48)
     # Current position should not have been changed
     self.assertEquals(bitstream.get_current_pos(),0)
Пример #39
0
 def test_num_write_part(self):
     """
     Test that we can write a large number piece by piece and read it as 
     whole number.
     """
     bitstream = BitStream()
     
     # Store a 64-bit integer in the stream.
     num = int('00000000000000110101011001010011'
               '00101100001000101000100110101111', 2)
     
     # ... in 8-bit, 16-bit and 32-bit increments        
     bitstream.put_num(int('00000000',2), 8)
     bitstream.put_num(int('0000001101010110',2), 16)
     bitstream.put_num(int('01010011001011000010001010001001',2), 32)        
     bitstream.put_num(int('10101111',2), 8)
     
     # Get it as a single 64-bit number
     bitstream.seek(0)
     self.assertEqual(bitstream.get_num(64),num)
Пример #40
0
    def test_num_write_part(self):
        """
        Test that we can write a large number piece by piece and read it as 
        whole number.
        """
        bitstream = BitStream()

        # Store a 64-bit integer in the stream.
        num = int(
            '00000000000000110101011001010011'
            '00101100001000101000100110101111', 2)

        # ... in 8-bit, 16-bit and 32-bit increments
        bitstream.put_num(int('00000000', 2), 8)
        bitstream.put_num(int('0000001101010110', 2), 16)
        bitstream.put_num(int('01010011001011000010001010001001', 2), 32)
        bitstream.put_num(int('10101111', 2), 8)

        # Get it as a single 64-bit number
        bitstream.seek(0)
        self.assertEqual(bitstream.get_num(64), num)
Пример #41
0
    def test_byte_basic(self):
        """
        Test basic put_byte and get_byte behavior.
        """
        bitstream = BitStream()
        
        # Put a couple of bytes in the stream:
        
        bytes = [ 12,	# 00001100
	              222,	# 11011110
	              145,	# 10010001
	              42,	# 00101010
	              0,	# 00000000
	              255]	# 11111111
	              
        for byte in bytes:
            bitstream.put_byte(byte)
            
        # Sanity check:
        self.assertEquals(bitstream.get_length(),len(bytes)*8)
        self.assertEquals(bitstream.get_current_pos(),len(bytes)*8)
        
        # Read the bytes back from the stream
        bitstream.seek(0)
        for byte in bytes:
            self.assertEquals(bitstream.get_byte(), byte)
            
        # Read some bits from the stream, interpreting them as bytes, but 
        # without restricting ourselves to 8-bit aligned bytes
        # e.g. read the "byte" defined by bits #4 to #12
        bitstream.seek(4)
        self.assertEquals(bitstream.get_byte(), 205) # 11001101
        bitstream.seek(19)
        self.assertEquals(bitstream.get_byte(), 137) # 10001001
Пример #42
0
 def test_get_num_beyond_eos(self):
     """
     Test than trying to read beyond the end of the stream raises an 
     exception when calling get_num(...).
     """
     bitstream = BitStream()
     
     # Store a 64-bit integer in the stream.
     num = int('00000000000000110101011001010011'
               '00101100001000101000100110101111', 2)
     bitstream.put_num(num, 64)
     
     # Check that trying to read 65 bits from the beginning of the stream
     # raises NotEnoughBitsInStreamError
     bitstream.seek(0)
     self.assertRaises(NotEnoughBitsInStreamError, bitstream.get_num, 65)
     # An invalid read call should not move the position indicator.
     self.assertEquals(bitstream.get_current_pos(), 0)
     
     # Check that trying to read 33 bits from the middle of the stream 
     # (pos = 32) raises NotEnoughBitsInStreamError
     bitstream.seek(32)
     self.assertRaises(NotEnoughBitsInStreamError, bitstream.get_num, 33)
     # An invalid read call should not move the position indicator.
     self.assertEquals(bitstream.get_current_pos(), 32)
     
     # Check that trying to read a single bit while at the end of the stream
     # raises NotEnoughBitsInStreamError
     bitstream.seek(64)
     self.assertRaises(NotEnoughBitsInStreamError, bitstream.get_num, 1)
     # An invalid read call should not move the position indicator.
     self.assertEquals(bitstream.get_current_pos(), 64)
Пример #43
0
    def test_get_num_beyond_eos(self):
        """
        Test than trying to read beyond the end of the stream raises an 
        exception when calling get_num(...).
        """
        bitstream = BitStream()

        # Store a 64-bit integer in the stream.
        num = int(
            '00000000000000110101011001010011'
            '00101100001000101000100110101111', 2)
        bitstream.put_num(num, 64)

        # Check that trying to read 65 bits from the beginning of the stream
        # raises NotEnoughBitsInStreamError
        bitstream.seek(0)
        self.assertRaises(NotEnoughBitsInStreamError, bitstream.get_num, 65)
        # An invalid read call should not move the position indicator.
        self.assertEquals(bitstream.get_current_pos(), 0)

        # Check that trying to read 33 bits from the middle of the stream
        # (pos = 32) raises NotEnoughBitsInStreamError
        bitstream.seek(32)
        self.assertRaises(NotEnoughBitsInStreamError, bitstream.get_num, 33)
        # An invalid read call should not move the position indicator.
        self.assertEquals(bitstream.get_current_pos(), 32)

        # Check that trying to read a single bit while at the end of the stream
        # raises NotEnoughBitsInStreamError
        bitstream.seek(64)
        self.assertRaises(NotEnoughBitsInStreamError, bitstream.get_num, 1)
        # An invalid read call should not move the position indicator.
        self.assertEquals(bitstream.get_current_pos(), 64)
Пример #44
0
 def test_string_utf8(self):
     """
     Test basic put_string and get_string support for UTF-8 strings.
     """
     bitstream = BitStream()
     string1 = "ÄäÜüß"    # 5 chars, 10 bytes
     string2 = "ЯБГДЖЙŁĄŻĘĆŃŚŹ" # 14 chars, 28 bytes
     string3 = "てすとアイウエオカキクケコサシスセソタチツテ"    # 22 chars, 66 bytes
     
     # Store our message in 3 writes
     bitstream.put_string(string1)
     bitstream.put_string(string2)
     bitstream.put_string(string3)
     
     # Sanity check:
     self.assertEquals(bitstream.get_length(),(10+28+66)*8)
     self.assertEquals(bitstream.get_current_pos(),(10+28+66)*8)
     
     # Retrieve the whole message
     bitstream.seek(0)
     self.assertEquals(bitstream.get_string(bitstream.get_length()),    
                       "ÄäÜüßЯБГДЖЙŁĄŻĘĆŃŚŹてすとアイウエオカキクケコサシスセソタチツテ")
Пример #45
0
 def test_bit_dump_string_basic(self):
     """
     This method tests put_bit_dump_string's and get_bit_dump_string's 
     basic functionality.
     """
     bitstream = BitStream()
     
     # Generate a random string of bits, ie: ('0' | '1')*
     num_bits = 50        
     bits = ""
     for i in range(0,num_bits):
         bits += random.choice(('0','1')) # inefficient, but ok for a test.
         
     # Put those bits in the BitStream...
     bitstream.put_bit_dump_string(bits)
     
     # ...and get them back
     bitstream.seek(0)
     read_bits = bitstream.get_bit_dump_string(len(bits))
     
     # Check that the bits were recovered correctly
     self.assertEqual(read_bits, bits)
Пример #46
0
    def test_string_utf8(self):
        """
        Test basic put_string and get_string support for UTF-8 strings.
        """
        bitstream = BitStream()
        string1 = "ÄäÜüß"  # 5 chars, 10 bytes
        string2 = "ЯБГДЖЙŁĄŻĘĆŃŚŹ"  # 14 chars, 28 bytes
        string3 = "てすとアイウエオカキクケコサシスセソタチツテ"  # 22 chars, 66 bytes

        # Store our message in 3 writes
        bitstream.put_string(string1)
        bitstream.put_string(string2)
        bitstream.put_string(string3)

        # Sanity check:
        self.assertEquals(bitstream.get_length(), (10 + 28 + 66) * 8)
        self.assertEquals(bitstream.get_current_pos(), (10 + 28 + 66) * 8)

        # Retrieve the whole message
        bitstream.seek(0)
        self.assertEquals(bitstream.get_string(bitstream.get_length()),
                          "ÄäÜüßЯБГДЖЙŁĄŻĘĆŃŚŹてすとアイウエオカキクケコサシスセソタチツテ")
Пример #47
0
    def test_num_basic(self):
        """
        Test basic put_num and get_num behavior
        """
        bitstream = BitStream()

        # Some parameters
        num_sizes = [4, 8, 16, 32, 64, 128, 256, 2839]
        num_writes = 10
        nums = []

        # Add num_writes integers of each size to nums:
        for i in range(0, len(num_sizes)):
            max_val = 2**num_sizes[i] - 1
            nums.append([])
            for j in range(0, num_writes):
                # append a random number between 0 and max_val, inclusive
                nums[i].append(random.randint(0, max_val))

        # Write all values in nums to the stream
        for i in range(0, len(num_sizes)):
            for j in range(0, num_writes):
                bitstream.put_num(nums[i][j], num_sizes[i])

        # Go back to start of the stream
        bitstream.seek(0)

        # Sanity check:
        expected_length = 0
        for num_size in num_sizes:
            expected_length += num_size * num_writes
        self.assertEqual(bitstream.get_length(), expected_length)

        # Read them back and compare
        for i in range(0, len(num_sizes)):
            for j in range(0, num_writes):
                n = bitstream.get_num(num_sizes[i])
                self.assertEqual(n, nums[i][j])
Пример #48
0
    def test_bit_dump_string_basic(self):
        """
        This method tests put_bit_dump_string's and get_bit_dump_string's 
        basic functionality.
        """
        bitstream = BitStream()

        # Generate a random string of bits, ie: ('0' | '1')*
        num_bits = 50
        bits = ""
        for i in range(0, num_bits):
            bits += random.choice(
                ('0', '1'))  # inefficient, but ok for a test.

        # Put those bits in the BitStream...
        bitstream.put_bit_dump_string(bits)

        # ...and get them back
        bitstream.seek(0)
        read_bits = bitstream.get_bit_dump_string(len(bits))

        # Check that the bits were recovered correctly
        self.assertEqual(read_bits, bits)
Пример #49
0
 def test_num_basic(self):
     """
     Test basic put_num and get_num behavior
     """
     bitstream = BitStream()
     
     # Some parameters
     num_sizes = [4,8,16,32,64,128,256,2839]
     num_writes = 10
     nums = []
     
     # Add num_writes integers of each size to nums:
     for i in range(0,len(num_sizes)):
         max_val = 2**num_sizes[i] - 1
         nums.append([])
         for j in range(0,num_writes):
             # append a random number between 0 and max_val, inclusive
             nums[i].append(random.randint(0, max_val))
              
     # Write all values in nums to the stream
     for i in range(0,len(num_sizes)):
         for j in range(0,num_writes):
             bitstream.put_num(nums[i][j], num_sizes[i])
             
     # Go back to start of the stream
     bitstream.seek(0)
     
     # Sanity check:
     expected_length = 0
     for num_size in num_sizes: expected_length += num_size * num_writes
     self.assertEqual(bitstream.get_length(), expected_length)
             
     # Read them back and compare
     for i in range(0,len(num_sizes)):
         for j in range(0,num_writes):
             n = bitstream.get_num(num_sizes[i])
             self.assertEqual(n, nums[i][j])
Пример #50
0
 def test_string_ascii(self):
     """
     Test basic put_string and get_string behavior, using ASCII strings.
     """
     bitstream = BitStream()
     string1 = "Test string "    # 12 chars/bytes
     string2 = "using only ASCII characters (0-126):\n\t" # 38 chars/bytes
     string3 = "Hello World!"    # 12 chars/bytes
     
     # Store our message in 3 writes
     bitstream.put_string(string1)
     bitstream.put_string(string2)
     bitstream.put_string(string3)
     
     # Sanity check:
     self.assertEquals(bitstream.get_length(),(12+38+12)*8)
     self.assertEquals(bitstream.get_current_pos(),(12+38+12)*8)
     
     # Retrieve our message in 2 reads
     bitstream.seek(0)
     self.assertEquals(bitstream.get_string(29*8),    # read 29 bytes
                       "Test string using only ASCII ")
     self.assertEquals(bitstream.get_string(33*8),    # read 33 bytes
                       "characters (0-126):\n\tHello World!")
Пример #51
0
 def test_hex_basic(self):
     """
     This method tests put_hex's and get_hex's basic functionality.
     """
     bitstream = BitStream()
     
     # Generate a random string of hex digits, ie: ('0'-'9'|'a'-'f'|'A'-'F')*
     valid_hex_digits = "0123456789abcdefABCDEF"
     num_digits = 50        
     digits = ""
     for i in range(0,num_digits):
         digits += random.choice(valid_hex_digits)
         
     # Put those digits in the BitStream...
     bitstream.put_hex(digits)
     
     # ...and get them back
     bitstream.seek(0)
     read_digits = bitstream.get_hex(len(digits)*4) # 1 hex digit == 4 bits
     
     # Check that the hexadecimal digits were recovered correctly
     # Note that case information may be lost. Comparison must be case 
     # insensitive (ie. 'a9Bc' and 'A9bC' are equal)
     self.assertEqual(read_digits.lower(), digits.lower())
Пример #52
0
    def test_multiformat_write_multiformat_read(self):
        """
        This test writes numeric, byte and string data to a stream and then 
        reads the whole stream as binary, hex and base64 data, ensuring that 
        the output is the expected one in each case. 
        """
        # Write a number, 2 bytes and a string
        bitstream = BitStream()
        bitstream.put_num(10438341575639894917, 64)
        bitstream.put_byte(230)
        bitstream.put_byte(191)
        bitstream.put_string("ÄäÜüßTestЯБГДЖЙŁĄŻStringĘĆŃŚŹてす" \
                                 "とアイウエオカキク4234ケコサシスセソタチツテ")

        # Read in binary, hex and base64 formats
        expected_bits = \
            "1001000011011100011100000101101110111100001101010000101110000101" \
            "1110011010111111110000111000010011000011101001001100001110011100" \
            "1100001110111100110000111001111101010100011001010111001101110100" \
            "1101000010101111110100001001000111010000100100111101000010010100" \
            "1101000010010110110100001001100111000101100000011100010010000100" \
            "1100010110111011010100110111010001110010011010010110111001100111" \
            "1100010010011000110001001000011011000101100000111100010110011010" \
            "1100010110111001111000111000000110100110111000111000000110011001" \
            "1110001110000001101010001110111110111101101100011110111110111101" \
            "1011001011101111101111011011001111101111101111011011010011101111" \
            "1011110110110101111011111011110110110110111011111011110110110111" \
            "1110111110111101101110000011010000110010001100110011010011101111" \
            "1011110110111001111011111011110110111010111011111011110110111011" \
            "1110111110111101101111001110111110111101101111011110111110111101" \
            "1011111011101111101111011011111111101111101111101000000011101111" \
            "1011111010000001111011111011111010000010111011111011111010000011"
        expected_hex = \
            "90dc705bbc350b85e6bfc384c3a4c39cc3bcc39f54657374d0afd091d093d094" \
            "d096d099c581c484c5bb537472696e67c498c486c583c59ac5b9e381a6e38199" \
            "e381a8efbdb1efbdb2efbdb3efbdb4efbdb5efbdb6efbdb7efbdb834323334ef" \
            "bdb9efbdbaefbdbbefbdbcefbdbdefbdbeefbdbfefbe80efbe81efbe82efbe83"
        expected_base64 = \
            "kNxwW7w1C4Xmv8OEw6TDnMO8w59UZXN00K/QkdCT0JTQltCZxYHEhMW7U3RyaW5n" \
            "xJjEhsWDxZrFueOBpuOBmeOBqO+9se+9su+9s++9tO+9te+9tu+9t++9uDQyMzTv" \
            "vbnvvbrvvbvvvbzvvb3vvb7vvb/vvoDvvoHvvoLvvoM="

        bitstream.seek(0)
        self.assertEquals( \
                    bitstream.get_bit_dump_string(bitstream.get_length()),
                    expected_bits)
        bitstream.seek(0)
        self.assertEquals(
            bitstream.get_hex(bitstream.get_length()).lower(), expected_hex)
        bitstream.seek(0)
        self.assertEquals(bitstream.get_base64(bitstream.get_length()),
                          expected_base64)
Пример #53
0
 def test_multiformat_write_multiformat_read(self):
     """
     This test writes numeric, byte and string data to a stream and then 
     reads the whole stream as binary, hex and base64 data, ensuring that 
     the output is the expected one in each case. 
     """
     # Write a number, 2 bytes and a string
     bitstream = BitStream()
     bitstream.put_num(10438341575639894917, 64)
     bitstream.put_byte(230)
     bitstream.put_byte(191)
     bitstream.put_string("ÄäÜüßTestЯБГДЖЙŁĄŻStringĘĆŃŚŹてす" \
                              "とアイウエオカキク4234ケコサシスセソタチツテ")
     
     # Read in binary, hex and base64 formats
     expected_bits = \
         "1001000011011100011100000101101110111100001101010000101110000101" \
         "1110011010111111110000111000010011000011101001001100001110011100" \
         "1100001110111100110000111001111101010100011001010111001101110100" \
         "1101000010101111110100001001000111010000100100111101000010010100" \
         "1101000010010110110100001001100111000101100000011100010010000100" \
         "1100010110111011010100110111010001110010011010010110111001100111" \
         "1100010010011000110001001000011011000101100000111100010110011010" \
         "1100010110111001111000111000000110100110111000111000000110011001" \
         "1110001110000001101010001110111110111101101100011110111110111101" \
         "1011001011101111101111011011001111101111101111011011010011101111" \
         "1011110110110101111011111011110110110110111011111011110110110111" \
         "1110111110111101101110000011010000110010001100110011010011101111" \
         "1011110110111001111011111011110110111010111011111011110110111011" \
         "1110111110111101101111001110111110111101101111011110111110111101" \
         "1011111011101111101111011011111111101111101111101000000011101111" \
         "1011111010000001111011111011111010000010111011111011111010000011"
     expected_hex = \
         "90dc705bbc350b85e6bfc384c3a4c39cc3bcc39f54657374d0afd091d093d094" \
         "d096d099c581c484c5bb537472696e67c498c486c583c59ac5b9e381a6e38199" \
         "e381a8efbdb1efbdb2efbdb3efbdb4efbdb5efbdb6efbdb7efbdb834323334ef" \
         "bdb9efbdbaefbdbbefbdbcefbdbdefbdbeefbdbfefbe80efbe81efbe82efbe83"
     expected_base64 = \
         "kNxwW7w1C4Xmv8OEw6TDnMO8w59UZXN00K/QkdCT0JTQltCZxYHEhMW7U3RyaW5n" \
         "xJjEhsWDxZrFueOBpuOBmeOBqO+9se+9su+9s++9tO+9te+9tu+9t++9uDQyMzTv" \
         "vbnvvbrvvbvvvbzvvb3vvb7vvb/vvoDvvoHvvoLvvoM="
         
     bitstream.seek(0)
     self.assertEquals( \
                 bitstream.get_bit_dump_string(bitstream.get_length()),
                 expected_bits)
     bitstream.seek(0)
     self.assertEquals(bitstream.get_hex(bitstream.get_length()).lower(),
                       expected_hex)
     bitstream.seek(0)
     self.assertEquals(bitstream.get_base64(bitstream.get_length()),
                       expected_base64)
Пример #54
0
    def test_num_read_part(self):
        """
        Test that we can read only some bits of a large number and interpret 
        them as a shorter number with the expected value.
        """
        bitstream = BitStream()

        # Store a 64-bit integer in the stream.
        num = int(
            '00000000000000110101011001010011'
            '00101100001000101000100110101111', 2)
        bitstream.put_num(num, 64)

        # Get it as 8-bit numbers
        bitstream.seek(0)
        self.assertEqual(bitstream.get_num(8), int('00000000', 2))
        self.assertEqual(bitstream.get_num(8), int('00000011', 2))
        self.assertEqual(bitstream.get_num(8), int('01010110', 2))
        self.assertEqual(bitstream.get_num(8), int('01010011', 2))
        self.assertEqual(bitstream.get_num(8), int('00101100', 2))
        self.assertEqual(bitstream.get_num(8), int('00100010', 2))
        self.assertEqual(bitstream.get_num(8), int('10001001', 2))
        self.assertEqual(bitstream.get_num(8), int('10101111', 2))

        # Get it as 16-bit numbers
        bitstream.seek(0)
        self.assertEqual(bitstream.get_num(16), int('0000000000000011', 2))
        self.assertEqual(bitstream.get_num(16), int('0101011001010011', 2))
        self.assertEqual(bitstream.get_num(16), int('0010110000100010', 2))
        self.assertEqual(bitstream.get_num(16), int('1000100110101111', 2))

        # Get it as 32-bit numbers
        bitstream.seek(0)
        self.assertEqual(bitstream.get_num(32),
                         int('00000000000000110101011001010011', 2))
        self.assertEqual(bitstream.get_num(32),
                         int('00101100001000101000100110101111', 2))
Пример #55
0
 def test_num_read_part(self):
     """
     Test that we can read only some bits of a large number and interpret 
     them as a shorter number with the expected value.
     """
     bitstream = BitStream()
     
     # Store a 64-bit integer in the stream.
     num = int('00000000000000110101011001010011'
               '00101100001000101000100110101111', 2)
     bitstream.put_num(num, 64)
     
     # Get it as 8-bit numbers
     bitstream.seek(0)
     self.assertEqual(bitstream.get_num(8),int('00000000',2))
     self.assertEqual(bitstream.get_num(8),int('00000011',2))
     self.assertEqual(bitstream.get_num(8),int('01010110',2))
     self.assertEqual(bitstream.get_num(8),int('01010011',2))
     self.assertEqual(bitstream.get_num(8),int('00101100',2))
     self.assertEqual(bitstream.get_num(8),int('00100010',2))
     self.assertEqual(bitstream.get_num(8),int('10001001',2))
     self.assertEqual(bitstream.get_num(8),int('10101111',2))
     
     # Get it as 16-bit numbers
     bitstream.seek(0)
     self.assertEqual(bitstream.get_num(16),int('0000000000000011',2))
     self.assertEqual(bitstream.get_num(16),int('0101011001010011',2))
     self.assertEqual(bitstream.get_num(16),int('0010110000100010',2))
     self.assertEqual(bitstream.get_num(16),int('1000100110101111',2))
     
     # Get it as 32-bit numbers
     bitstream.seek(0)
     self.assertEqual(bitstream.get_num(32),
                      int('00000000000000110101011001010011',2))
     self.assertEqual(bitstream.get_num(32),
                      int('00101100001000101000100110101111',2))
Пример #56
0
    def test_byte_basic(self):
        """
        Test basic put_byte and get_byte behavior.
        """
        bitstream = BitStream()

        # Put a couple of bytes in the stream:

        bytes = [
            12,  # 00001100
            222,  # 11011110
            145,  # 10010001
            42,  # 00101010
            0,  # 00000000
            255
        ]  # 11111111

        for byte in bytes:
            bitstream.put_byte(byte)

        # Sanity check:
        self.assertEquals(bitstream.get_length(), len(bytes) * 8)
        self.assertEquals(bitstream.get_current_pos(), len(bytes) * 8)

        # Read the bytes back from the stream
        bitstream.seek(0)
        for byte in bytes:
            self.assertEquals(bitstream.get_byte(), byte)

        # Read some bits from the stream, interpreting them as bytes, but
        # without restricting ourselves to 8-bit aligned bytes
        # e.g. read the "byte" defined by bits #4 to #12
        bitstream.seek(4)
        self.assertEquals(bitstream.get_byte(), 205)  # 11001101
        bitstream.seek(19)
        self.assertEquals(bitstream.get_byte(), 137)  # 10001001
Пример #57
0
    def test_put_bitstream_copy(self):
        """
        Test the basic functionality of the put_bitstream_copy method.
        """
        bitstream1 = BitStream()
        bitstream1.put_string("This is bitstream1")
        bitstream2 = BitStream()
        bitstream2.put_string("This is bitstream2")
        bitstream3 = BitStream()
        # bitstream3 remains empty
        bitstream4 = BitStream()
        bitstream4.put_string("This is bitstream4")

        # copy the full contents of bitstream2 to the end of bitstream1
        bitstream2.seek(0)
        bitstream1.put_bitstream_copy(bitstream2)
        self.assertEquals(bitstream2.get_current_pos(),
                          bitstream2.get_length())

        # check the contents of bitstream1
        bitstream1.seek(0)
        self.assertEquals(bitstream1.get_string(bitstream1.get_length()),
                          "This is bitstream1This is bitstream2")

        # copy the full contents of bitstream3 (aka. nothing) to the end of
        # bitstream4
        bitstream3.seek(0)
        bitstream4.put_bitstream_copy(bitstream3)

        # check the contents of bitstream4
        bitstream4.seek(0)
        self.assertEquals(bitstream4.get_string(bitstream4.get_length()),
                          "This is bitstream4")

        # copy the contents of bitstream4 from the position 8 onwards
        bitstream4.seek(8 * 8)
        bitstream1.put_bitstream_copy(bitstream4)
        self.assertEquals(bitstream4.get_current_pos(),
                          bitstream4.get_length())

        # check the contents of bitstream1
        bitstream1.seek(0)
        self.assertEquals(bitstream1.get_string(bitstream1.get_length()),
                          "This is bitstream1This is bitstream2bitstream4")
Пример #58
0
	def verify(self, original_collection, shuffled_collection):
		"""
		Verifies that original_collection and shuffled_collection are 
		equivalent as proven by this ShufflingProof object.
		
		If this method returns true, then we have proof that both collections 
		contain encryptions of the same collection of plaintexts, save for the 
		negligible probability (for a correct security parameter configured in 
		params.py) that the zero-knowledge proof has been faked. Otherwise we 
		gain no information about the two collections, other than they are not 
		shown to be equivalent by this particular proof.
		
		ShufflingProof is a zero-knowledge proof: the result of this 
		verification or the information within the ShufflingProof object for 
		which two collections pass this verification, provide no information as 
		to the association of particular ciphertexts in original_collection  
		with particular ciphertexts of shuffled_collection.
		
		Arguments:
			original_collection::CiphertextCollection	--
				The original collection of ciphertexts.
			shuffled_collection::CiphertextCollection	--
				Another collection for which we wish to know if the current 
				ShufflingProof object demonstrates equivalence with 
				original_collection.
		
		Returns:
			result::bool	-- True if this proof shows both collections to be 
							   equivalent.
							   False otherwise.
		"""
		# Get the security parameter P with which the proof was originally 
		# created. This is reflect in the length of self._collections and 
		# self._mappings.
		assert len(self._collections) == len(self._mappings), \
			"The length of the private properties self._collections and " \
			"self._mappings of ShufflingProof must always be the same."
		security_parameter = len(self._collections)
		
		
		# Get the security parameter specified in params
		minimum_allowed_security_parameter = params.SHUFFLING_PROOF_SECURITY_PARAMETER
		
		# Check that the security parameter is <= 256, since that is the most 
		# bits of challenge we can currently have. Also check that P is at least 1
		if(minimum_allowed_security_parameter < 1 or 
		   minimum_allowed_security_parameter > 256):
			raise ValueError("Security parameter for shuffling proof " \
					"(params.SHUFFLING_PROOF_SECURITY_PARAMETER) is out of " \
					"range. The security parameter must be between 1 and 256, "\
					"its current value is %d. If you have set " \
					"CUSTOM_SHUFFLING_PROOF_SECURITY_PARAMETER in the file " \
					"params.py, please correct this value or set it to None, " \
					"in order for the security parameter to be decided based " \
					"on the global SECURITY_LEVEL of plonevotecryptolib. It " \
					"is recommended that " \
					"CUSTOM_SHUFFLING_PROOF_SECURITY_PARAMETER be always set " \
					"to None for deployment operation of plonevotecryptolib." \
					% security_parameter)
					
		# Check that the security parameter for which the proof was generated 
		# is correct and meets the security standards declared in params.py
		if(security_parameter < minimum_allowed_security_parameter or
		   security_parameter < 1 or 
		   security_parameter > 256):
		   	raise InvalidShuffilingProofError("The security parameter for " \
					"(which the current proof was created is %d. This is " \
					"(either an incorrect value (outside of the [1,256] " \
					"(range) or not secure enough to meet the standards set " \
					"(in the configuration of params.py (< %d). The proof " \
					"(is thus invalid." \
					% (security_parameter, 
					  minimum_allowed_security_parameter))
					
		# Generate the challenge 
		challenge = \
			self._generate_challenge(original_collection, shuffled_collection)
		
		# Verify that the challenge corresponds to the stored one
		if(challenge != self._challenge):
			return False
		
		# Get the challenge as a BitStream for easier manipulation
		challenge_bits = BitStream()
		challenge_bits.put_hex(challenge)
		challenge_bits.seek(0)	# back to the beginning of the stream
		
		# For each of the first P bits in the stream
		for i in range(0, security_parameter):
			bit = challenge_bits.get_num(1)
			if(bit == 0):
				# verify that self._mapping[i] maps original_collection into
				# self._collections[i]
				if(not self._mappings[i].verify(original_collection, 
											   self._collections[i])):
					return False
					
			elif(bit == 1):
				# verify that self._mapping[i] self._collections[i] into
				# self._collections[i]
				if(not self._mappings[i].verify(self._collections[i], 
											   shuffled_collection)):
					return False
			else:
				assert False, "We took a single bit, its value must be either "\
						"0 or 1."
		
		# If we made it so far, the proof is correct
		# (each mapping is in accordance to the challenge and valid)
		return True
Пример #59
0
 def encrypt_bitstream(self, bitstream, pad_to=None, task_monitor=None):
     """
     Encrypts the given bitstream into a ciphertext object.
     
     Arguments:
         bitstream::BitStream-- A stream of bits to encrypt 
                                (see BitStream utility class).
         pad_to::int            -- Minimum size (in bytes) of the resulting 
                                ciphertext. Data will be padded before 
                                encryption to match this size.
         task_monitor::TaskMonitor    -- A task monitor for this task.
     
     Returns:
         ciphertext:Ciphertext    -- A ciphertext object encapsulating the 
                                    encrypted data.        
     """
     random = StrongRandom()
     
     ## PART 1
     # First, format the bitstream as per Ciphertext.py Note 001,
     # previous to encryption.
     #     [size (64 bits) | message (size bits) | padding (X bits) ]
     ##
     formated_bitstream = BitStream()
     
     # The first 64 encode the size of the actual data in bits
     SIZE_BLOCK_LENGTH = 64
     size_in_bits = bitstream.get_length()
     
     if(size_in_bits >= 2**SIZE_BLOCK_LENGTH):
         raise ValueError("The size of the bitstream to encrypt is larger " \
                          "than 16 Exabits. The current format for  " \
                          "PloneVote ciphertext only allows encrypting a  " \
                          "maximum of 16 Exabits of information.")
     
     formated_bitstream.put_num(size_in_bits, SIZE_BLOCK_LENGTH)
     
     # We then copy the contents of the original bitstream
     bitstream.seek(0)
     formated_bitstream.put_bitstream_copy(bitstream)
     
     # Finally, we append random data until we reach the desired pad_to 
     # length
     unpadded_length = formated_bitstream.get_length()
     if(pad_to != None and (pad_to * 8) > unpadded_length):
         full_length = pad_to * 8
     else:
         full_length = unpadded_length
     
     padding_left = full_length - unpadded_length
     
     while(padding_left > 1024):
         padding_bits = random.randint(1, 2**1024)
         formated_bitstream.put_num(padding_bits,1024)
         padding_left -= 1024
     
     if(padding_left > 0):
         padding_bits = random.randint(1, 2**padding_left)
         formated_bitstream.put_num(padding_bits, padding_left)
         padding_left = 0
     
     ## PART 2
     # We encrypt the formated bitsteam using ElGamal into a Ciphertext 
     # object.
     # See "Handbook of Applied Cryptography" Algorithm 8.18
     ##
     
     # block_size is the size of each block of bits to encrypt
     # since we can only encrypt messages in [0, p - 1]
     # we should use (nbits - 1) as the block size, where 
     # 2**(nbits - 1) < p < 2**nbits
     
     block_size = self.cryptosystem.get_nbits() - 1
     prime = self.cryptosystem.get_prime()
     generator = self.cryptosystem.get_generator()
     
     # We pull data from the bitstream one block at a time and encrypt it
     formated_bitstream.seek(0)
     ciphertext = \
         Ciphertext(self.cryptosystem.get_nbits(), self.get_fingerprint()) 
     
     plaintext_bits_left = formated_bitstream.get_length()
     
     # Check if we have a task monitor and register with it
     if(task_monitor != None):
         # We will do two tick()s per block to encrypt: one for generating 
         # the gamma component of the ciphertext block and another for the 
         # delta component (those are the two time intensive steps, 
         # because of exponentiation). 
         ticks = math.ceil((1.0 * plaintext_bits_left) / block_size) * 2
         encrypt_task_mon = \
             task_monitor.new_subtask("Encrypt data", expected_ticks = ticks)
     
     while(plaintext_bits_left > 0):
     
         # get next block (message, m, etc) to encrypt
         if(plaintext_bits_left >= block_size):
             block = formated_bitstream.get_num(block_size)
             plaintext_bits_left -= block_size
         else:
             block = formated_bitstream.get_num(plaintext_bits_left)
             # Encrypt as if the stream was filled with random data past its 
             # end, this avoids introducing a 0's gap during decryption to 
             # bitstream
             displacement = block_size - plaintext_bits_left
             block = block << displacement
             padding = random.randint(0, 2**displacement - 1)
             assert (padding / 2**displacement == 0), \
                         "padding should be at most displacement bits long"
             block = block | padding
             plaintext_bits_left = 0
         
         # Select a random integer k, 1 <= k <= p − 2
         k = random.randint(1, prime - 2)
         
         # Compute gamma and delta
         gamma = pow(generator, k, prime)
         if(task_monitor != None): encrypt_task_mon.tick()
         
         delta = (block * pow(self._key, k, prime)) % prime
         if(task_monitor != None): encrypt_task_mon.tick()
         
         # Add this encrypted data portion to the ciphertext object
         ciphertext.append(gamma, delta)
     
     # return the ciphertext object
     return ciphertext
Пример #60
0
    def test_seek_basic(self):
        """
        Use seek to read data at different points in the bitstream.
        """
        bitstream = BitStream()

        # Store a 64-bit integer in the stream.
        num = int(
            '00000000000000110101011001010011'
            '00101100001000101000100110101111', 2)
        bitstream.put_num(num, 64)

        # Get the 0th, 3rd, 5th and 6th bytes of the stream
        # First in forwards order
        bitstream.seek(0)
        self.assertEqual(bitstream.get_num(8), int('00000000', 2))
        bitstream.seek(3 * 8)
        self.assertEqual(bitstream.get_num(8), int('01010011', 2))
        bitstream.seek(5 * 8)
        self.assertEqual(bitstream.get_num(8), int('00100010', 2))
        self.assertEqual(bitstream.get_num(8), int('10001001', 2))
        # Then in backwards order
        bitstream.seek(6 * 8)
        self.assertEqual(bitstream.get_num(8), int('10001001', 2))
        bitstream.seek(5 * 8)
        self.assertEqual(bitstream.get_num(8), int('00100010', 2))
        bitstream.seek(3 * 8)
        self.assertEqual(bitstream.get_num(8), int('01010011', 2))
        bitstream.seek(0)
        self.assertEqual(bitstream.get_num(8), int('00000000', 2))