예제 #1
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)
예제 #2
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)
예제 #3
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.")
예제 #4
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.")
예제 #5
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)
예제 #6
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)
예제 #7
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
예제 #8
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!")
예제 #9
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"])
예제 #10
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"])
예제 #11
0
 def test_bitstream_constructor(self):
     """
     Test that creating an empty bitstream succeeds.
     """
     bitstream = BitStream()
     # An empty bitstream has length 0 ...
     self.assertEqual(bitstream.get_length(), 0)
     # ...and has its current position marker at position 0.
     self.assertEqual(bitstream.get_current_pos(), 0)
예제 #12
0
 def test_bitstream_constructor(self):
     """
     Test that creating an empty bitstream succeeds.
     """
     bitstream = BitStream()
     # An empty bitstream has length 0 ...
     self.assertEqual(bitstream.get_length(), 0)
     # ...and has its current position marker at position 0.
     self.assertEqual(bitstream.get_current_pos(), 0)
예제 #13
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")
예제 #14
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")
예제 #15
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)
예제 #16
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()),    
                       "ÄäÜüßЯБГДЖЙŁĄŻĘĆŃŚŹてすとアイウエオカキクケコサシスセソタチツテ")
예제 #17
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()),
                       "ÄäÜüßЯБГДЖЙŁĄŻĘĆŃŚŹてすとアイウエオカキクケコサシスセソタチツテ")
예제 #18
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()),
                          "ÄäÜüßЯБГДЖЙŁĄŻĘĆŃŚŹてすとアイウエオカキクケコサシスセソタチツテ")
예제 #19
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()),    
                       "ÄäÜüßЯБГДЖЙŁĄŻĘĆŃŚŹてすとアイウエオカキクケコサシスセソタチツテ")
예제 #20
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)
예제 #21
0
    def test_put_hex_invalid_format(self):
        """
        Test that put_hex raises an exception when passed any string not of the 
        form ('0'-'9'|'a'-'f'|'A'-'F')*
        """
        bitstream = BitStream()

        # Try some fixed examples
        self.assertRaises(ValueError, bitstream.put_hex, "aF92G2")
        self.assertRaises(ValueError, bitstream.put_hex, "Hello")
        self.assertRaises(ValueError, bitstream.put_hex, "3354 F")
        self.assertRaises(ValueError, bitstream.put_hex, "ケコサシス")

        # Generate a random string conforming to ('0'-'9'|'a'-'f'|'A'-'F')*
        # except for one (ascii) character.
        valid_hex_digits = "0123456789abcdefABCDEF"
        num_digits = 50
        pos_wrong_char = random.randint(1, 48)
        r_invalid_hex_string = ""

        for i in range(0, pos_wrong_char):
            r_invalid_hex_string += random.choice(valid_hex_digits)

        non_hex_char = "0"
        while (non_hex_char in valid_hex_digits):
            non_hex_char = \
               random.choice(string.letters + string.digits + string.whitespace)

        r_invalid_hex_string += non_hex_char

        for i in range(0, num_digits - pos_wrong_char - 1):
            r_invalid_hex_string += random.choice(valid_hex_digits)

        # Try the randomly generated example
        self.assertRaises(ValueError, bitstream.put_hex, r_invalid_hex_string)

        # Calls that throw exceptions should not alter the contents or position
        # of the bitstream:
        self.assertEquals(bitstream.get_length(), 0)
        self.assertEquals(bitstream.get_current_pos(), 0)
예제 #22
0
 def test_put_hex_invalid_format(self):
     """
     Test that put_hex raises an exception when passed any string not of the 
     form ('0'-'9'|'a'-'f'|'A'-'F')*
     """
     bitstream = BitStream()
     
     # Try some fixed examples
     self.assertRaises(ValueError, bitstream.put_hex, "aF92G2")
     self.assertRaises(ValueError, bitstream.put_hex, "Hello")
     self.assertRaises(ValueError, bitstream.put_hex, "3354 F")
     self.assertRaises(ValueError, bitstream.put_hex, "ケコサシス")
     
     # Generate a random string conforming to ('0'-'9'|'a'-'f'|'A'-'F')* 
     # except for one (ascii) character.
     valid_hex_digits = "0123456789abcdefABCDEF"
     num_digits = 50
     pos_wrong_char = random.randint(1,48)
     r_invalid_hex_string = ""
     
     for i in range(0,pos_wrong_char):
         r_invalid_hex_string += random.choice(valid_hex_digits)
     
     non_hex_char = "0"
     while(non_hex_char in valid_hex_digits): 
         non_hex_char = \
            random.choice(string.letters + string.digits + string.whitespace)
     
     r_invalid_hex_string += non_hex_char
         
     for i in range(0,num_digits - pos_wrong_char - 1):
         r_invalid_hex_string += random.choice(valid_hex_digits)
     
     # Try the randomly generated example
     self.assertRaises(ValueError, bitstream.put_hex, r_invalid_hex_string)
                       
     # Calls that throw exceptions should not alter the contents or position 
     # of the bitstream:
     self.assertEquals(bitstream.get_length(),0)
     self.assertEquals(bitstream.get_current_pos(),0)
