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