[英]Encryption, encoding and Python (AES)
我正在嘗試在 python (python-Cypher, rhymes with decypher) 中編寫一個名為 P-Cypher 的加密/解密程序。 它使用 PyCrypto 庫對文件進行編碼(使用 AES)。 雖然我知道 Python,但我不知道密碼學 - 我這樣做是因為我認為它會很有趣,所以不要批評我的安全性。
這就是程序應該如何工作。
- 要求輸入文件。
- 詢問您是否希望它加密或解密。 (設置模式)
- 要求輸出文件。 驗證它存在 - 如果不存在,詢問您是否希望它創建一個。
- 加密輸入文件並告訴您密鑰/提示您輸入密鑰,並使用密鑰解密文件(取決於模式)
- 寫入輸出文件。
除了數字 4 之外,一切正常。(我知道第 5 步可以工作,因為第 5 步與上一個穩定版本 v0.03d 幾乎沒有變化)。 在第 4 步編碼中,會發生以下兩種情況之一,具體取決於我編碼的方式:
- 事情成功了 - 耶! 對文件進行編碼。 但是它打印出來的key是b'U\\xxx\\xxx\\xxx\\xxx\\xxx'這樣的形式。 當我在第 4 步解碼模式下輸入它時,無論有沒有 b 和 's,它都不起作用。 所以程序無法解密文件,使我的程序的一半無用。
- 我可以使用 .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.')
一種解決方案是將其編碼為十六進制...保證是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 )
我想我找到了自己的答案! 我真幼稚。 我假設字節輸出將是字母或數字。 實際上,我只是發現我的程序只是發出字節。 它們並不全是字母,數字甚至符號,這就是編碼不起作用的原因(至少是我的理解-如果我錯了,請糾正我)。
我更新了代碼以使用密鑰文件代替打印密鑰,現在加密就可以了! 但是,現在,在解密時,出現“ binascii.Error:不正確的填充”。 誰能幫助我解決這個問題? 我已經更新了問題中的代碼。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.