· 7 years ago · Dec 28, 2018, 04:30 PM
1from Crypto import Random
2from Crypto.PublicKey import RSA
3from Crypto.Cipher import AES
4import base64, os
5
6def generate_keys_RSA():
7 # RSA modulus length must be a multiple of 256 and >= 1024
8 modulus_length = 256*4 # use larger value in production
9 privatekey = RSA.generate(modulus_length, Random.new().read)
10 publickey = privatekey.publickey()
11 return privatekey, publickey
12
13def encrypt_message_RSA(a_message, publickey):
14 encrypted_msg = publickey.encrypt(a_message, 32)[0]
15 encoded_encrypted_msg = base64.b64encode(encrypted_msg) # base64 encoded strings are database friendly
16 return encoded_encrypted_msg
17
18def decrypt_message_RSA(encoded_encrypted_msg, privatekey):
19 decoded_msg = base64.b64decode(encoded_encrypted_msg)
20 decoded_decrypted_msg = privatekey.decrypt(decoded_msg)
21 return decoded_decrypted_msg
22
23def generate_key_AES():
24 # AES key length must be either 16, 24, or 32 bytes long
25 AES_key_length = 32
26 secret_key = os.urandom(AES_key_length)
27 encoded_secret_key = base64.b64encode(secret_key)
28 print("key_AES !not encoded!: %s - (%d)" % (secret_key, len(secret_key)))
29 return encoded_secret_key
30
31def encrypt_message_AES(private_msg, encoded_secret_key, padding_character):
32 secret_key = base64.b64decode(encoded_secret_key)
33 cipher = AES.new(secret_key)
34 padded_private_msg = private_msg + (padding_character * ((16 - len(private_msg)) % 16))
35 encrypted_msg = cipher.encrypt(padded_private_msg)
36 encoded_encrypted_msg = base64.b64encode(encrypted_msg)
37 return encoded_encrypted_msg
38
39def decrypt_message_AES(encoded_encrypted_msg, encoded_secret_key, padding_character):
40 secret_key = base64.b64decode(encoded_secret_key)
41 # use the decoded secret key to create a AES cipher
42 cipher = AES.new(secret_key)
43 encrypted_msg = base64.b64decode(encoded_encrypted_msg)
44 decrypted_msg = cipher.decrypt(encrypted_msg)
45 unpadded_private_msg = decrypted_msg.rstrip(padding_character)
46 return unpadded_private_msg.decode("ascii")
47
48##########-BEGIN-##########
49# 'rec' means 'received' #
50# 'enc' means 'encrypted' #
51# 'dec' means 'decrypted' #
52# 'pad' means 'padding' #
53# 'div' means 'division' #
54###########################
55
56raw_txt = input("Message to send: ") # Ask user for text to send
57txt = str(raw_txt) # Parse input to string
58
59pad_char = "{" # Character to concat at the end of the text message to make it the right length
60div_char = "|" # Character to divide the text message and the key with in the final message
61
62## ASSEMBLY ##
63privatekey0_RSA , publickey0_RSA = generate_keys_RSA() # Generate RSA keys for sender
64privatekey1_RSA , publickey1_RSA = generate_keys_RSA() # Generate RSA keys for receiver
65key_AES = generate_key_AES() # Generate AES key for encoding the actual message
66
67enc_txt = encrypt_message_AES(txt, key_AES, pad_char) # Encrypt the txt with the key_AES
68enc_key = encrypt_message_RSA(key_AES, publickey0_RSA) # Encrypt the key_AES with the publickey1_RSA
69
70msg = ( # Assemble the full msg to send
71 pad_char.encode("utf-8") + # Add pad_char after encoding it in utf-8
72 div_char.encode("utf-8") + # Add div_char after encoding it in utf-8
73 enc_txt + # Add enc_txt
74 div_char.encode("utf-8") + # Add div_char after encoding it in utf-8
75 enc_key # Add enc_key
76 )
77
78## DISASSEMBLY ##
79rec_enc_pad = msg[: 1] # Extract rec_enc_pad from received msg
80rec_enc_div = chr(msg[1]) # Extract rec_enc_div from received msg
81rec_enc_txt = msg[2 : (msg[2:].find(rec_enc_div.encode("utf-8")) + 2)] # Extract rec_enc_txt from received msg
82rec_enc_key = msg[(msg[2:].find(rec_enc_div.encode("utf-8")) + 1) :] # Extract rec_enc_key from received msg
83dec_key = decrypt_message_RSA(rec_enc_key, privatekey0_RSA) # Decrypt the rec_enc_key with the privatekey1_RSA
84dec_txt = decrypt_message_AES(rec_enc_txt, dec_key, rec_enc_pad) # Decrypt the rec_enc_txt with the rec_enc_key and the rec_enc_pad
85
86## RESULT LOG ##
87print("Total message: %s" % msg)
88print()
89print(" Original key_AES: %s - (%d)" % (key_AES, len(key_AES)))
90print()
91print("Encrypted key_AES: %s - (%d)" % (enc_key, len(enc_key)))
92print()
93print("Decrypted key_AES: %s - (%d)" % (dec_key, len(dec_key)))
94print()
95print("Decrypted key_AES == Original key_AES: %s" % (dec_key == key_AES))
96print()
97print()
98print(" Original text: %s - (%d)" % (txt, len(txt)))
99print()
100print("Encrypted text: %s - (%d)" % (enc_txt, len(enc_txt)))
101print()
102print("Decrypted text: %s - (%d)" % (dec_txt, len(dec_txt)))
103print()
104print("Decrypted text == Original text: %s" % (dec_txt == txt))