Я пытаюсь написать программу шифрования/дешифрования под названием P-Cypher на python (python-Cypher, рифмуется с decypher). Он использует библиотеки PyCrypto для кодирования файла (с использованием AES). Хотя я знаю Python, я не разбираюсь в криптографии — я делаю это, потому что подумал, что это будет весело, так что не критикуйте меня за безопасность.
Вот так должна работать программа.
- Запрашивает входной файл.
- Спрашивает, хотите ли вы, чтобы он зашифровал или расшифровал. (устанавливает режим)
- Запрашивает выходной файл. Проверяет его существование, если нет, спрашивает, хотите ли вы его создать.
- Шифрует входной файл и сообщает вам ключ/запрашивает ключ и расшифровывает файл с помощью ключа (в зависимости от режима)
- Записывает в выходной файл.
Все работает, кроме пункта 4. (Я знаю, что шаг 5 работает, так как шаг 5 практически не изменился по сравнению с последней стабильной версией v0.03d). На шаге 4 кодирования происходит одна из двух вещей в зависимости от того, как я его кодирую:
- Вещь успешно- YAY! кодирует файл. Однако ключ, который он выводит, имеет вид b'U\xxx\xxx\xxx\xxx\xxx'. Когда я ввожу его в режиме декодирования шага 4, с буквами b и без них или без них, это не работает. Таким образом, программа не может расшифровать файл, что делает половину моей программы бесполезной.
- Я могу использовать .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.')