I'm trying to write an encryption/decryption program for Python, using PyCrypto The way the program works is that you specify an input/output, choose your input mode (for the sake of this question AES), and the program encrypts the input to the output file while also writing the encryption key to a file called encryption.key. To decrypt, you specify an input/output again, choose your mode (AES) again, and then the program loads the key from the encryption.key and uses it to decrypt the input.
The problem is, I'm a novice at python and cryptography and don't know how to fix the problem I'm getting. The problem is this: encryption works fine (as far as I can tell), but on decryption binascii throws an error about the keyfile having invalid padding. I'm not sure how to pad correctly- I tried implementing some code to pad it (based off the message pad) but it still throws the error. Does anyone know how to pad this key correctly?
Forgive me for being such a noob, everything I know about AES encryption came from me reverse-engineering some code I found in the source of Google's Keyczar's python implementation.
Now that I think about it, I don't really know why I just didn't use keyczar...
CODE:
#!/usr/bin/python
# -*- coding: utf-8 -*-
# P-Cypher-Dev
# Made in 2015 by Mateo Guynn
# v0.05 dev
# Using AES encryption \ Caesar Cipher
# 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
- Added mode switcher
- Readded Caesar Cipher to mode switcher (defaults to AES)
----------------O.K.----------------
(AES decryption broken)
"""
"""
v0.05g (v0.05 gui)
- Initial tests of a GUI
"""
import os
import sys#!/usr/bin/python
# -*- coding: utf-8 -*-
# P-Cypher-Dev
# Made in 2015 by Mateo Guynn
# v0.05 dev
# Using AES encryption \ Caesar Cipher
# 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
- Added mode switcher
- Readded Caesar Cipher to mode switcher (defaults to AES)
----------------O.K.----------------
(AES decryption broken)
"""
"""
v0.05g (v0.05 gui)
- Initial tests of a GUI
"""
import os
import sys
from Crypto.Cipher import AES
from Crypto import Random
from Crypto.Util import randpool
import base64
currentEncryptions = ['AES', 'Caesar Cipher']
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 getAESCipher(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)
pad_key = block_size - len(key_bytes) % block_size
key_bytes_write = key_bytes + pad_key * bytearray(pad_key)
open('decryption.key', 'wb+').write(key_bytes_write)
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:
if os.stat(outputFile).st_size != 0:
overwriteFile = input('The file you specified is not empty. Do you want to overwrite it? (y/n)')
if overwriteFile in 'y_yes_yeah_yes please_please_ok'.split('_'):
return outputFile
else:
sys.exit('Aborting.')
else:
return outputFile
except IOError as ioerror:
createNewFile = input('The file you specified does not exist. Shall I create one? (y/n) ').lower()
if createNewFile in 'y_yes_yeah_yes please_ok_please'.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')
def getEncrypt(mode,message,cipherMode):
case = cipherMode
if case == 0: # If the cipherMode is set to AES -- implemented
return getAESCipher(mode,message)
elif case == 1: # If the cipherMode is set to Blowfish -- not implemented
return getBlowfishCipher(mode,message)
elif case == 2: # If the cipherMode is set to SHA -- not implemented
return getSHAHash(mode,message)
elif case == 3: # If the cipherMode is set to HMAC -- not implemented
return getHMACHash(mode,message)
elif case == 4: # If the cipherMode is set to PublicKey -- not implemented
return getPublicKey(mode,message)
elif case == 5: # If the cipherMode is set to Caesar -- implemented
return getCaesarCipher(mode,message)
else: # If no case is found
print('No cipher mode found. Defaulting to AES.')
return getAESCipher(mode,message)
def getShiftNum(mode): # Used in the Caesar Cipher to determine the amount of characters to shift the message.
if mode[0] == 'e':
shiftNumInput = input('\nHow many characters would you like to shift the message? (1-26) ')
else:
shiftNumInput = input('\nPlease enter your shift number. (1-26) ')
try:
shiftNum = int(shiftNumInput)
if shiftNum >= 1 and shiftNum <= 26:
return shiftNum
else:
sys.exit('\nSorry, but that\'s not in the specified range. Aborting.\n')
except TypeError:
sys.exit('\nSorry, but that\'s not an integer. Aborting.\n')
except:
sys.exit('Input error. Aborting.')
def getBlowfishCipher(mode,message):
# This ain't implemented yet! Coming soon (possibly)
sys.exit('Sorry, but blowfish encryption is not currently implemented. Available encryptions: %s' % currentEncryptions)
def getSHAHash(mode,message):
# This ain't implemented yet! Coming soon (possibly)
sys.exit('Sorry, but SHA hash encryption is not currently implemented. Available encryptions: %s' % currentEncryptions)
def getHMACHash(mode,message):
# This ain't implemented yet! Coming soon (possibly)
sys.exit('Sorry, but HMAC hash encryption is not currently implemented. Available encryptions: %s' % currentEncryptions)
def getPublicKey(mode,message):
# This ain't implemented yet! Coming soon (possibly)
sys.exit('Sorry, but public keys are not currently implemented. Available encryptions: %s' % currentEncryptions)
def getCaesarCipher(mode,message):
key = getShiftNum(mode)
encryptedMessage = ''
if mode[0] == 'd':
key = -key
for symbol in message:
if symbol.isalpha():
num = ord(symbol)
num += key
if symbol.isupper():
if num > ord('Z'):
num -= 26
elif num < ord('A'):
num += 26
elif symbol.islower():
if num > ord('z'):
num -= 26
elif num < ord('a'):
num += 26
encryptedMessage += chr(num)
else:
encryptedMessage += symbol
return encryptedMessage
def getCipherMode():
cipherModeInput = input('\nPlease select your encryption mode. Available encryptions are: %s. ' % currentEncryptions).lower()
if cipherModeInput in 'aes_advanced encryption standard_a'.split('_'):
print('\nEncrypting with AES.')
cipherMode = 0
return cipherMode
elif cipherModeInput in 'blowfish b blow fish'.split():
print('\nEncrypting with Blowfish.')
cipherMode = 1
return cipherMode
elif cipherModeInput in 'sha_sha-256_sha-512_sha-1_sha-2_sha-3_secure hash algorithm_secure hash_sha 256_ sha 512_sha 1_sha 2_sha 3'.split('_'):
print('\nEncrypting with SHA.')
cipherMode = 2
return cipherMode
elif cipherModeInput in 'hmac_hash-based message authentication code_hash based message authentication code_h'.split('_'):
print('\nEncrypting with HMAC.')
cipherMode = 3
return cipherMode
elif cipherModeInput in 'p_pk_k_public_key_public key'.split('_'):
print('\nEncrypting with a public key.')
cipherMode = 4
return cipherMode
elif cipherModeInput in 'caesar_cipher_cypher_caesar cipher_caesar cypher_shifter'.split('_'):
print('\nEncrypting with a Caesar Cipher.')
cipherMode = 5
return cipherMode
else:
cipherMode = 20
return cipherMode
def startup():
print("\nP-Cypher Alpha starting up...\n\nv0.05 dev\nMateo Guynn\n2015\n")
mode = getMode()
message = getMessage()
cipherMode = getCipherMode()
if cipherMode != 5:
try:
open(getOutput(), 'wb').write(getEncrypt(mode,message,cipherMode))
except IOError:
sys.exit('Oh noes! Something has gone terribly wrong!')
except FileNotFoundError:
sys.exit('Your input file was not found.')
else:
try:
open(getOutput(), 'w+').write(getEncrypt(mode,message,cipherMode))
except IOError:
sys.exit('Oh noes! Something has gone terribly wrong!')
except FileNotFoundError:
sys.exit('Your input file was not found.')
print('\nDone.')
startup()
from Crypto.Cipher import AES
from Crypto import Random
from Crypto.Util import randpool
import base64
currentEncryptions = ['AES', 'Caesar Cipher']
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 getAESCipher(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)
pad_key = block_size - len(key_bytes) % block_size
key_bytes_write = key_bytes + pad_key * bytearray(pad_key)
open('decryption.key', 'wb+').write(key_bytes_write)
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:
if os.stat(outputFile).st_size != 0:
overwriteFile = input('The file you specified is not empty. Do you want to overwrite it? (y/n)')
if overwriteFile in 'y_yes_yeah_yes please_please_ok'.split('_'):
return outputFile
else:
sys.exit('Aborting.')
else:
return outputFile
except IOError as ioerror:
createNewFile = input('The file you specified does not exist. Shall I create one? (y/n) ').lower()
if createNewFile in 'y_yes_yeah_yes please_ok_please'.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')
def getEncrypt(mode,message,cipherMode):
case = cipherMode
if case == 0: # If the cipherMode is set to AES -- implemented
return getAESCipher(mode,message)
elif case == 1: # If the cipherMode is set to Blowfish -- not implemented
return getBlowfishCipher(mode,message)
elif case == 2: # If the cipherMode is set to SHA -- not implemented
return getSHAHash(mode,message)
elif case == 3: # If the cipherMode is set to HMAC -- not implemented
return getHMACHash(mode,message)
elif case == 4: # If the cipherMode is set to PublicKey -- not implemented
return getPublicKey(mode,message)
elif case == 5: # If the cipherMode is set to Caesar -- implemented
return getCaesarCipher(mode,message)
else: # If no case is found
print('No cipher mode found. Defaulting to AES.')
return getAESCipher(mode,message)
def getShiftNum(mode): # Used in the Caesar Cipher to determine the amount of characters to shift the message.
if mode[0] == 'e':
shiftNumInput = input('\nHow many characters would you like to shift the message? (1-26) ')
else:
shiftNumInput = input('\nPlease enter your shift number. (1-26) ')
try:
shiftNum = int(shiftNumInput)
if shiftNum >= 1 and shiftNum <= 26:
return shiftNum
else:
sys.exit('\nSorry, but that\'s not in the specified range. Aborting.\n')
except TypeError:
sys.exit('\nSorry, but that\'s not an integer. Aborting.\n')
except:
sys.exit('Input error. Aborting.')
def getBlowfishCipher(mode,message):
# This ain't implemented yet! Coming soon (possibly)
sys.exit('Sorry, but blowfish encryption is not currently implemented. Available encryptions: %s' % currentEncryptions)
def getSHAHash(mode,message):
# This ain't implemented yet! Coming soon (possibly)
sys.exit('Sorry, but SHA hash encryption is not currently implemented. Available encryptions: %s' % currentEncryptions)
def getHMACHash(mode,message):
# This ain't implemented yet! Coming soon (possibly)
sys.exit('Sorry, but HMAC hash encryption is not currently implemented. Available encryptions: %s' % currentEncryptions)
def getPublicKey(mode,message):
# This ain't implemented yet! Coming soon (possibly)
sys.exit('Sorry, but public keys are not currently implemented. Available encryptions: %s' % currentEncryptions)
def getCaesarCipher(mode,message):
key = getShiftNum(mode)
encryptedMessage = ''
if mode[0] == 'd':
key = -key
for symbol in message:
if symbol.isalpha():
num = ord(symbol)
num += key
if symbol.isupper():
if num > ord('Z'):
num -= 26
elif num < ord('A'):
num += 26
elif symbol.islower():
if num > ord('z'):
num -= 26
elif num < ord('a'):
num += 26
encryptedMessage += chr(num)
else:
encryptedMessage += symbol
return encryptedMessage
def getCipherMode():
cipherModeInput = input('\nPlease select your encryption mode. Available encryptions are: %s. ' % currentEncryptions).lower()
if cipherModeInput in 'aes_advanced encryption standard_a'.split('_'):
print('\nEncrypting with AES.')
cipherMode = 0
return cipherMode
elif cipherModeInput in 'blowfish b blow fish'.split():
print('\nEncrypting with Blowfish.')
cipherMode = 1
return cipherMode
elif cipherModeInput in 'sha_sha-256_sha-512_sha-1_sha-2_sha-3_secure hash algorithm_secure hash_sha 256_ sha 512_sha 1_sha 2_sha 3'.split('_'):
print('\nEncrypting with SHA.')
cipherMode = 2
return cipherMode
elif cipherModeInput in 'hmac_hash-based message authentication code_hash based message authentication code_h'.split('_'):
print('\nEncrypting with HMAC.')
cipherMode = 3
return cipherMode
elif cipherModeInput in 'p_pk_k_public_key_public key'.split('_'):
print('\nEncrypting with a public key.')
cipherMode = 4
return cipherMode
elif cipherModeInput in 'caesar_cipher_cypher_caesar cipher_caesar cypher_shifter'.split('_'):
print('\nEncrypting with a Caesar Cipher.')
cipherMode = 5
return cipherMode
else:
cipherMode = 20
return cipherMode
def startup():
print("\nP-Cypher Alpha starting up...\n\nv0.05 dev\nMateo Guynn\n2015\n")
mode = getMode()
message = getMessage()
cipherMode = getCipherMode()
if cipherMode != 5:
try:
open(getOutput(), 'wb').write(getEncrypt(mode,message,cipherMode))
except IOError:
sys.exit('Oh noes! Something has gone terribly wrong!')
except FileNotFoundError:
sys.exit('Your input file was not found.')
else:
try:
open(getOutput(), 'w+').write(getEncrypt(mode,message,cipherMode))
except IOError:
sys.exit('Oh noes! Something has gone terribly wrong!')
except FileNotFoundError:
sys.exit('Your input file was not found.')
print('\nDone.')
startup()
Aucun commentaire:
Enregistrer un commentaire