I am attempting to encrypt and decrypt 5-14 MB text files with two Python files, one containing encrypt/decrypt methods and another being a runner for those methods.
Here's the class file:
from Crypto.Cipher import AES
from Crypto import Random
import sys
import codecs
reload(sys)
sys.setdefaultencoding('utf8')
sys.stdout = codecs.getwriter('utf8')(sys.stdout)
class Crypt:
def __init__(self, encrypted, key):
self.message = encrypted
self.key = key
def encrypt(self):
iv = Random.new().read(AES.block_size)
if len(self.message) % AES.block_size != 0:
self.message += " " * (AES.block_size - (len(self.message) % AES.block_size))
lenKey = len(self.key)
if lenKey > 32:
self.key = self.key[:32]
cipher = AES.new(self.key, AES.MODE_CFB, iv)
return iv + cipher.encrypt(self.message)
def decrypt(self):
iv, message = (self.message[:AES.block_size], self.message[AES.block_size:])
if len(message) % AES.block_size != 0:
message += " " * (AES.block_size - (len(message) % AES.block_size))
lenKey = len(self.key)
if lenKey > 32:
self.key = self.key[:32]
cipher = AES.new(self.key, AES.MODE_CFB, iv)
return cipher.decrypt(message).strip()
Here's the runner:
import crypt_classes
from Crypto.Hash import SHA256
import sys
reload(sys)
sys.setdefaultencoding('utf8')
h = SHA256.new()
while True:
choice = raw_input("Encrypt [1] or decrypt [2]? ").strip()
if choice != "1" and choice != "2":
print "Invalid choice, please try again."
continue
key = ""
first = ""
confirm = ""
while True:
first = raw_input("Enter passphrase (>= 32 chars): ").strip()
# confirm = raw_input("Confirm passphrase: ").strip()
confirm = first
if first == confirm and len(confirm) >= 32:
h.update(first)
key = h.hexdigest()
break
else:
print "Passphrases did not match or were shorter than 32 characters. Try again."
continue
if choice == "1":
f = open("encrypted.txt", "w")
h = open("source.txt", "r")
message = h.read()
h.close()
encrypter = crypt_classes.Crypt(message, key)
e = encrypter.encrypt()
f.write(e)
f.close()
break
elif choice == "2":
f = open("encrypted.txt", "r")
encrypted = f.read()
f.close()
decrypter = crypt_classes.Crypt(encrypted, key)
w = open("decrypted.txt", "w")
o = decrypter.decrypt()
w.write(o)
w.close()
break
Encryption works fine, but as the file is decrypted and the program ostensibly finishes, only a few lines are shown in the file along with a few miscellaneous characters, like so:
# This data file generated by 23andMe at: Thu May 22 15:47:06 2008
#
# Below is a text version of your data. Fields are TAB-separated
# Each line corresponds to a single SNP. For each SNP, we provide its identifier
# (an rsid or an internal id), its lU�
Please comment if any further elaboration is required.
Thank you!
Just use simple functions. I see no need for a class here.
Taking the hex digest and then truncating makes the effective keylength 128 while you seem to want 256.
Don't write encrypted data as UTF8. Don't use padding for CFB mode.
My try (which works on my system); you can put the encrypt and decrypt functions with their imports in a separate file (module), if you like.
from Crypto.Hash import SHA256
from Crypto.Cipher import AES
from Crypto import Random
import sys
def encrypt_data(data, key):
iv=Random.new().read(AES.block_size)
aes=AES.new(key, AES.MODE_CFB, iv)
return iv+aes.encrypt(data)
def decrypt_data(data, key):
iv = data[:16]
data = data[16:]
aes=AES.new(key, AES.MODE_CFB, iv)
return aes.decrypt(data)
h = SHA256.new()
while True:
choice = raw_input("Encrypt [1] or decrypt [2]? ").strip()
if choice != "1" and choice != "2":
print "Invalid choice, please try again."
continue
key = ""
first = ""
confirm = ""
while True:
first = raw_input("Enter passphrase (>= 32 chars): ").strip()
# confirm = raw_input("Confirm passphrase: ").strip()
confirm = first
if first == confirm and len(confirm) >= 32:
h.update(first)
key = h.digest()
break
else:
print "Passphrases did not match or were shorter than 32 characters. Try again."
continue
if choice == "1":
f = open("encryptedDNA.txt", "w")
h = open("genome_Mikolaj_Habryn_20080522154706.txt", "r")
message = h.read()
h.close()
encmessage = encrypt_data(message, key)
f.write(encmessage)
f.close()
break
elif choice == "2":
f = open("encryptedDNA.txt", "r")
encrypted = f.read()
f.close()
decrypted = decrypt_data(encrypted,key)
w = open("decryptedDNA.txt", "w")
w.write(decrypted)
w.close()
break
~