예제 #23
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])
예제 #24
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])
예제 #25
0
 def test_put_bit_dump_string_invalid_format(self):
     """
     Test that put_bit_dump_string raises an exception when passed any 
     string not of the form ('0'|'1')*
     """
     bitstream = BitStream()
     
     # Try some fixed examples
     self.assertRaises(ValueError, bitstream.put_bit_dump_string, "23234")
     self.assertRaises(ValueError, bitstream.put_bit_dump_string, "Hello")
     self.assertRaises(ValueError, bitstream.put_bit_dump_string, "0101 0")
     self.assertRaises(ValueError, bitstream.put_bit_dump_string, "ケコサシス")
     
     # Generate a random string conforming to ('0'|'1')* except for one 
     # (ascii) character.
     num_bits = 50
     pos_wrong_char = random.randint(1,48)
     r_invalid_bit_string = ""
     
     for i in range(0,pos_wrong_char):
         r_invalid_bit_string += random.choice(('0','1'))
         
     r_invalid_bit_string += \
         random.choice(string.letters + "23456789_-/\\" + string.whitespace)
         
     for i in range(0,num_bits - pos_wrong_char - 1):
         r_invalid_bit_string += random.choice(('0','1'))
     
     # Try the randomly generated example
     self.assertRaises(ValueError, bitstream.put_bit_dump_string, 
                       r_invalid_bit_string)
                       
     # Calls that throw exceptions should not alter the contents or position 
     # of the bitstream:
     self.assertEquals(bitstream.get_length(),0)
     self.assertEquals(bitstream.get_current_pos(),0) 
예제 #26
0
    def test_put_bit_dump_string_invalid_format(self):
        """
        Test that put_bit_dump_string raises an exception when passed any 
        string not of the form ('0'|'1')*
        """
        bitstream = BitStream()

        # Try some fixed examples
        self.assertRaises(ValueError, bitstream.put_bit_dump_string, "23234")
        self.assertRaises(ValueError, bitstream.put_bit_dump_string, "Hello")
        self.assertRaises(ValueError, bitstream.put_bit_dump_string, "0101 0")
        self.assertRaises(ValueError, bitstream.put_bit_dump_string, "ケコサシス")

        # Generate a random string conforming to ('0'|'1')* except for one
        # (ascii) character.
        num_bits = 50
        pos_wrong_char = random.randint(1, 48)
        r_invalid_bit_string = ""

        for i in range(0, pos_wrong_char):
            r_invalid_bit_string += random.choice(('0', '1'))

        r_invalid_bit_string += \
            random.choice(string.letters + "23456789_-/\\" + string.whitespace)

        for i in range(0, num_bits - pos_wrong_char - 1):
            r_invalid_bit_string += random.choice(('0', '1'))

        # Try the randomly generated example
        self.assertRaises(ValueError, bitstream.put_bit_dump_string,
                          r_invalid_bit_string)

        # Calls that throw exceptions should not alter the contents or position
        # of the bitstream:
        self.assertEquals(bitstream.get_length(), 0)
        self.assertEquals(bitstream.get_current_pos(), 0)
예제 #27
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!")
예제 #28
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
예제 #29
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
예제 #30
0
    def from_file(cls, filename, SerializerClass=serialize.XMLSerializer):
        """
        Loads an instance of Ciphertext from the given file.

        Arguments:
            filename::string    -- The name of a file containing the ciphertext
                                   in serialized form.
            SerializerClass::class --
                The class that provides the deserialization. XMLSerializer by
                default. Must inherit from serialize.BaseSerializer and provide
                an adequate deserialize_from_file method.
                Note that often the same class used to serialize the data must
                be used to deserialize it.
                (see utilities/serialize.py documentation for more information)

        Throws:
            InvalidPloneVoteCryptoFileError -- If the file is not a valid
                                               PloneVoteCryptoLib stored
                                               ciphertext file.
        """
        # Create a new serializer object for the Ciphertext structure definition
        serializer = SerializerClass(Ciphertext_serialize_structure_definition)

        # Deserialize the Ciphertext instance from file
        try:
            data = serializer.deserialize_from_file(filename)
        except serialize.InvalidSerializeDataError as e:
            # Convert the exception to an InvalidPloneVoteCryptoFileError
            raise InvalidPloneVoteCryptoFileError(filename,
                "File \"%s\" does not contain a valid ciphertext. The " \
                "following error occurred while trying to deserialize the " \
                "file contents: %s" % (filename, str(e)))

        # Get the values from the deserialized data
        try:
            nbits = int(data["PloneVoteCiphertext"]["nbits"])
        except ValueError:
            raise InvalidPloneVoteCryptoFileError(filename,
                    "File \"%s\" does not contain a valid ciphertext. The " \
                    "stored value for nbits is not a valid (decimal) integer." \
                    % filename)

        fingerprint_str = data["PloneVoteCiphertext"]["PKFingerprint"]
        enc_data_str = data["PloneVoteCiphertext"]["EncryptedData"]

        # Construct a new Ciphertext object with the given nbits and fingerprint
        ciphertext = cls(nbits, fingerprint_str)

        # Load the encrypted data
        bitstream = BitStream()
        bitstream.put_base64(enc_data_str)
        bitstream.seek(0)
        length = bitstream.get_length()

        #     number of gamma and delta blocks in the bitstream:
        blocks = length // (nbits * 2)

        for i in range(0, blocks):
            gamma_val = bitstream.get_num(nbits)
            delta_val = bitstream.get_num(nbits)
            ciphertext.append(gamma_val, delta_val)

        # Return the ciphertext
        return ciphertext
예제 #31
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