diff --git a/period_1/03-cryptography/301_T01_A01_ Asym_KeyGen_EnDe/Asym.py b/period_1/03-cryptography/301_T01_A01_ Asym_KeyGen_EnDe/Asym.py new file mode 100644 index 0000000..56a1028 --- /dev/null +++ b/period_1/03-cryptography/301_T01_A01_ Asym_KeyGen_EnDe/Asym.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python3 +"""Asymmetric Cryptography -> Key Generation: Tutorial 1 + +The goal of this tutorial is to learn how to generate and use asymmetric keys. +Additionally, you will learn how to encrypt and decrypt messages using generated private and public keys. +In this implementation the message is a string converted to a byte object. +Both methods encrypt and decrypt accept two args: a message and a key to perform its operation. + +Your task is to: + * locate the TODOs in this file + * complete the missing part from the code + * run the test of this tutorial located in same folder. + +To test run 'Asym_t.py' in your command line + +Notes: + * do not change class structure or method signature to not break unit tests + * visit this url for more information on this topic: + https://cryptography.io/en/latest/hazmat/primitives/asymmetric/rsa/ +""" + +from cryptography.exceptions import * +from cryptography.hazmat.primitives.asymmetric import rsa +from cryptography.hazmat.primitives import hashes +from cryptography.hazmat.primitives.asymmetric import padding + + +# TODO 1: Generate first a private key, then a public key. As a result return both values. +# Make sure you generate the keys in the correct order. +# Use recommended algorithm values where possible +# Suggested key size 2048 +def generate_keys(): + private = rsa.generate_private_key( + public_exponent=65537, + key_size=2048, + ) + public = private.public_key() + return private, public + +# TODO 2: Encrypt a passed message using the provided key +# Suggested algorithm is SHA256() +def encrypt(message, key): + try: + return key.encrypt( + message, + padding.OAEP( + mgf=padding.MGF1(algorithm=hashes.SHA256()), + algorithm=hashes.SHA256(), + label=None + ) + ) + except InvalidKey: + return None + + +# TODO 3: Decrypt a passed message using the provided key +# Make sure using the same recommended algorithm values for encryption and decryption +# Suggested algorithm is SHA256(). +def decrypt(ciphertext, key): + try: + return key.decrypt( + ciphertext, + padding.OAEP( + mgf=padding.MGF1(algorithm=hashes.SHA256()), + algorithm=hashes.SHA256(), + label=None + ) + ) + except: + return None + + diff --git a/period_1/03-cryptography/301_T01_A01_ Asym_KeyGen_EnDe/Asym_t.py b/period_1/03-cryptography/301_T01_A01_ Asym_KeyGen_EnDe/Asym_t.py new file mode 100644 index 0000000..6781265 --- /dev/null +++ b/period_1/03-cryptography/301_T01_A01_ Asym_KeyGen_EnDe/Asym_t.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python3 +""" +This test case will verify if the provided solution by a student for Asym.py is correct. +""" +from Asym import * + +if __name__ == '__main__': + + # Generate both private en public keys for each user + alex_prv, alex_pbc = generate_keys() + mike_prv, mike_pbc = generate_keys() + rose_prv, rose_pbc = generate_keys() + + # Create a message + alex_message = b'This is a message for Rose: Hi Rose' + + # Encrypt and decrypt a message using a user asymmetric keys + ciphertext = encrypt(alex_message, rose_pbc) + received_message = decrypt(ciphertext, rose_prv) + + # Compare sent and reveived messages before encryptions and after decryption + # to check if the proccess was applied correctly + if received_message!= None and received_message == alex_message: + print("Success: The received message is properly decrypted by Rose's Private Key.") + else: + print("Fail: The received message is not properly decrypted by Rose's Private Key.") + + + received_message = decrypt(ciphertext, mike_prv) + if received_message== None or received_message == alex_message: + print("Fail: The received message is None or could be decrypted by Mike's Private Key!") + else: + print("Success: The received message could not be decrypted by Mike's Private Key.") + + + received_message = decrypt(ciphertext, alex_pbc) + if received_message== None or received_message == alex_message: + print("Fail: The received message is None or could be decrypted by Alex's Public Key!") + else: + print("Success: The received message could not be decrypted by Alex's Public Key.") \ No newline at end of file diff --git a/period_1/03-cryptography/302_T02_A02_ Asym_KeySaveLoad_1/Asym.py b/period_1/03-cryptography/302_T02_A02_ Asym_KeySaveLoad_1/Asym.py new file mode 100644 index 0000000..ee9f1d7 --- /dev/null +++ b/period_1/03-cryptography/302_T02_A02_ Asym_KeySaveLoad_1/Asym.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python3 +"""Asymmetric Cryptography -> Key Management: Tutorial 2 + +The goal of this tutorial is to learn how to load and store asymmetric keys on the disk. +In previous tutorial you have learned how to generate keys and use them directly to encrypt/decrypt a message, +but in many cases generated keys are stored on and loaded from a disk when they are needed for a specific application. +As a part of the loading and saving process keys are de-/serialized. +It is optionally possible to encrypted before saving using a password. In our example no passwords are needed. +Stored keys in the file system are encoded using PEM encapsulation format. +This format has BEGIN {format} and END {format} markers to separate keys. +Stored keys are located in a subdirectory called *storage* + +Your task is to: + * locate the TODOs in this file + * complete the missing part from the code + * run the test of this tutorial located in same folder. + +To test run 'Asym_t.py' in your command line + +Notes: + * do not change class structure or method signature to not break unit tests + * visit these urls for more information on this topic: + https://cryptography.io/en/latest/hazmat/primitives/asymmetric/serialization/ + https://docs.python.org/3/library/pickle.html +""" +# from tkinter.messagebox import NO +from cryptography.exceptions import * +from cryptography.hazmat.primitives.asymmetric import rsa +from cryptography.hazmat.primitives import hashes +from cryptography.hazmat.primitives.asymmetric import padding +from cryptography.hazmat.primitives import serialization +import pickle + +def generate_keys(): + private_key = rsa.generate_private_key(public_exponent=65537,key_size=2048) + public_key = private_key.public_key() + return private_key, public_key + +def encrypt(message, key): + try: + ciphertext = key.encrypt(message, + padding.OAEP( + mgf=padding.MGF1(algorithm=hashes.SHA256()), + algorithm=hashes.SHA256(), + label=None)) + return ciphertext + except: + return False + +def decrypt(ciphertext, key): + try: + plaintext = key.decrypt( + ciphertext, + padding.OAEP( + mgf=padding.MGF1(algorithm=hashes.SHA256()), + algorithm=hashes.SHA256(), + label=None)) + return plaintext + except: + return False + +# TODO 1: Store the list of keys into a given file. +# Make sure of proper PEM encoding before serialization +def save_keys(keys_file_name, keys_list): + keys_ser_list = [] + for item in keys_list: + key_name, private_key, public_key = item + + prv_ser = private_key.private_bytes( + encoding=serialization.Encoding.PEM, + format=serialization.PrivateFormat.TraditionalOpenSSL, + encryption_algorithm=serialization.NoEncryption() + ) + pbc_ser = public_key.public_bytes( + encoding=serialization.Encoding.PEM, + format=serialization.PublicFormat.SubjectPublicKeyInfo + ) + + keys_ser_list.append((key_name, prv_ser, pbc_ser)) + + savefile = open(keys_file_name, "wb") + pickle.dump(keys_ser_list, savefile) + savefile.close() + +# TODO2: Load all private and public keys from a given file and return those keys as a list +# Make sure of proper PEM decoding when deserializing +def load_keys(keys_file_name): + loadfile = open(keys_file_name, "rb") + keys_ser_list = pickle.load(loadfile) + loadfile.close() + + keys_list = [] + for item in keys_ser_list: + key_name, prv_ser, pbc_ser = item + private_key = serialization.load_pem_private_key( + prv_ser, + password=None + ) + public_key = serialization.load_pem_public_key( + pbc_ser + ) + keys_list.append((key_name, private_key, public_key)) + return keys_list diff --git a/period_1/03-cryptography/302_T02_A02_ Asym_KeySaveLoad_1/Asym_t.py b/period_1/03-cryptography/302_T02_A02_ Asym_KeySaveLoad_1/Asym_t.py new file mode 100644 index 0000000..87d579b --- /dev/null +++ b/period_1/03-cryptography/302_T02_A02_ Asym_KeySaveLoad_1/Asym_t.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python3 +""" +This test case will verify if the provided solution by a student for Asym.py is correct. +""" +from Asym import * + +if __name__ == '__main__': + + # Create an empty list + keys_list = [] + + # Generate asymmetric keys for several users + # Save all keys to the list + alex_prv, alex_pbc = generate_keys() + keys_list.append(('alex', alex_prv, alex_pbc)) + + mike_prv, mike_pbc = generate_keys() + keys_list.append(('mike', mike_prv, mike_pbc)) + + rose_prv, rose_pbc = generate_keys() + keys_list.append(('rose', rose_prv, rose_pbc)) + + mara_prv, mara_pbc = generate_keys() + keys_list.append(('mara', mara_prv, mara_pbc)) + + john_prv, john_pbc = generate_keys() + keys_list.append(('john', john_prv, john_pbc)) + + lily_prv, lily_pbc = generate_keys() + keys_list.append(('lily', lily_prv, lily_pbc)) + + # Specify the file name for key storage + keys_file_name = 'samples.keys' + # Save keys to the file + save_keys(keys_file_name, keys_list) + # Load keys + loaded_keys = load_keys(keys_file_name) + + plain_message = b'This is a test message!' + + # Test if a message can be encrypted/decrypted using asymmetric key combination of each user + for item in loaded_keys: + key_name, prv_key, pbc_key = item + ciphertext = encrypt(plain_message, pbc_key) + decrypted_message = decrypt(ciphertext, prv_key) + if decrypted_message == plain_message: + print(f'Success: The message is correctly encrypted and decrypted by {key_name}') + else: + print(f'Fail: The message could not be decrypted by {key_name}') + diff --git a/period_1/03-cryptography/303_T03_A03_ Asym_KeySaveLoad_2_msg_sender/Asym.py b/period_1/03-cryptography/303_T03_A03_ Asym_KeySaveLoad_2_msg_sender/Asym.py new file mode 100644 index 0000000..808be8b --- /dev/null +++ b/period_1/03-cryptography/303_T03_A03_ Asym_KeySaveLoad_2_msg_sender/Asym.py @@ -0,0 +1,104 @@ +#!/usr/bin/env python3 +"""Asymmetric Cryptography -> Message Receive: Tutorial 3 + +The goal of this tutorial is to learn how to read a decrypted message from a file. +In previous tutorial you have learned how to store and load asymmetric keys. +When a user receives a messages it is normally encrypted. +To simplify the implementation we assume the received encrypted message is stored in +a file called *message_test.enc*. Asymmetric keys are stored in the file *samples_test.keys*. + +Your task is to: + * locate the TODOs in this file + * complete the missing part from the code + * run the test of this tutorial located in same folder. + +To test run 'Asym_t.py' in your command line + +Notes: + * do not change class structure or method signature to not break unit tests + * visit this url for more information on this topic: + https://cryptography.io/en/latest/hazmat/primitives/asymmetric/rsa/ +""" +# from tkinter.messagebox import NO +from cryptography.exceptions import * +from cryptography.hazmat.primitives.asymmetric import rsa +from cryptography.hazmat.primitives import hashes +from cryptography.hazmat.primitives.asymmetric import padding +from cryptography.hazmat.primitives import serialization +import pickle + +def generate_keys(): + private_key = rsa.generate_private_key(public_exponent=65537,key_size=2048) + public_key = private_key.public_key() + return private_key, public_key + +def encrypt(message, key): + try: + ciphertext = key.encrypt(message, + padding.OAEP( + mgf=padding.MGF1(algorithm=hashes.SHA256()), + algorithm=hashes.SHA256(), + label=None)) + return ciphertext + except: + return False + +def decrypt(ciphertext, key): + try: + plaintext = key.decrypt( + ciphertext, + padding.OAEP( + mgf=padding.MGF1(algorithm=hashes.SHA256()), + algorithm=hashes.SHA256(), + label=None)) + return plaintext + except: + return False + +def save_keys(keys_file_name, keys_list): + keys_ser_list = [] + for item in keys_list: + key_name, private_key, public_key = item + + prv_ser = private_key.private_bytes( + encoding=serialization.Encoding.PEM, + format=serialization.PrivateFormat.TraditionalOpenSSL, + encryption_algorithm=serialization.NoEncryption() + ) + pbc_ser = public_key.public_bytes( + encoding=serialization.Encoding.PEM, + format=serialization.PublicFormat.SubjectPublicKeyInfo + ) + + keys_ser_list.append((key_name, prv_ser, pbc_ser)) + + savefile = open(keys_file_name, "wb") + pickle.dump(keys_ser_list, savefile) + savefile.close() + +def load_keys(keys_file_name): + loadfile = open(keys_file_name, "rb") + keys_list_ser = pickle.load(loadfile) + loadfile.close() + + keys_list = [] + for item in keys_list_ser: + key_name, private_key_ser, public_key_ser = item + private_key = serialization.load_pem_private_key(private_key_ser,password=None) + public_key = serialization.load_pem_public_key(public_key_ser) + + keys_list.append((key_name, private_key, public_key)) + return keys_list + +# TODO 1: Load message from a given file and return it +# Make sure of passing proper arguments to open a file in read mode +def load_message(file_name): + load_file = open(file_name, "rb") + message_list = pickle.load(load_file) + load_file.close() + + for item in message_list: + message = item + print(message) + + return None diff --git a/period_1/03-cryptography/303_T03_A03_ Asym_KeySaveLoad_2_msg_sender/Asym_t.py b/period_1/03-cryptography/303_T03_A03_ Asym_KeySaveLoad_2_msg_sender/Asym_t.py new file mode 100644 index 0000000..1482051 --- /dev/null +++ b/period_1/03-cryptography/303_T03_A03_ Asym_KeySaveLoad_2_msg_sender/Asym_t.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python3 +""" +This test case will verify if the provided solution by a student for Asym.py is correct. +""" +from Asym import * + +if __name__ == '__main__': + + # Specify file name for key storage + keys_file_name = 'samples_test.keys' + # Specify file name where the encrypted message is located + message_file_name = 'message_test.enc' + + # Load encrypted message from the file + received_message = load_message(message_file_name) + + # Load existing asymmetric keys + loaded_keys = load_keys(keys_file_name) + found = False + # Try to decrypt the loaded message using every existing private key + # Print the result of each decryption attempt + for item in loaded_keys: + key_name, prv_key, _ = item + decrypted_message = decrypt(received_message, prv_key) + if decrypted_message: + print(f'Sucecss: The message is decoded by {key_name}: "{str(decrypted_message,"utf-8")}"') + found = True + if not found: + print('Fail: The message could not be successfully decoded.') + \ No newline at end of file