# How to work with bytes in Python

Page 1 of 1

## 5 Replies - 18173 Views - Last Post: 22 July 2011 - 01:28 PMRate Topic: //<![CDATA[ rating = new ipb.rating( 'topic_rate_', { url: 'http://www.dreamincode.net/forums/index.php?app=forums&module=ajax&section=topics&do=rateTopic&t=240431&amp;s=67706396947154cefeaeae3725111ab6&md5check=' + ipb.vars['secure_hash'], cur_rating: 0, rated: 0, allow_rate: 0, multi_rate: 1, show_rate_text: true } ); //]]>

### #1 duffman18

Reputation: 15
• Posts: 54
• Joined: 20-October 10

# How to work with bytes in Python

Posted 21 July 2011 - 08:41 AM

I am messing around with making encryption algorithms and have run into a simple yet annoying problem when trying to work with plain bytes. Right now I am just trying to do a very very simple encryption algorithm on a file. It is nothing fancy just doing some bit-wise operations on each byte of the file and writing that new data to a new encrypted file. The algorithm is simple:
```initialData = file.read(1)
newData = initialData >> 1(with carry of LSB to MSB)
newData = ~newData
newData = newData * key(key is an int passed to the algorithm)
pad newData to 2 bytes with 0s
encryptedFile.write(newData)

```

So with that algorithm in mind I wrote this code to try and do that:
```def encrypt(fileName, key, m = ''):
if m == '':
fWrite = open(fileName+'encrypted.txt', 'wb')

while tempB != b'':
if (tempB & b'\x01') != b'\x00':
newB = tempB>>1
newB = newB | b'\x80'
else:
newB = tempB>>1
newB = ~newB
newB = newB*key
bytesWritten = fWrite.write(newB)
print(bytesWritten)

fWrite.close()
return

```

However python is not even letting me do these bit-wise operations on the bytes. I keep getting "TypeError: unsupported operand type(s)" for the operations(&, >>, and ~) which I thought were bit-operations(bit-wise AND, rotate right, and bit-wise invert respectively). Is there a way to get the full individual bit control without having to make my own class for this application? Also I know I have not padded the newB out to 2 bytes with 0s yet. I could not even get to try doing that because I can't even execute the previous parts of the algorithm yet.

Is This A Good Question/Topic? 0

## Replies To: How to work with bytes in Python

### #2 Motoma

Reputation: 452
• Posts: 798
• Joined: 08-June 10

## Re: How to work with bytes in Python

Posted 21 July 2011 - 09:03 AM

Which version of Python?

You can use ord() to convert a single byte to an integer which you can perform bitwise ops on.

### #3 duffman18

Reputation: 15
• Posts: 54
• Joined: 20-October 10

## Re: How to work with bytes in Python

Posted 21 July 2011 - 09:11 AM

Motoma, on 21 July 2011 - 09:03 AM, said:

Which version of Python?

Sorry forgot to include that I am using Python v3.1. Thanks for the help I'll give ord() a try.

### #4 baavgai

• Dreaming Coder

Reputation: 7150
• Posts: 14,890
• Joined: 16-October 07

## Re: How to work with bytes in Python

Posted 21 July 2011 - 09:23 AM

So:
```def encodeByte(initialData, key):
newData = initialData >> 1
newData = ~newData
newData = newData * key
return newData

```

The problem is you're either relying on an overflow behavior that doesn't exist in Python. Or, and I'm guessing this is the case, you're trying to manipulate a 'byte' object, which is really just a string representation of an encoding.

e.g.
```>>> encodeByte(3, 42)
-84
>>> n = '\x03'
>>> n
'\x03'
>>> len(n)
1
>>> int(n)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: '\x03'
>>> import struct
>>> struct.unpack('B',n)
(3,)
>>> encodeByte(b, 42)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in encodeByte
TypeError: unsupported operand type(s) for >>: 'str' and 'int'
>>>

```

