Шифрование, кодирование и Python (AES)

Я пытаюсь написать программу шифрования/дешифрования под названием P-Cypher на python (python-Cypher, рифмуется с decypher). Он использует библиотеки PyCrypto для кодирования файла (с использованием AES). Хотя я знаю Python, я не разбираюсь в криптографии — я делаю это, потому что подумал, что это будет весело, так что не критикуйте меня за безопасность.

Вот так должна работать программа.

  1. Запрашивает входной файл.
  2. Спрашивает, хотите ли вы, чтобы он зашифровал или расшифровал. (устанавливает режим)
  3. Запрашивает выходной файл. Проверяет его существование, если нет, спрашивает, хотите ли вы его создать.
  4. Шифрует входной файл и сообщает вам ключ/запрашивает ключ и расшифровывает файл с помощью ключа (в зависимости от режима)
  5. Записывает в выходной файл.

Все работает, кроме пункта 4. (Я знаю, что шаг 5 работает, так как шаг 5 практически не изменился по сравнению с последней стабильной версией v0.03d). На шаге 4 кодирования происходит одна из двух вещей в зависимости от того, как я его кодирую:

  1. Вещь успешно- YAY! кодирует файл. Однако ключ, который он выводит, имеет вид b'U\xxx\xxx\xxx\xxx\xxx'. Когда я ввожу его в режиме декодирования шага 4, с буквами b и без них или без них, это не работает. Таким образом, программа не может расшифровать файл, что делает половину моей программы бесполезной.
  2. Я могу использовать .decode(encoding), чтобы превратить его в строку. Это метод, который вы видите в коде ниже. Однако вот в чем проблема: независимо от того, какую кодировку я использую (ascii, ISO, windows-125x, EUR, Big5, utf-8, 16 и 32 и т. д.), всегда есть один или несколько байтов, которые кодировка не может кодировать. А без кодирования нет декодирования, что делает ВСЮ программу бесполезной.

Поэтому прошу вас о помощи. Если бы вы могли понять, как исправить проблему №1 или №2 (или, может быть, даже обе), я был бы признателен.

КОД — обновлено

# 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.')

person Community    schedule 22.06.2015    source источник


Ответы (1)


одно решение - закодировать его как шестнадцатеричный... это гарантированно символы ascii

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 )
person Joran Beasley    schedule 22.06.2015
comment
Извините, но это не сработало. Пишет "найдена не шестнадцатеричная цифра". В любом случае спасибо. - person ; 23.06.2015
comment
Чтобы уточнить, код, который вы разместили, работает. Однако, когда я использую codecs.encode в МОЕМ коде, это дает мне эту ошибку. Ваш код просто не работает на моем. - person ; 23.06.2015
comment
любая строка байтов должна быть закодирована в шестнадцатеричном формате... это заставляет меня поверить, что вы делаете что-то не так - person Joran Beasley; 23.06.2015