0

I'm trying to write an encryption/decryption program called P-Cypher in python (python-Cypher, rhymes with decypher). It uses the PyCrypto libraries to encode a file (using AES). Although I know Python, I do not know cryptography - I'm doing this because I thought it would be fun, so don't critique me on security.

This is how the program is supposed to work.

  1. Asks for input file.
  2. Asks whether you want it to encrypt or decrypt. (sets mode)
  3. Asks for output file. Verifies it exists- if it does not, asks if you want it to create one.
  4. Encrypts input file and tells you the key/Prompts you for the key, and decrypts the file with the key (Depending on mode)
  5. Writes to output file.

Everything works except for number 4. (I know step 5 works as step 5 remains pretty much unchanged from the last stable version, v0.03d). On step 4 encoding, one of two things happen depending on which way I code it:

  1. The thing successfully- YAY! encodes the file. However, the key it prints out is in the form of b'U\xxx\xxx\xxx\xxx\xxx' like that. When I enter it in step 4 decoding mode, with or without the b and 's, it doesn't work. So the program cannot decrypt the file, rendering half of my program useless.
  2. I can use .decode(encoding) to turn it into a string. This is the method you see on the code below. However, here is this way's problem- no matter what encoding I use (ascii, ISO, windows-125x, EUR, Big5, utf-8, 16, and 32, etc...) there is always one or more bytes that the encoding cannot encode. And without encoding, there's no decoding, rendering the WHOLE program useless.

So I ask you for help. If you could figure out how to fix problem #1 or #2 (or maybe even both), I would be grateful.

CODE -- Updated

# P-Cypher-Dev
# Made in 2015 by Mateo Guynn
# v0.04d
# Using AES 16/32/64-bit encryption (Google standard)
# DEV VERSION: Possibly unstable, contains better code.
# Changelog:
"""
v0.02d
- Improved Caesar Cipher
- Added binary Cipher converter (fail)
-------------FILE BROKEN------------
"""
"""
v0.03d
- Added ability to create new output files
- Fixed code not quitting on abort
- DEL : binary Cipher converter 
---------------STABLE---------------

"""
"""
v0.04d
- DEL : Caesar Cypher
- Added 16/32/64-byte AES encryption
- Binary and text now handled in same manner
-------------FILE BROKEN------------
(encryption works, decryption does not)

"""
"""
v0.05d
- Changed AES encryption to Google's way
- Fixed Key entry

"""
import os
import sys
from Crypto.Cipher import AES
from Crypto import Random
from Crypto.Util import randpool
import base64
import codecs

MAX_KEY_SIZE = 26 # Shows the number of available characters (26 in the alphabet)

 #NOTES: Binary mode only works if the file is named binary.dat.

def getMode():

    while True:

        eOrD = input('\nDo you wish to encrypt or decrypt a message? ')

        mode = eOrD.lower()

        if mode in 'encrypt e decrypt d'.split():

            return mode

        else:

            sys.exit('\nEnter either "encrypt" or "e" or "decrypt" or "d". Capital letters are allowed.\n')



def getMessage():


    inputFile = open(input('\nPlease enter the name of the file you want to encrypt/decrypt. You may use relative or full paths. \nPlease, remember the file extension(s)! ')).read()
    try:
        print ('\nThe contents of the file are: \n%s\n' % inputFile)
        return inputFile
    except IOError as e:
        sys.exit('Unable to open file (the file does not exist or P-Cypher does not have permission to view it).\n Aborting.')
    except FileNotFoundError as e:
        sys.exit('Unable to open file (the file does not exist or P-Cypher does not have permission to view it).\n Aborting.')


def getCipher(mode, message):
    block_size = 16 # For AES, this is the only working value
    key_size = 32 # Size of crypto key (possibly changes in getKey())
    aesmode = AES.MODE_CBC # More secure mode
    if mode[0] == 'e':
        key_bytes = randpool.RandomPool(512).get_bytes(key_size)
        open('decryption.key', 'wb+').write(key_bytes)
        print('\nYour keyfile is: decryption.key\n')
        pad = block_size - len(message) % block_size
        data = message + pad * chr(pad)
        iv_bytes = randpool.RandomPool(512).get_bytes(block_size)
        encrypted_bytes = iv_bytes + AES.new(key_bytes,aesmode,iv_bytes).encrypt(data)
        encrypted = base64.urlsafe_b64encode(encrypted_bytes)
        return encrypted
    else: 
        decryptb = base64.urlsafe_b64decode(message)
        decrypted_ivbytes = decryptb[:block_size]
        decrypt = decryptb[block_size:]
        print('\nAuto-searching for decryption.key...')
        try:
            key_bytes = base64.urlsafe_b64decode(open('decryption.key', 'rb').read())
        except IOError as io:
            key_bytes = base64.urlsafe_b64decode(open(input('decryption.key not found. If you have an alternate keyfile, please enter its name now. ')), 'rb').read
        except FileNotFoundError as fnf:
            key_bytes = base64.urlsafe_b64decode(open(input('decryption.key not found. If you have an alternate keyfile, please enter its name now. '), 'rb').read())
        decrypted = AES.new(key_bytes, aesmode, decrypted_ivbytes).decrypt(decryptb)
        pad = ord(decrypted[-1])
        decrypted = decrypted[:-pad]
        return decrypted
def getOutput():


    outputFile = input('\nPlease specify an output file. \nDon\'t forget the file extension! ')

    outputCheck = input('\nYour message will be encrypted/decrypted into the following output file: %s\n\nIs this okay? (y/n) ' % outputFile).lower()


    if outputCheck in 'y yes yeah ok'.split():

        try:
            return outputFile
        except IOError as ioerror:
            createNewFile = input('The file you specified does not exist. Shall I create one? (y/n) ')
            if createNewFile in 'y_yes_yeah_yes please_ok'.split('_'):
                oF = open(outputFile, 'w+')
                oF.close()
                return outputFile

            else:
                sys.exit('Aborting...')
    elif outputCheck in 'n no'.split():
        sys.exit('\nAborting...\n')
    else:
        sys.exit('\nAborting.\n')


print("\nP-Cypher Alpha starting up...\n\nv0.05 dev\nMateo Guynn\n2015\n")
mode = getMode()
message = getMessage()

try:
    open(getOutput(), 'wb+').write(getCipher(mode,message))
except IOError:
    sys.exit('Oh noes! Something has gone terribly wrong!')
except FileNotFoundError:
    sys.exit('Your input file was not found.')
print('\nDone.')

1 Answer 1

1

one solution is to encode it as hex ... this is guaranteed to be ascii characters

import codecs
my_key = "U\x22\x54\x33"
print ("Your Key:", codecs.encode(my_key,"hex"))


...

my_decode_key = codecs.decode(input("enter key:"),"hex")
print( repr(my_decode_key))
print( my_decode_key == my_key )
Sign up to request clarification or add additional context in comments.

3 Comments

Sorry, but it didn't work. It said 'non-hexadecimal digit found'. Thanks anyways.
To clarify, the code you posted works. However, when I use codecs.encode on MY code, it gives me that error. Your code just doesn't work on mine.
any byte string should be hex encodable ... this leads me to believe you are doing something wrong

Your Answer

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