Reputation: 24555
I am trying to run code from the answer in this post (which works perfectly with python3 version 3.5.3) with python2 version 2.7.13:
def myencode_str(ori_str, key):
enc = []
for i in range(len(ori_str)):
key_c = key[i % len(key)]
enc_c = (ord(ori_str[i]) + ord(key_c)) % 256
enc.append(enc_c)
return (base64.urlsafe_b64encode(bytes(enc))).decode("utf-8")
I am using following decode fn:
def mydecode(enc_str, key):
dec = []
enc_str = base64.urlsafe_b64decode(enc_str)
for i in range(len(enc_str)):
key_c = key[i % len(key)]
dec_c = chr((256 + enc_str[i] - ord(key_c)) % 256)
dec.append(dec_c)
return "".join(dec)
But I get following error message:
dec_c = chr((256 + enc_str[i] - ord(key_c)) % 256)
TypeError: unsupported operand type(s) for +: 'int' and 'str'
I tried code with following changes but they also do not work:
dec_c = chr((256 + int(enc_str[i]) - int(ord(key_c))) % 256)
ValueError: invalid literal for int() with base 10: '\xc3'
Where is the problem and how can it be solved?
Upvotes: 1
Views: 302
Reputation: 148965
The problems is that bytes
constructor has changed between Python2 and Python3, when it receives an list of integers:
And in Python3 a byte string is an iterable of bytes (which are directly convertible to integers) while it is a mere string in Python2.
So your functions have to be a little changed:
def myencode_str(ori_str, key):
enc = []
for i in range(len(ori_str)):
key_c = key[i % len(key)]
enc_c = (ord(ori_str[i]) + ord(key_c)) % 256
enc.append(enc_c)
return (base64.urlsafe_b64encode(''.join([chr(i) for i in enc])))
def mydecode(enc_str, key):
dec = []
enc_str = [ord(i) for i in base64.urlsafe_b64decode(enc_str)]
for i in range(len(enc_str)):
key_c = key[i % len(key)]
dec_c = chr((256 + enc_str[i] - ord(key_c)) % 256)
dec.append(dec_c)
return "".join(dec)
In fact, it is possible to write those functions so that same code can be used in both Python2 and Python3 with the help of the bytearray
class which has same behaviour in both versions. Simply you must choose whether the input is a byte string or a unicode string. As the algorythm is based on bytes, I choosed to process byte strings in following code. You would need to encode the original string and key (using 'utf8' for full portability) and decode the decoded string to process unicode strings:
def myencode_str(ori_str, key):
enc = []
b = bytearray(ori_str)
k = bytearray(key)
for i, c in enumerate(b):
key_c = k[i % len(key)]
enc_c = (c + key_c) % 256
enc.append(enc_c)
return (base64.urlsafe_b64encode(bytes(bytearray(enc))))
def mydecode(enc_str, key):
dec = []
enc_str = bytearray(base64.urlsafe_b64decode(enc_str))
k = bytearray(key)
for i, c in enumerate(enc_str):
key_c = k[i % len(key)]
dec_c = (c - key_c) % 256
dec.append(dec_c)
return bytes(bytearray(dec))
You can then do in Python2:
>>> myencode_str(b"abcdef", b"XYZ")
'ubu9vL7A'
>>> mydecode('ubu9vL7A', b"XYZ")
'abcdef'
and in Python3:
>>> myencode_str(b"abcdef", b"XYZ")
b'ubu9vL7A'
>>> mydecode(b'ubu9vL7A', b"XYZ")
b'abcdef'
Upvotes: 2