Error: Odd-length string (Python 3, making a stream cipher)

Viewed 692

Im starting to learn how to work on python beacause of school, and I haven't really had any problem at all; however, last week we were assigned to make a stream cipher, but I've really had a hard time working with it. The code is the following:

import binascii

mode = 0

def asktodo():
    while True:
        print('Do you wish to encrypt or decrypt your message?')
        mode = input().lower()
        if mode in 'encrypt e decrypt d'.split():
            return mode
        else:
            print('Enter either "encrypt" or "e", or "decrypt" or "d".')

def message():
    inp = input('Input your message:\n')
    inp = inp.lower()
    return inp     

def gkey():
    nkey = int(input('Input your key:\n'))
    return nkey

def encrypt(plaintext,key):
    ciphered=""
    for x in plaintext:
        ptd=ord(x)
        cip=ptd^key
        ciphered=ciphered+chr(cip)
    ciphered=bytes(ciphered, 'utf-8')
    return binascii.hexlify(ciphered)

def decrypt(ciphered,key):
    ciphered=binascii.unhexlify(ciphered)
    ciphered=str(ciphered, 'utf-8')
    plain=''
    for x in ciphered:
        ctd=ord(x)
        descip=ctd^key
        plain=plain+chr(descip)
     return plain

mode = asktodo()
mess= message()
xkey = gkey()

if mode == 'e' or mode == 'encrypt':
    print(' ')
    print('Your encrypted message is:') 
    print(encrypt(mess, xkey))
else:
    print(' ')
    print('Your decrypted message is:') 
    print(decrypt(mess, xkey))

input()

The encription part works perfectly. However, when I try to decrypt any message the following error pops out:

--line 33, in decrypt
   - ciphered=binascii.unhexlify(ciphered)

Error: Odd-length string

I've tried many ways and followed many advises, but I just can't solve it.

P.S.: The code changes the values to hexadecimal before giving you the encrypted message.

1 Answers

I can't reproduce your error:

In [12]: import binascii                                                         
    ...:                                                                         
    ...: def asktodo():                                                          
    ...:     while True:                                                         
    ...:         mode = input('Do you wish to encrypt or decrypt your message?') 
    ...:         mode = mode.lower()                                             
    ...:         if mode in 'encrypt e decrypt d'.split():                       
    ...:             return mode                                                 
    ...:         else:                                                           
    ...:             print('Enter either "encrypt" or "e", or "decrypt" or "d".')
    ...:                                           
    ...: def message():                            
    ...:     inp = input('Input your message:\n')  
    ...:     inp = inp.lower()                     
    ...:     return inp                            
    ...:                                           
    ...: def gkey():
    ...:     nkey = int(input('Input your key:\n'))
    ...:     return nkey
    ...: 
    ...: def encrypt(plaintext,key):
    ...:     ciphered=""
    ...:     for x in plaintext:
    ...:         ptd=ord(x)
    ...:         cip=ptd^key
    ...:         ciphered=ciphered+chr(cip)
    ...:     ciphered=bytes(ciphered, 'utf-8')
    ...:     return binascii.hexlify(ciphered)
    ...: 
    ...: def decrypt(ciphered,key):
    ...:     ciphered=binascii.unhexlify(ciphered)
    ...:     ciphered=str(ciphered, 'utf-8')
    ...:     plain=''
    ...:     for x in ciphered:
    ...:         ctd=ord(x)
    ...:         descip=ctd^key
    ...:         plain=plain+chr(descip)
    ...:     return plain
    ...: 
    ...: print('')
    ...: mess= message()
    ...: xkey = gkey()
    ...: print('Your encrypted message is:') 
    ...: print(encrypt(mess, xkey))
    ...: 
    ...: print('')
    ...: mess= message()
    ...: xkey = gkey()
    ...: print('Your decrypted message is:') 
    ...: print(decrypt(mess, xkey))
    ...: 
    ...:     

Input your message:
test1
Input your key:
123
Your encrypted message is:
b'0f1e080f4a'

Input your message:
0f1e080f4a
Input your key:
123
Your decrypted message is:
test1

Most likely, I guess, is that you are entering the byte string representation including b and apostrophes. That is, in the decryption part you likely enter:

Input your message:
b'0f1e080f4a'

That string has an odd number of characters (and it shouldn't).

Related