Jemson
Jemson

Reputation: 45

Python String to Escaped Hex

I have some python code below I managed to cobble together to achieve what I needed, but being quite new to python I believe there should be a much more elegant solution than the one I have here.

Essentially I need to take an arbitrary string (MAGICSTRING) and convert each of it's characters into their hex value, then pad a 0x00 to the start and end of the resultant hex string, and finally put the hex value of the length of the entire padded string on the end. I then need these escaped so it can be passed to a socket connection later on.

In the example, MAGICSTRING is 1234, and the expected result of 'value' is '\x00\x31\x32\x33\x34\x00\x06'

See below example.

MAGICSTRING = '1234'
i=0
hexpass = ''
while i < len(MAGICSTRING):
    hexpass = hexpass + hex(ord(MAGICSTRING[i]))[2:]
    i += 1
strlen = len(MAGICSTRING) + 2
sendstr = '00'+ hexpass + '00' + '0' + hex(strlen)[2:]
value = sendstr.decode('hex')

Appreciate any improvements that can be made to the above.

Upvotes: 4

Views: 18794

Answers (1)

Martijn Pieters
Martijn Pieters

Reputation: 1121864

The string '1234' is already equivalent to '\x31\x32\x33\x34':

>>> '\x31\x32\x33\x34'
'1234'
>>> '\x31\x32\x33\x34' == '1234'
True

thus encoding that to hex then decoding it again is.. busy work:

>>> '1234'.encode('hex').decode('hex')
'1234'

\xhh is just a notation to help you create the values; when echoing a byte string Python will always display printable ASCII characters directly rather than use the \xhh notation.

Hex notation here is just a way to express the values of each byte, which is really an integer between 0 and 255. Each byte in a Python string is then a byte with such a constrained value, and encoding to the 'hex' codec produces a string with hex digits for those bytes, and bytes again from the hex digits.

As such, all you have to do is add the \x00 null bytes and the length:

MAGICSTRING = '1234'
value = '\x00{}\x00{}'.format(MAGICSTRING, chr(len(MAGICSTRING) + 2))

Here the \xhh notation is used to produce the null bytes, and the chr() function produces the length 'byte'.

Demo:

>>> MAGICSTRING = '1234'
>>> '\x00{}\x00{}'.format(MAGICSTRING, chr(len(MAGICSTRING) + 2))
'\x001234\x00\x06'
>>> '\x00{}\x00{}'.format(MAGICSTRING, chr(len(MAGICSTRING) + 2)) == '\x00\x31\x32\x33\x34\x00\x06'
True

Upvotes: 11

Related Questions