### #5 duffman18

Reputation: 15
• Posts: 54
• Joined: 20-October 10

## Re: How to work with bytes in Python

Posted 22 July 2011 - 07:31 AM

Thanks to the help from you guys I got my code working the way I wanted and also I got the decryption method working. There were a few difficulties I had with the invert, but in the end I got it working and will be able to do this again in a more elaborate encryption algorithm. Here is how I wrote the encryption method:
```def encrypt(fileName, key, m = ''):
if m == '':
fWrite = open('encrypted'+fileName, 'wb')

while tempB != b'':
intB = ord(tempB) #convert the byte to an int
if intB%2 != 0: #Check if odd or even(LSB is set or not)
newB = intB>>1
newB = newB + 128 # add 128(\x80) is the same as carrying the LSB when it is set.
else:
newB = (intB>>1)
newB = (~newB) & 255 #& with 255 to drop the leading 1s that you get
newB = newB*key
LBi = newB%256 # isolates the lower byte
UBi = (newB>>8)%256 # rotates right to get the upper byte
encryptedBytes = bytearray([UBi, LBi])
bytesWritten = fWrite.write(encryptedBytes)
print('eBytes Written:'+str(bytesWritten))

fWrite.close()
return

```

And here is how I handled the decryption method:
```def decrypt(fileName, key):
fWrite = open('decrypted'+fileName, 'wb')

#reads in the 2 bytes seperately
#the only while loop condition needed because you know any
#file encrypted will have an even number of bytes
while tempLB != b'' and tempUB != b'':
intUB = ord(tempUB)
intLB = ord(tempLB)
intB = (intUB<<8)+intLB
intB = (intB//key)
# & with 255 here to change the leading 1 you get from ~ to a 0
# and keep the rest the same.
intB = (~intB) & 255
if intB > 127: #check if the MSB is 1
newB = intB<<1
newB += 1 # carry the 1 to the LSB
newB = newB%256 # gets rid of the original 1 in the MSB
else:
newB = intB<<1
decryptedBytes = bytearray([newB])
bytesWritten = fWrite.write(decryptedBytes)
print('dBytes Written:'+str(bytesWritten))
fWrite.close()
return

```

I forgot when I was doing the bit-wise invert that in an integer variable there were all the leading 0s in the block of memory. Therefore when I inverted the number I always got -(N+1) where N is my number I was inverting. This was not the behavior I wanted for this application. I wanted it to be an unsigned 8-bit int, but there is no way to specify this so all I had to do was & the number with 255(or \xFF) to keep just the lower 8 bits and make the rest 0. That way I will always get a positive 8-bit integer. Thanks again baavgai and Motoma for your help.

### #6 baavgai

• Dreaming Coder

Reputation: 7150
• Posts: 14,890
• Joined: 16-October 07

## Re: How to work with bytes in Python

Posted 22 July 2011 - 01:28 PM

This was kind of interesting, but I have a problem with it: I can't test it without a file! Indeed, encryption implementation should be reasonably separate from file IO... what would that take?

I isolated your encryption to look something like:
```def encrypt(intB, key):
newB = intB>>1
if not intB%2 == 0:
newB = newB + 128 # add 128(\x80) is the same as carrying the LSB when it is set.
newB = (~newB) & 255 #& with 255 to drop the leading 1s that you get
newB = newB*key
return ( (newB>>8)%256, newB%256 )

```

I'm dubious of those mods. You should be able to do it all with an & 255. This works the same:
```def encrypt(intB, key):
def toByte(n): return n & 255
newB = toByte(~((intB>>1) + ((intB%2) * 128))) * key
return ( toByte(newB>>8), toByte(newB) )

```

So, a decrypt with similar considerations:
```def decrypt(intUB, intLB, key):
def toByte(n): return n & 255
intB = toByte(~(((intUB<<8)+intLB)//key))
newB = intB<<1
if intB > 127:
newB += 1