0

So, i am collecting some codes from a ip device, and i am struggling to calc it's checksum. For example, this is the package that I collected using a simple socket in python:

b'\x07\x94ES(\xff\xceY:'

Converting it to a more human readable using .hex(), i got this:

0794455328ffce593a

3a is the given checksum, i should be able to get the same value by xor the code (like 07^94^45^53^28^ff^ce^59^FF = 3a), but i can't figure out how. I tried to xor the values as integers, but the result was way off. BTW, 07 is the number of bytes of the package.

Another string example is

b'\x11\xb0\x11\x05\x03\x02\x08\x01\x08\x01\x03\x08\x03\n\x01\n\n\x01I'

Anyone have an idea?

Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219
IamRichter
  • 15
  • 9
  • 1
    _"I tried to xor the values as integers, but the result was way off"_. Please show the code where you tried this. – Kevin Mar 13 '20 at 12:35
  • with two's complement it could work, since checksum is currently 0xC5 like `hex(~(0xC5)+0x100)` => 0x3A but it could be a coincidence. – Jean-François Fabre Mar 13 '20 at 12:40
  • hi kevin, i did not build a code first. i went into the python shell and just iterate value by value to see if the result would work out. – IamRichter Mar 13 '20 at 12:42
  • So you're basically, through trial and error, trying to determine the checksum algorithm? – GordonAitchJay Mar 13 '20 at 12:45
  • Where did you get the extra `^FF` from in your example? – Mark Dickinson Mar 13 '20 at 12:47
  • @GordonAitchJay Well, i am not actually a python developer. I am just a sysadmin who uses a lot of bash and since last month decided to learn Python. Sorry if my question or my method was dumb... @Jean-FrançoisFabre How did you made it? Also, i have other codes to see if the result check in: ```b'\x11\xb0\x11\x05\x03\x02\x08\x01\x08\x01\x03\x08\x03\n\x01\n\n\x01I'``` ```11b01105030208010801030803000100000149``` – IamRichter Mar 13 '20 at 12:48
  • @MarkDickinson It came from the manufacture pdf... – IamRichter Mar 13 '20 at 12:49
  • Can you post a link to the manufacturer's pdf? I can be very hard to figure out the checksum algorithm. It won't necessarily start at `0` and could involve magic numbers. – GordonAitchJay Mar 13 '20 at 12:59
  • @GordonAitchJay Actually, i can't (for some legal reason i can't distribute it). I can post the same example that come with the pdf and a C sharp example: ` 1 Passo: calcular a operação XOR com todos os dados do comando. o Ex: 09 ^ E7 ^ 05 ^ 11 ^ 87 ^ 87 ^ 87 ^ 34 ^ EB ^ 1C = BE 2 Passo: fazer o complemento 1 do resultado (operação XOR do resultado com FF). o Ex: BE ^ FF = 41` – IamRichter Mar 13 '20 at 13:04
  • 1
    @GordonAitchJay here goes the sample code. `xor = using System; { public class Checksum : IChecksum { public byte Calculate(byte[] data) { byte xor = 0; foreach (var b in data) { xor ^= b; } xor ^= 0xFF; return xor; } } }` – IamRichter Mar 13 '20 at 13:05
  • 1
    `0xff ^ reduce((lambda x, y: x ^ y), unhexlify(hex_string))` works for the first example but not for the second . To match, that should have ended with `0x43`. That new example `09E7051187878734EB1C` works again -- but *please* stop adding important information and useful examples in **comments**. – Jongware Mar 13 '20 at 13:14

2 Answers2

3

with a little guess work and 2 examples, it seems that the xor algorithm used is flipping all the bits somewhere. Doing that flip makes the value of the examples match.

data_list = [b'\x07\x94ES(\xff\xceY:', b'\x11\xb0\x11\x05\x03\x02\x08\x01\x08\x01\x03\x08\x03\n\x01\n\n\x01I']
for data in data_list:
    value = data[0]
    for d in data[1:-1]:
        value ^= d

    checksum = value ^ 0xFF  # negate all the bits

    if checksum == data[-1]:
        print("checksum match for {}".format(data))
    else:
        print("checksum DOES NOT MATCH for {}".format(data))

prints:

checksum match for b'\x07\x94ES(\xff\xceY:'
checksum match for b'\x11\xb0\x11\x05\x03\x02\x08\x01\x08\x01\x03\x08\x03\n\x01\n\n\x01I'

not sure if it helps future readers but at least this is solved.

Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219
  • Nitpick: do you mean ones' complement rather than two's complement? – Mark Dickinson Mar 13 '20 at 13:19
  • I just checked and it's called "two's complement" in English. – Jean-François Fabre Mar 13 '20 at 13:23
  • No, both are proper English but they mean something else. [Two's complement](https://en.wikipedia.org/wiki/Two%27s_complement) is actually (a version of) the negative number . This is [One's complement](https://en.wikipedia.org/wiki/Ones'_complement): "All bits inverted". It only happens to *be* a one's complement because it does an explicit `XOR 0xFF` (because `0xFF` could have been any other number). A 'true' one's cpl would have been `~checksum`. – Jongware Mar 13 '20 at 14:56
0

If you're curious, here's a direct port of the C# implementation you put in a comment:

def calculate(data):
    xor = 0
    for byte in data:
        xor ^= byte

    xor ^= 0xff
    return xor

I didn't realise the last byte was in fact the checksum.

GordonAitchJay
  • 4,640
  • 1
  • 14
  • 16
  • 1
    You can set `xor = 0xff` in the first line and omit the last line. It's due to one of the inherent properties of `xor` -- order independency, much like `+` and not like `–`. – Jongware Mar 13 '20 at 14:58