0

I'm trying to implement a CRC verification on a network based protocol. CRC calculation is done via the PyCRC lib.

PyCRC will generate a checksum for the given packet and return a result like this: CB3D9FD1

When I try to send it on the wire, somehow python modify my string and convert it in ascii to Hex, example:

Crc = "CB3D9FD1"
...
buffer = "\x41\x42\x43\x44"+crc
...
s.send(buffer)

On the wire I will see that:

\x41\x42\x43\x44***\x43\x42\x33\x44\x39\x46\x44\x31***

Instead of:

 \x41\x42\x43\x44***\xCB\x3D\x9F\xD1***

Any ways to solve this issue easily ?

Thanks !

jterrace
  • 64,866
  • 22
  • 157
  • 202
n00bz0r
  • 87
  • 9
  • You'll need to provide some additional hint as to what you're doing. Code helps. The smallest code that demonstrates the problem is ideal. Feel free to create a short demo script that fails, and **update** your question with it. Python is not doing anything bad; your script has some small mistake in it. – S.Lott Dec 29 '11 at 19:17
  • 2
    Why are you going this route? Look at this answer for an alternative: http://stackoverflow.com/questions/1742866/compute-crc-of-file-in-python – Joe Dec 29 '11 at 19:19

3 Answers3

2

Actually, don't convert your CRC to ASCII. Keep it in hex and then pack it into a byte string using struct.pack::

buffer += struct.pack("L", crc)
Bashwork
  • 1,619
  • 8
  • 14
  • Yup I tried that before, only issue is struct return this : ***struct.error: cannot convert argument to integer*** – n00bz0r Dec 29 '11 at 19:24
  • 1
    I'd also recommend to use the exclamation mark (`'!L'`) to ensure network byte order (probably needed). – jcollado Dec 29 '11 at 19:29
  • @n00bz0r make sure your crc is an integer, perhaps parse it first: int(crc, 16). – Bashwork Dec 29 '11 at 19:31
  • crc must be numeric value, not a string. try `crc=0xCB3D9FD1` and `buffer += struct.pack("I", crc)` – gaoithe Jun 14 '16 at 14:59
0

By assigning it this way: crc = "CB3D9FD1" you are saying make var crc an 8 byte string. As @Bashwork says you need to convert it from hex string to numeric or keep it numeric. Assign it with 0x like this to get a numeric value: crc=0xCB3D9FD1.

pack("L",x) means I am giving you x which is(must be) an integer and I want you to pack it as an unsigned long.
You get "struct.error: cannot convert argument to integer" because you are passing pack("L",...) a string "CB3D9FD1".

RTFM what "L" and "I" and other args mean: https://docs.python.org/2/library/struct.html

Pack the CRC as long integer works: and you get 0s padding out to 64bits (on my PC. YMMV)

>>> from struct import pack
>>> crc=0xcb3d9fd1
>>> repr(crc)
'3409813457'
>>> pack("L", crc)
'\xd1\x9f=\xcb\x00\x00\x00\x00'
>>> print crc
3409813457

Maybe you want to use pack("I",...): to get 32bits

>>> pack("I",crc)
'\xd1\x9f=\xcb'

Fail if try to pack a CRC string with pack("L",...):

>>> crc = "CB3D9FD1"
>>> repr(crc)
"'CB3D9FD1'"
>>> pack("L", crc)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
struct.error: cannot convert argument to integer
gaoithe
  • 4,218
  • 3
  • 30
  • 38
0

If you have converted the CRC to a string containing "CB3D9FD1", then the correct byte sequence is 0x43 0x42 0x33 0x44 0x39 0x46 0x44 0x31. Don't convert the cry into a string or parse the string as a hex (two characters to each byte).

Roger Lindsjö
  • 11,330
  • 1
  • 42
  • 53