-1

I've been at this thing for an a few hours trying to figure it out:

data = b'\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF'
v = sum(struct.unpack('!%sH' % int(len(data)/2), data))
for i in range(3):
    chksum += v & 0xffff
    v = v >> 16

I understand what it's doing until the for i in range part. One part that gets me is this:

chksum += v & 0xffff

I'm sure v is 8 bytes, and I understand it's basically clearing bits. But it's half the size, so does it do upper or lower?

I don't know. Any help would be appreciated

user3806518
  • 45
  • 1
  • 5

2 Answers2

0

Python numbers are of unspecified bit width - they are of arbitrary size.

The "bitwise and" operator works as advertised, so let's take it step by step:

  1. v & 0xffff - masking the least significant 16 bits (because 2^16-1=0xffff) of v is truncating v to mod 2^16
  2. Add the truncated quantity to chksum
  3. Handle any remaining carry by folding the sum on itself (the Internet Checksum is computed on 16-bit integers)

Your code is incomplete in handling (3), but the idea is the same. For more info, see the RFC.

Michael Foukarakis
  • 39,737
  • 6
  • 87
  • 123
  • Well, the return value is chksum ^ 0xffff, so I do think (3) is handled. I think I understand a little better, so when we do chksum += v & 0xffff it really kind of adjust itself to the size of the operand with leading zeros? such as 0x00ffff or 0x0ffff? – user3806518 Jul 14 '14 at 06:56
  • Your questions are answered in the RFC, especially in §4.1 – Michael Foukarakis Jul 14 '14 at 07:01
  • How is it RFC? That's a Python thing... Let's say v is 0x46325FFFFF and we go v & 0xFFFF. Does it adjust to the size of v with leading 0s or what? Yea, don't point me to RFC when it's not what I'm asking. – user3806518 Jul 14 '14 at 07:09
  • Yes, you said it's truncating, but the question is how? I understand it all now 100% thanks to your answer, but I would like to know how it truncates it. – user3806518 Jul 14 '14 at 07:22
  • If you want to know exactly what bitwise AND means, you could start [here](http://stackoverflow.com/questions/1746613/bitwise-operation-and-usage). – Michael Foukarakis Jul 14 '14 at 07:45
0

The string evaluates to '!4H' which happens to be a group of 4 unsigned short values.

Note that v without the sum is = (struct.unpack('!%sH' % int(len(data)/2), data)) and this is (65535, 65535, 65535, 65535).

Note that 0xffff is 65535.

Unfortunately in Python, this gets converted into an int32 object, and after the sum it results in the value: 262140. Within Python, v.nbytes is 4, and v.dtype is dtype('int32').

Finally, the >> 16 right shifts by 16 bits not 16 bytes, as in '%x'%(0xffff >> 1) = '7fff'

ssm
  • 5,277
  • 1
  • 24
  • 42