def test_byte_length_correctness(self): numbers = [-12, 12, 1200, 120091, 123456789] for num in numbers: if num < 0: bit_length = len(bin(num, None)) - 1 else: bit_length = len(bin(num, None)) count = int(math.ceil(bit_length / 8.0)) self.assertEqual( builtins.integer_byte_length(num), count, "Boom. for number %d, expected %d" % (num, count) ) self.assertEqual(_alt_builtins.integer_byte_length_shift_counting(num), count) self.assertEqual(_alt_builtins.integer_byte_length_word_aligned(num), count) self.assertEqual(builtins.integer_byte_length(1 << 1023), 128) self.assertEqual(builtins.integer_byte_length((1 << 1024) - 1), 128) self.assertEqual(builtins.integer_byte_length(1 << 1024), 129) self.assertEqual(_alt_builtins.integer_byte_length_shift_counting(1 << 1023), 128) self.assertEqual(_alt_builtins.integer_byte_length_shift_counting((1 << 1024) - 1), 128) self.assertEqual(_alt_builtins.integer_byte_length_shift_counting(1 << 1024), 129) self.assertEqual(_alt_builtins.integer_byte_length_shift_counting(1 << 1023), 128) self.assertEqual(_alt_builtins.integer_byte_length_shift_counting((1 << 1024) - 1), 128) self.assertEqual(_alt_builtins.integer_byte_length_word_aligned(1 << 1024), 129)
def long_to_mpi(num): """ Converts a long value into an OpenSSL-format MPI Bignum byte string. :param num: Long value. :returns: OpenSSL-format MPI Bignum byte string. """ # from mom._types.bytearray import \ # long_to_bytearray, bytearray_concat, \ # bytearray_to_bytes, bytearray_create_zeros byte_array = long_to_bytearray(num) ext = 0 # If the high-order bit is going to be set, # add an extra byte of zeros if not (builtins.integer_bit_length(num) & 0x7): ext = 1 length = builtins.integer_byte_length(num) + ext byte_array = bytearray_concat(bytearray_create_zeros(4 + ext), byte_array) byte_array[0] = (length >> 24) & 0xFF byte_array[1] = (length >> 16) & 0xFF byte_array[2] = (length >> 8) & 0xFF byte_array[3] = length & 0xFF return bytearray_to_bytes(byte_array)
def test_byte_length_correctness(self): numbers = [-12, 12, 1200, 120091, 123456789] for num in numbers: if num < 0: bit_length = len(bin(num, None)) - 1 else: bit_length = len(bin(num, None)) count = int(math.ceil(bit_length / 8.0)) self.assertEqual(builtins.integer_byte_length(num), count, "Boom. for number %d, expected %d" % (num, count)) self.assertEqual(_alt_builtins.integer_byte_length_shift_counting(num), count) self.assertEqual(_alt_builtins.integer_byte_length_word_aligned(num), count) self.assertEqual(builtins.integer_byte_length(1 << 1023), 128) self.assertEqual(builtins.integer_byte_length((1 << 1024) - 1), 128) self.assertEqual(builtins.integer_byte_length(1 << 1024), 129) self.assertEqual(_alt_builtins.integer_byte_length_shift_counting(1 << 1023), 128) self.assertEqual(_alt_builtins.integer_byte_length_shift_counting((1 << 1024) - 1), 128) self.assertEqual(_alt_builtins.integer_byte_length_shift_counting(1 << 1024), 129) self.assertEqual(_alt_builtins.integer_byte_length_shift_counting(1 << 1023), 128) self.assertEqual(_alt_builtins.integer_byte_length_shift_counting((1 << 1024) - 1), 128) self.assertEqual(_alt_builtins.integer_byte_length_word_aligned(1 << 1024), 129)
def long_to_bytearray(num): """ Converts a long into a byte array. :param num: Long value :returns: Long. """ bytes_count = builtins.integer_byte_length(num) byte_array = bytearray_create_zeros(bytes_count) for count in range(bytes_count - 1, -1, -1): byte_array[count] = int(num % 256) num >>= 8 return byte_array
def uint_to_bytes_naive(number, block_size=0): """ Naive slow and accurate implementation. Base for all our tests. Converts a number to a string of bytes. :param number: the number to convert :param block_size: the number of bytes to output. If the number encoded to bytes is less than this, the block will be zero-padded. When not given, the returned block is not padded. :raises: ``OverflowError`` when block_size is given and the number takes up more bytes than fit into the block. """ if number < 0: raise ValueError("Negative numbers cannot be used: %d" % number) # Do some bounds checking needed_bytes = builtins.integer_byte_length(number) if block_size > 0: if needed_bytes > block_size: raise OverflowError("Needed %i bytes for number, but block size " "is %i" % (needed_bytes, block_size)) # Convert the number to bytes. if number == 0: raw_bytes = [ZERO_BYTE] else: raw_bytes = [] num = number while num > 0: raw_bytes.insert(0, builtins.byte(num & 0xFF)) num >>= 8 # Pad with zeroes to fill the block if block_size > 0: padding_size = (block_size - needed_bytes) if number == 0: padding_size -= 1 padding = ZERO_BYTE * padding_size else: padding = EMPTY_BYTE return padding + EMPTY_BYTE.join(raw_bytes)
def uint_to_bytes_naive_array_based(uint, chunk_size=0): """ Converts an integer into bytes. :param uint: Unsigned integer value. :param chunk_size: Chunk size. :returns: Bytes. """ if uint < 0: raise ValueError('Negative numbers cannot be used: %i' % uint) if uint == 0: bytes_count = 1 else: bytes_count = integer_byte_length(uint) byte_array = array('B', [0] * bytes_count) for count in range(bytes_count - 1, -1, -1): byte_array[count] = uint & 0xff uint >>= 8 raw_bytes = byte_array.tostring() if chunk_size > 0: # Bounds checking. We're not doing this up-front because the # most common use case is not specifying a chunk size. In the worst # case, the number will already have been converted to bytes above. length = len(raw_bytes) bytes_needed = bytes_count if bytes_needed > chunk_size: raise OverflowError( "Need %d bytes for number, but chunk size is %d" % (bytes_needed, chunk_size) ) remainder = length % chunk_size if remainder: raw_bytes = (chunk_size - remainder) * ZERO_BYTE + raw_bytes return raw_bytes
def uint_to_bytes_naive_array_based(uint, chunk_size=0): """ Converts an integer into bytes. :param uint: Unsigned integer value. :param chunk_size: Chunk size. :returns: Bytes. """ if uint < 0: raise ValueError("Negative numbers cannot be used: %i" % uint) if uint == 0: bytes_count = 1 else: bytes_count = builtins.integer_byte_length(uint) byte_array = array.array("B", [0] * bytes_count) for count in builtins.range(bytes_count - 1, -1, -1): byte_array[count] = uint & 0xff uint >>= 8 raw_bytes = byte_array.tostring() if chunk_size > 0: # Bounds checking. We're not doing this up-front because the # most common use case is not specifying a chunk size. In the worst # case, the number will already have been converted to bytes above. length = len(raw_bytes) bytes_needed = bytes_count if bytes_needed > chunk_size: raise OverflowError( "Need %d bytes for number, but chunk size is %d" % (bytes_needed, chunk_size)) remainder = length % chunk_size if remainder: raw_bytes = (chunk_size - remainder) * ZERO_BYTE + raw_bytes return raw_bytes
def test_byte_length_zero_if_zero(self): self.assertEqual(builtins.integer_byte_length(0), 0) self.assertEqual(_alt_builtins.integer_byte_length_shift_counting(0), 0) self.assertEqual(_alt_builtins.integer_byte_length_word_aligned(0), 0)
def test_byte_length_zero_if_zero(self): self.assertEqual(integer_byte_length(0), 0) self.assertEqual(integer_byte_length_shift_counting(0), 0) self.assertEqual(integer_byte_length_word_aligned(0), 0)