1

My goal is to get a 64 characters long hex number from a user (which represent a serial number) and convert to c_type 32bytes number. Serial Number is defined like this:

_sn =  c_ubyte * 32

I accept SN string from user into args.sn variable. Here's how I managed to solve it. I'm sure there is an easier and more elegant way, would appreciate your help.

SN_List= []
for i in range(0,len(args.sn),2):
    myByte = args.sn[i: i+2]
    num = int("0x" + myByte,16)
    SN_List.append(num)

if(len(SN_List) != 32):
    print("S/N is not valid, it should be 64 hex characters long")
    return 1
_sn = (c_ubyte * 32)(*SN_List)
2
  • Have you tried binascii.a2b_hex? Commented May 6, 2015 at 16:38
  • As a side note, you don't need both the "0x" + and the , 16; one or the other will do. Commented May 6, 2015 at 16:40

3 Answers 3

4

The very easy way, using binascii (Python 3):

import binascii

print(list(binascii.unhexlify(args.sn)))

Example:

>>> list(binascii.unhexlify('09F911029D74E35BD84156C5635688C0'))
[9, 249, 17, 2, 157, 116, 227, 91, 216, 65, 86, 197, 99, 86, 136, 192]

In Python 2, you would use

print map(ord, args.sn.decode('hex'))

Example:

>>> sn = '09F911029D74E35BD84156C5635688C0'
>>> print map(ord, sn.decode('hex'))
[9, 249, 17, 2, 157, 116, 227, 91, 216, 65, 86, 197, 99, 86, 136, 192]
Sign up to request clarification or add additional context in comments.

5 Comments

It should be almost as easy in Python 2, just with map(ord, …)) instead of list(…).
In Python 2, it's actually slightly easier because of .decode('hex'). I amended my answer.
I never found decode('hex') to be any simpler than unhexlify. But if you really like that, you can use codecs.decode(args.sn, 'hex'), which works in 2.x and 3.3+.
@abarnert: I always liked it because it let me skip an import - this is important to me when doing short little things on the command-line.
@nneonneo: Yeah, I occasionally catch myself using __import__ on python -c command lines just so I can cram the whole expression in with no spaces and avoid quoting my quotes; not having to import anything certainly solves that problem. :)
1

Expanding on @nneonneo's comment (binascii.unhexlify is equivelent to binascii.a2b_hex):

_sn = (c_ubyte * 32)(*binascii.unhexlify("ffaabb"))

Example (with the hex ffaabb):

>>> binascii.unhexlify("ffaabb")
b'\xff\xaa\xbb'
>>> _sn = (c_ubyte * 32)(*binascii.unhexlify("ffaabb"))
>>> _sn
<__main__.c_ubyte_Array_32 object at 0x7fe14fee8bf8>
>>> for i in _sn:
...     print(i)
... 
255
170
187
0
0
<27 more zeros>

1 Comment

that gives what the question asks for (a byte array) in the simplest way.
0

First, you can use a list comprehension to eliminate most of the overhead code. Second, it's not necessary to prepend 0x to the string when you convert to int, as long as you've specified the second parameter. Third, if you need to validate the string to make sure it contains the correct number of digits, that should be a separate step. Or perhaps you can just rely on a raised exception when things go wrong.

SN_List = [int(args.sn[i: i+2], 16) for i in range(0, 64, 2)]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.