2

I am converting 3 letters into their ASCII binary notation and then incrementing the first letter by 16 places, the second letter by 8 places, and the last is staying where it is, so that when the 24 bit stream is configured, the first 8 bit places represents the first letter, the next 8 the middle letter and the last represent the last letter. Here's my code:

# create a block for the word 'Ozy'
bk1 = (ord('O')<<16) + (ord('z')<<8) + (ord('y'))
# Now take off the encryption for the block
cbk1 = ((chr(bk1>>16)) + (chr(bk1>>8)) + (chr(bk1&0xFF)))
# output of cbk1 is: 'O\u4f7ay'

So thats where the problem is, the first letter was decrypted as O, the last letter was correct as well as y, but for some reason it won't do the right thing for z. What's wrong?

Gilles 'SO- stop being evil'
  • 104,111
  • 38
  • 209
  • 254

3 Answers3

1

Looks like you're missing an & 0xff:

cbk1 = ((chr(bk1>>16)) + (chr((bk1>>8) & 0xff)) + (chr(bk1&0xFF)))

yields the correct answer. When reshifting back you need to mask out the upper bits as well because the bits set by the first character (shifted by 16 bit) will still be there.

Dennis Bliefernicht
  • 5,147
  • 1
  • 28
  • 24
1

This happens because you forgot to filter-out the bits from the first letter!
Indeed the ASCII value for the 2nd letter, 'z', shows as '7a', but as you see it has '4f' (i.e. the ASCII for 'O'), in front of it. Try something like:
cbk1 = ((chr(bk1>>16)) + (chr((bk1 & 0xFF00)>>8) ) + (chr(bk1&0xFF)))

As pointed out in warvariuc's answer, Python's struct module helps managing the packing and unpacking of records of various form, but at this point in your learning of Python and of codification systems at large, you probably want to stick with explicit bit-wise manipulation.

mjv
  • 73,152
  • 14
  • 113
  • 156
0
>>> import struct
>>> a = chr(0) + 'Ozy' # make the data 4 byte long
>>> x = struct.unpack('>I', a)[0] # convert byte data into unsigned integer of 4 bytes
>>> hex(x) # it should be 3 bytes long, because first byte was 0x00
'0x4f7a79'
>>> a = struct.pack('>I', x)[1:] # pack the integer back to bytes and throw away the left most 0x00 byte
>>> a
'Ozy'
>>> 
warvariuc
  • 57,116
  • 41
  • 173
  • 227