from Crypto.PublicKey import RSA from Crypto import Random KEYSIZE = 256 * 8 def readfile(filename): fh = open(filename, 'rb') string = fh.read() fh.close() return string def writefile(filename, string): fh = open(filename, 'wb') fh.write(string) fh.close() random_generator = Random.new().read RSAkey = RSA.generate(KEYSIZE, randfunc=random_generator, progress_func=None, e=65537) public_key = RSAkey.publickey() # Export the public key pke = public_key.exportKey(format='PEM', passphrase=readfile('public_passphrase.txt'), pkcs=1) writefile('../Public/public_key.txt', pke) # Export the private key pke = RSAkey.exportKey(format='PEM', passphrase=readfile('private_passphrase.txt'), pkcs=1) writefile('private_key.txt', pke)This generates a 2048-bit RSA key from which I can extract the public key. I export the key to two text files: 'public_key.txt' and 'private_key.txt'. As their names suggest the public key may be shared but the private key is meant for the sender and receiver only. The public key may be used only to encrypt data whereas the private key may be used to encrypt and decrypt data. There is an extra password/passphrase on the key export process which is needed by both parties to import the key(s). With my key in place I can now encrypt my file2encrypt.txt file.
from Crypto.Signature import PKCS1_v1_5 from Crypto.Hash import SHA256 from Crypto.PublicKey import RSA import cPickle def readfile(filename): fh = open(filename, 'rb') string = fh.read() fh.close() return string def writefile(filename, string): fh = open(filename, 'wb') fh.write(string) fh.close() def write_serial(filename, data): fh = open(filename, 'wb') cPickle.dump(data, fh, protocol=cPickle.HIGHEST_PROTOCOL) fh.close() PASSPHRASE_PRIVATE = readfile('private_passphrase.txt') plainfile = readfile('file2encrypt.txt') RSAkey = readfile('private_key.txt') RSAkey = RSA.importKey(RSAkey, passphrase=PASSPHRASE_PRIVATE) h = SHA256.new(plainfile) signer = PKCS1_v1_5.new(RSAkey) signature = signer.sign(h) # Save signature write_serial('signature.pkl', signature) # Encrypt file write_serial('../Public/encryptedfile.pkl', RSAkey.encrypt(plainfile, ''))This script loads my file2encrypt and the RSA key using the "importKey" function. The author of the encrypted file has the option to "sign" the file so that the recipient has a means of verifying that the encrypted file did indeed come from the sender (ie. the message wasn't changed during transmission). I create a serial signature.pkl file using the cPickle module. The data is encrypted via the RSAkey.encrypt() function and sent to the recipient.
On the recipient end we need to decrypt the file and verify the signature. To accomplish this I exectute the following code. This code imports the private key and verifies the signature of the message generated by the author.
from Crypto.Signature import PKCS1_v1_5 from Crypto.Hash import SHA256 from Crypto.PublicKey import RSA import cPickle def readfile(filename): fh = open(filename, 'rb') string = fh.read() fh.close() return string def read_serial(filename): fh = open(filename, 'rb') data = cPickle.load(fh) fh.close() return data encodedfile = read_serial('../Public/encryptedfile.pkl') RSAkey = readfile('private_key.txt') RSAkey = RSA.importKey(RSAkey, passphrase=readfile('private_passphrase.txt')) # Decrypt data plaindata = RSAkey.decrypt(encodedfile) # Verify author h = SHA256.new(plaindata) verifier = PKCS1_v1_5.new(RSAkey) signature = read_serial('signature.pkl') if verifier.verify(h, signature): print "The signature is authentic.\n" print plaindata else: print "The signature is not authentic."If you print the string "plaindata" you will see "For your eyes only! My secret message". We have succeeded in decrypting the original message and verifying it's authenticity.
No comments:
Post a Comment