0

I wrote a custom encoding code snippet. When i run it on pyton 3.6 i got type error. I couldn't figure it out exactly. The code snippet is working fine with python 2.7.

import os
import sys
import base64

def encode(key, clear):
    """encode custom """
    enc = []
    for i in range(len(clear)):
        key_c = key[i % len(key)]
        enc_c = chr((ord(clear[i]) + ord(key_c)) % 256)
        #change the int or str
        enc.append(enc_c)
    return base64.urlsafe_b64encode("".join(enc))

clear = "ABCDEFGH"
encode_var = encode("crumbs", clear)

Error Log :

(py3) C:\Dev\crumbles>python s1.py
Traceback (most recent call last):
  File "s1.py", line 45, in <module>
    encode_var = encode("crumbs", clear)
  File "s1.py", line 42, in encode
    return base64.urlsafe_b64encode("".join(enc))
  File "C:\Users\Cookie1\Anaconda3\envs\py3\lib\base64.py", line 118, in urlsafe
_b64encode
    return b64encode(s).translate(_urlsafe_encode_translation)
  File "C:\Users\Cookie1\Anaconda3\envs\py3\lib\base64.py", line 58, in b64encod
e
    encoded = binascii.b2a_base64(s, newline=False)
TypeError: a bytes-like object is required, not 'str'

1 Answer 1

1

You are passing in text, not a binary bytes object. The base64.urlsafe_b64encode() function expects bytes, not text.

Generate bytes instead:

from itertools import cycle

def encode(key, clear):
    """encode custom """
    key, clear = cycle(key.encode()), clear.encode() 
    enc = bytes((c + k) % 256 for c, k in zip(clear, key))
    return base64.urlsafe_b64encode(enc)

I used a few iterator tricks to produce the integers that bytes() accepts.

Note that it is more common to use XOR to produce encrypted bytes when creating a single-key encryption:

from operator import xor

key, clear = cycle(key.encode()), clear.encode() 
enc = bytes(map(xor, clear, key))

That's because XOR is trivially reversed by using the same key; clear XOR key produces the encrypted text, and encrypted XOR key produces the cleartext again.

Sign up to request clarification or add additional context in comments.

6 Comments

Can we join bytes?
Yes, there is a bytes.join() method, but that too only can join other bytes objects.
Hello @MartijnPieters. Your answer helps me. But i cant understand the code what you have posted. Can u please explain in brief.
bytes is really a sequence of integers with values between 0 and 255; when you print these you are shown ASCII characters where possible, but at their heart it’s still a bunch of numbers. In Python 2 you need to go from character to integer with ord() and back from integer to character with chr() but all that is not needed when iterating over bytes (gives you numbers) and building a new bytes object (it accepts numbers).
zip() lets you pair up two sequences. It gives you the first values of the inputs together, then the second values, etc. until one of the inputs is done. cycle() lets you repeat the values of a sequence over and over, indefinitely. So the zip() takes the input cleartext bytes together with the key bytes, the latter cycling through all characters over and over as often as needed, and gives you the individual clear text byte with the right key byte. All that remains to do then is make a new encrypted byte out of those two.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.