First I will need a utility class to:
1. encrypt some plain text and save it to a disk file
2. open the encrypted file and decrypt it into plaintext
With the help of the Python Cryptography Toolkit, I can do that easily:
# filecrypto.py
import os
from Crypto.Hash import SHA256 as HASH
from Crypto.Cipher import Blowfish as CIPHER
class FileCrypto(object):
def _create_cipher(self, password):
h = HASH.new()
h.update(password)
key = h.digest()
h.update(key)
iv = h.digest()[:8]
return CIPHER.new(key, CIPHER.MODE_CFB, iv)
def load(self, filename, password):
'decrypt a file into a string of plain text'
if not os.path.isfile(filename):
return ""
with open(filename, 'rb') as f:
ciphertext = f.read()
cipher = self._create_cipher(password)
return cipher.decrypt(ciphertext)
def save(self, filename, password, plaintext):
'encrypt a string of plain text into a file'
cipher = self._create_cipher(password)
ciphertext = cipher.encrypt(plaintext)
with open(filename, 'wb') as f:
f.write(ciphertext)
I pick Blowfish as the encryption algorithm because it allows variable key size. CFB (Cipher FeedBack) mode is used to that block size padding is not necessary.
For basic unit testing, I add the following to the module:
def unittest():
import random
import string
# test 1 - encrypt 1024 printable chars
filename = "".join( [random.choice(string.hexdigits) for i in range(8)] )
password = "".join( [random.choice(string.printable) for i in range(256)] )
message = "".join( [random.choice(string.printable) for i in range(1024)] )
if os.path.isfile(filename):
os.remove(filename)
fc = FileCrypto()
assert "" == fc.load(filename, password)
fc.save(filename, password, message)
assert message == fc.load(filename, password)
fc = None
if os.path.isfile(filename):
os.remove(filename)
# test 2 - encrypt byte values 0 to 255
filename = "".join( [random.choice(string.hexdigits) for i in range(8)] )
password = "".join( [random.choice(string.printable) for i in range(256)] )
message = "".join( [chr(x) for x in range(256)] )
if os.path.isfile(filename):
os.remove(filename)
fc = FileCrypto()
assert "" == fc.load(filename, password)
fc.save(filename, password, message)
assert message == fc.load(filename, password)
fc = None
if os.path.isfile(filename):
os.remove(filename)
if __name__ == '__main__':
unittest()
import random
import string
# test 1 - encrypt 1024 printable chars
filename = "".join( [random.choice(string.hexdigits) for i in range(8)] )
password = "".join( [random.choice(string.printable) for i in range(256)] )
message = "".join( [random.choice(string.printable) for i in range(1024)] )
if os.path.isfile(filename):
os.remove(filename)
fc = FileCrypto()
assert "" == fc.load(filename, password)
fc.save(filename, password, message)
assert message == fc.load(filename, password)
fc = None
if os.path.isfile(filename):
os.remove(filename)
# test 2 - encrypt byte values 0 to 255
filename = "".join( [random.choice(string.hexdigits) for i in range(8)] )
password = "".join( [random.choice(string.printable) for i in range(256)] )
message = "".join( [chr(x) for x in range(256)] )
if os.path.isfile(filename):
os.remove(filename)
fc = FileCrypto()
assert "" == fc.load(filename, password)
fc.save(filename, password, message)
assert message == fc.load(filename, password)
fc = None
if os.path.isfile(filename):
os.remove(filename)
if __name__ == '__main__':
unittest()
In the next posting, I will build a GUI using this module to encrypt/decrypt a file.
No comments:
Post a Comment