Reputation: 4075
I am trying to convert a number (of arbitrary size, possibly very long) to its corresponding string of bytes. For example, inputting the number 1094795585 (base 10), which is 0x41414141 (base 16), should return "\x41\x41\x41\x41".
Currently I have:
def number_to_bytes(number):
hex_string = hex(number).rstrip("L").lstrip("0x")
return bytearray.fromhex(hex_string.decode("hex"))
When I input the number 1094795585 (0x41414141), I get the error "odd-length string".
When I input the number 1094795584 (0x41414140), I get the error "non-hexadecimal number found in fromhex() arg at position 2".
This makes me think that Python is adding some sort of invisible character in the hex_string
. Is this the case?
How can I achieve the correct conversion?
Upvotes: 4
Views: 9326
Reputation: 1122382
You should not decode the string from hex; drop the .decode('hex')
call. You need to pass in actual hex digits, not a bytestring with codepoints based on those digits.
Compare the difference:
>>> hex(1094795584)[2:]
'41414140'
>>> hex(1094795584)[2:].decode('hex')
'AAA@'
By decoding you are already producing the very bytes you wanted bytesarray.fromhex()
to produce; you could just use bytesarray(hex_string.decode('hex'))
in that case.
You can use format()
to produce a hex format for your number that doesn't include the 0x
prefix, nor a L
postfix for long integers:
import math
def number_to_bytes(number):
byte_count = int(math.log(number, 256)) + 1
hex_string = '{:0{}x}'.format(number, byte_count * 2)
return bytearray.fromhex(hex_string)
Demo:
>>> import math
>>> def number_to_bytes(number):
... nibble_count = int(math.log(number, 256)) + 1
... hex_string = '{:0{}x}'.format(number, nibble_count * 2)
... return bytearray.fromhex(hex_string)
...
>>> number_to_bytes(1094795585)
bytearray(b'AAAA')
>>> number_to_bytes(1094795584)
bytearray(b'AAA@')
Upvotes: 2
Reputation: 6186
This should work:
import math
def number_to_bytes(num):
hex_str = format(num, 'x')
hex_len = (int(math.log2(num)/8)+1)*2
return bytearray.fromhex(hex_str.zfill(hex_len))
Upvotes: 0