1

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?

rnso
  • 23,686
  • 25
  • 112
  • 234

1 Answers1

2

The problems is that bytes constructor has changed between Python2 and Python3, when it receives an list of integers:

  • in Python3, it builds a byte string where each byte receives a code from the list
  • in Python2, it just converts the list to a string (by using the representation or the string)

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'
Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
  • What can I use which works both for python2 and python3 and where the encoded version can be stored in a text file (not needing write to binary file)? – rnso Dec 07 '17 at 15:09
  • I cannot imagine a totally transparent way, because you are processing bytes which have different behaviour in Python2 and Python3. The only way I know to write compatible code here, is to test the major Python version. – Serge Ballesta Dec 07 '17 at 16:22
  • @rnso: I finally remember the `bytearray` class that allows to write code working in both Python2 and Python3. See my last edit – Serge Ballesta Dec 09 '17 at 12:01