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